Skip to content

Commit

Permalink
Merge pull request #7 from pltanton/variables
Browse files Browse the repository at this point in the history
Add initial variabels implementation
  • Loading branch information
pltanton authored Apr 23, 2024
2 parents 1448439 + cd6991d commit f791a97
Show file tree
Hide file tree
Showing 14 changed files with 292 additions and 95 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }} # checkout the correct branch name
fetch-depth: 0

- name: Git Version
id: version
uses: codacy/git-version@2.7.1
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Build and release

on: [push]

jobs:
test-linux:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v25
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
- run: nix build
- run: nix flake check

test-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'macos/go.mod'
cache-dependency-path: 'macos/go.sum'

- name: Build macos
run: make build-macos
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ Automatically choosing web-browser depends on environment context rules.
## Example

```
firefox -p job {}:url.regex='.*jira.*';app.class=Slack # Open all jira links from slack with job firefox profile
firefox 'ext+container:name=Isolated&url={}':app.class=org.telegram.desktop # Open all links from the telegram app using Isolated firefox container
work:=firefox -p job {}:url.regex='.*jira.*'
work;app.class=Slack # Open all jira links from slack with job firefox profile
work:app.class=org.telegram.desktop # Open all links from the telegram app using Isolated firefox container
# Default fallback
firefox {}:fallback
Expand All @@ -36,6 +38,8 @@ Browser command is a sequence of words, divided by spaces. The first word is an

You can escape spaces or other _non-word characters_ can be escaped by a single-quote string.

To avoid repeating of same browser command you can user assignment syntax `command_name:=your command {}` for further use.

## Matchers

### fallback
Expand Down Expand Up @@ -80,6 +84,10 @@ Due to stupidity of Gonme shell interface there is no legal way to recieve focus

To be able to use the `app` matcher, please [install the extenions](https://extensions.gnome.org/extension/5592/focused-window-d-bus/), that exposes currently focused window via dbus interface: https://github.com/flexagoon/focused-window-dbus

### Prebuilt packages

You can find `.rpm`, `.deb`, `.apk` and `.zst` packages on the release page.

### Linux manual

```sh
Expand Down
54 changes: 35 additions & 19 deletions common/pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app

import (
"errors"
"fmt"
"io"
"log/slog"
"os"
Expand All @@ -21,34 +22,49 @@ func SetupAndRun(configPath string, url string, registry *matchers.MatchersRegis

parser := config.NewParser(configFile)

for rule, err := parser.ParseRule(); !errors.Is(err, io.EOF); rule, err = parser.ParseRule() {
if err != nil {
slog.Error("Failed to parse rule", "err", err)
os.Exit(1)
}
variables := make(map[string][]string)

matches, err := registry.EvalRule(rule)
for instruction, err := parser.ParseInstruction(); !errors.Is(err, io.EOF); instruction, err = parser.ParseInstruction() {
if err != nil {
slog.Error("Failed to evaluate rule", "err", err)
slog.Error("Failed to parse instruction", "err", err)
os.Exit(1)
}

if matches {
// Replace all placeholders in command to url
command := rule.Command
for i := range command {
command[i] = strings.Replace(command[i], "{}", url, 1)
if assignment, ok := instruction.Assignment(); ok {
variables[assignment.Key] = assignment.Value
} else if rule, ok := instruction.Rule(); ok {
matches, err := registry.EvalRule(rule)
if err != nil {
slog.Error("Failed to evaluate rule", "err", err)
os.Exit(1)
}

cmd := exec.Command(command[0], command[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
if matches {
// Replace all placeholders in command to url
command := rule.Command
// Try find command in variables if it's single word command
if len(command) == 1 {
if newCommand, ok := variables[command[0]]; ok {
command = newCommand
}
}

if err := cmd.Run(); err != nil {
slog.Error("Failed to run command", "err", err)
os.Exit(1)
for i := range command {
command[i] = strings.Replace(command[i], "{}", url, 1)
}

cmd := exec.Command(command[0], command[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout

if err := cmd.Run(); err != nil {
slog.Error("Failed to run command", "err", err)
os.Exit(1)
}
return
}
return
} else {
slog.Error(fmt.Sprintf("Unknown instruction type %+v", instruction))
}
}

Expand Down
22 changes: 15 additions & 7 deletions common/pkg/config/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ const (
EOF

EQ
ASSIGN
DOT
COMMA
COLON
SEMICOLON
VALUE
WORD
SPACE
COMMENT
ENDL
Expand All @@ -37,6 +38,8 @@ func (t TokenType) String() string {
return "EOF"
case EQ:
return "EQ"
case ASSIGN:
return "ASSIGN"
case DOT:
return "DOT"
case COMMA:
Expand All @@ -45,8 +48,8 @@ func (t TokenType) String() string {
return "COLON"
case SEMICOLON:
return "SEMICOLON"
case VALUE:
return "VALUE"
case WORD:
return "WORD"
case SPACE:
return "SPACE"
case ENDL:
Expand Down Expand Up @@ -96,12 +99,17 @@ func (l *Lexer) Next() Token {
case '#':
l.unreadRune()
return l.scanComment()
case ':':
if l.readRune() == '=' {
return Token{ASSIGN, ":="}
} else {
l.unreadRune()
return Token{COLON, string(r)}
}
case '=':
return Token{EQ, string(r)}
case '.':
return Token{DOT, string(r)}
case ':':
return Token{COLON, string(r)}
case ';':
return Token{SEMICOLON, string(r)}
case ',':
Expand Down Expand Up @@ -161,7 +169,7 @@ func (l *Lexer) scanWhitespaces() Token {
}

func (l *Lexer) scanValue() Token {
return l.scanCharclassSequence(VALUE, ValueClass)
return l.scanCharclassSequence(WORD, ValueClass)
}

func (l *Lexer) scanEscapedValue() Token {
Expand All @@ -182,7 +190,7 @@ func (l *Lexer) scanEscapedValue() Token {
}

return Token{
Type: VALUE,
Type: WORD,
Value: buf.String(),
}
}
Expand Down
44 changes: 28 additions & 16 deletions common/pkg/config/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ func TestLexer_Next(t *testing.T) {
want: Token{DOT, "."},
},
{
name: "Lex value",
inStr: "here_is-va1ue",
want: Token{VALUE, "here_is-va1ue"},
name: "Lex word",
inStr: "here_is-va1ue{}",
want: Token{WORD, "here_is-va1ue{}"},
},
{
name: "Lex escaped value",
inStr: "'here.is,escaped=value\t*** () ?? {} <> 💀'",
want: Token{VALUE, "here.is,escaped=value\t*** () ?? {} <> 💀"},
want: Token{WORD, "here.is,escaped=value\t*** () ?? {} <> 💀"},
},
{
name: "Lex comma",
Expand Down Expand Up @@ -63,12 +63,16 @@ func TestLexer_Next(t *testing.T) {
inStr: "\n",
want: Token{ENDL, "\n"},
},

{
name: "Lex comment",
inStr: "# Hello.={} ;:",
want: Token{COMMENT, "# Hello.={} ;:"},
},
{
name: "Lex assign",
inStr: ":=",
want: Token{ASSIGN, ":="},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -85,37 +89,45 @@ func TestLexer_Next(t *testing.T) {

func TestLexer_FullSequence(t *testing.T) {
input := `
foo:=bar biz
firefox:url.regex='.*foo.*';app.class=telegram # Commentary with row description
'firefox -p work':url.host='github.com'`

expected := []Token{
{ENDL, "\n"},

{VALUE, "firefox"},
{WORD, "foo"},
{ASSIGN, ":="},
{WORD, "bar"},
{SPACE, " "},
{WORD, "biz"},
{ENDL, "\n"},

{WORD, "firefox"},
{COLON, ":"},
{VALUE, "url"},
{WORD, "url"},
{DOT, "."},
{VALUE, "regex"},
{WORD, "regex"},
{EQ, "="},
{VALUE, ".*foo.*"},
{WORD, ".*foo.*"},
{SEMICOLON, ";"},
{VALUE, "app"},
{WORD, "app"},
{DOT, "."},
{VALUE, "class"},
{WORD, "class"},
{EQ, "="},
{VALUE, "telegram"},
{WORD, "telegram"},

{SPACE, " "},
{COMMENT, "# Commentary with row description"},
{ENDL, "\n"},

{VALUE, "firefox -p work"},
{WORD, "firefox -p work"},
{COLON, ":"},
{VALUE, "url"},
{WORD, "url"},
{DOT, "."},
{VALUE, "host"},
{WORD, "host"},
{EQ, "="},
{VALUE, "github.com"},
{WORD, "github.com"},
}

l := &Lexer{
Expand Down
Loading

0 comments on commit f791a97

Please sign in to comment.