Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add extra_args #43

Merged
merged 2 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ allow_concurrent_presets = false
kanata_executable = '~/bin/kanata' # if empty or omitted, system $PATH will be searched.
kanata_config = '' # if empty or not omitted, kanata default config locations will be used.
tcp_port = 5829 # if not specified, defaults to 5829
extra_args = ['-n', '-c=~/.config/kanata/another.kbd']

[defaults.hooks]
# Hooks allow running custom commands on specific events (e.g. starting preset).
Expand All @@ -64,6 +65,7 @@ autorun = true
# kanata_executable = ''
# layer_icons = { }
# tcp_port = 1234
# extra_args = ['-n', '-c=~/.config/kanata/another.kbd']

[presets.'test cfg']
kanata_config = '~/.config/kanata/test.kbd'
Expand All @@ -72,7 +74,7 @@ kanata_config = '~/.config/kanata/test.kbd'
### Explanation

`presets` - a config item, that adds an entry to tray menu. Each preset can have different settings for running kanata with:
`kanata_config`, `kanata_executable`, `autorun`, `layer_icons`, `tcp_port`.
`kanata_config`, `kanata_executable`, `autorun`, `layer_icons`, `tcp_port`, `extra_args`.

`preset.autorun` - when set to true, preset will run at kanata-tray startup.

Expand All @@ -86,7 +88,7 @@ When disabled, switching presets will stop currently running preset (if any).
Disabled by default.

Other notes:
- You can use `~` in `kanata_config` and `kanata_executable` to substitute to your "home" directory.
- You can use `~` in `kanata_config`, `kanata_executable` and `extra_args` to substitute to your "home" directory.
- On Windows: make sure to surround paths with single-quotes `'` instead of double-quotes, otherwise paths will not work (because `\` would be treated as escape character).

### Hooks
Expand Down
15 changes: 10 additions & 5 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ type SystrayApp struct {
}

func NewSystrayApp(menuTemplate []PresetMenuEntry, layerIcons LayerIcons, allowConcurrentPresets bool, logFilepath string) *SystrayApp {

systray.SetIcon(icons.Default)
systray.SetTooltip("kanata-tray")

Expand Down Expand Up @@ -104,10 +103,16 @@ func (t *SystrayApp) runPreset(presetIndex int, runner *runner_pkg.Runner) {
log.Infof("Running preset '%s'", t.presets[presetIndex].PresetName)

t.setStatus(presetIndex, statusStarting)
kanataExecutable := t.presets[presetIndex].Preset.KanataExecutable
kanataConfig := t.presets[presetIndex].Preset.KanataConfig
ctx, cancel := context.WithCancel(context.Background())
err := runner.Run(ctx, t.presets[presetIndex].PresetName, kanataExecutable, kanataConfig, t.presets[presetIndex].Preset.TcpPort, t.presets[presetIndex].Preset.Hooks)
err := runner.Run(
ctx,
t.presets[presetIndex].PresetName,
t.presets[presetIndex].Preset.KanataExecutable,
t.presets[presetIndex].Preset.KanataConfig,
t.presets[presetIndex].Preset.TcpPort,
t.presets[presetIndex].Preset.Hooks,
t.presets[presetIndex].Preset.ExtraArgs,
)
if err != nil {
log.Errorf("runner.Run failed with: %v", err)
t.setStatus(presetIndex, statusCrashed)
Expand Down Expand Up @@ -284,7 +289,7 @@ func (t *SystrayApp) setIcon(iconBytes []byte) {
func multipleMenuItemsClickListener(menuItems []*systray.MenuItem) chan int {
ch := make(chan int)
for i := range menuItems {
var i = i
i := i
go func() {
for range menuItems[i].ClickedCh {
ch <- i
Expand Down
6 changes: 6 additions & 0 deletions app/menu_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ func MenuTemplateFromConfig(cfg config.Config) ([]PresetMenuEntry, error) {
if err != nil {
return nil, err
}
for i, arg := range preset.ExtraArgs {
preset.ExtraArgs[i], err = expandHomeDir(arg)
if err != nil {
return nil, err
}
}

entry := PresetMenuEntry{
IsSelectable: true,
Expand Down
27 changes: 24 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import (
"os"
"strings"

"github.com/labstack/gommon/log"

"github.com/elliotchance/orderedmap/v2"
"github.com/k0kubun/pp/v3"
"github.com/kr/pretty"
"github.com/labstack/gommon/log"
"github.com/pelletier/go-toml/v2"
tomlu "github.com/pelletier/go-toml/v2/unstable"
)
Expand Down Expand Up @@ -49,6 +48,7 @@ type Preset struct {
TcpPort int
LayerIcons map[string]string
Hooks Hooks
ExtraArgs []string
}

func (m *Preset) GoString() string {
Expand Down Expand Up @@ -84,6 +84,7 @@ type preset struct {
TcpPort *int `toml:"tcp_port"`
LayerIcons map[string]string `toml:"layer_icons"`
Hooks *hooks `toml:"hooks"`
ExtraArgs extraArgs `toml:"extra_args"`
}

func (p *preset) applyDefaults(defaults *preset) {
Expand All @@ -107,6 +108,9 @@ func (p *preset) applyDefaults(defaults *preset) {
if p.Hooks == nil {
p.Hooks = defaults.Hooks
}
if p.ExtraArgs == nil {
p.ExtraArgs = defaults.ExtraArgs
}
}

func (p *preset) intoExported() (*Preset, error) {
Expand All @@ -133,6 +137,13 @@ func (p *preset) intoExported() (*Preset, error) {
}
result.Hooks = *x
}
if p.ExtraArgs != nil {
x, err := p.ExtraArgs.intoExported()
if err != nil {
return nil, err
}
result.ExtraArgs = x
}
return result, nil
}

Expand Down Expand Up @@ -169,6 +180,17 @@ func (p *hooks) intoExported() (*Hooks, error) {
}, nil
}

type extraArgs []string

func (e extraArgs) intoExported() ([]string, error) {
for _, s := range e {
if strings.HasPrefix(s, "--port") || strings.HasPrefix(s, "-p") {
return nil, fmt.Errorf("port argument is not allowed in extra_args, use tcp_port instead")
}
}
return e, nil
}

func ReadConfigOrCreateIfNotExist(configFilePath string) (*Config, error) {
var cfg *config = &config{}
// Golang map don't keep track of insertion order, so we need to get the
Expand Down Expand Up @@ -274,7 +296,6 @@ func layersOrder(cfgContent []byte) ([]string, error) {
}

return layerNamesInOrder, nil

}

// helper to transfor a key iterator to a slice of strings
Expand Down
9 changes: 8 additions & 1 deletion doc/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@
}
},
"description": "Allows running additional scripts/programs on specific events."
},
"extra_args": {
"type": "array",
"items": {
"type": "string"
},
"description": "You may pass extra arguments to kanata except for the port (use tcp_port instead), such as --nodelay, additional --cfg params, etc."
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -96,4 +103,4 @@
}
},
"additionalProperties": false
}
}
7 changes: 4 additions & 3 deletions runner/kanata/kanata.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func NewKanataInstance() *Kanata {
}
}

func (r *Kanata) RunNonblocking(ctx context.Context, kanataExecutable string, kanataConfig string, tcpPort int, hooks config.Hooks) error {
func (r *Kanata) RunNonblocking(ctx context.Context, kanataExecutable string, kanataConfig string, tcpPort int, hooks config.Hooks, extraArgs []string) error {
if kanataExecutable == "" {
var err error
kanataExecutable, err = exec.LookPath("kanata")
Expand All @@ -55,7 +55,8 @@ func (r *Kanata) RunNonblocking(ctx context.Context, kanataExecutable string, ka
cfgArg = "-c=" + kanataConfig
}

cmd := cmd(ctx, kanataExecutable, cfgArg, "--port", fmt.Sprint(tcpPort))
args := append([]string{cfgArg, "--port", fmt.Sprint(tcpPort)}, extraArgs...)
cmd := cmd(ctx, kanataExecutable, args...)

go func() {
selfCtx, selfCancel := context.WithCancelCause(ctx)
Expand Down Expand Up @@ -234,7 +235,7 @@ func runAllBlockingHooks(hooks [][]string, hookName string) error {
defer cancel()
wg := sync.WaitGroup{}
wg.Add(len(hooks))
var errors = make([]error, len(hooks))
errors := make([]error, len(hooks))
for i, hook := range hooks {
log.Infof("Running %s hook [%d] '%s'", hookName, i, hook)
i := i // fix race condition
Expand Down
4 changes: 2 additions & 2 deletions runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func NewRunner() *Runner {
// Calling Run when there's a previous preset running with the the same
// presetName will block until the previous process finishes.
// To stop running preset, caller needs to cancel ctx.
func (r *Runner) Run(ctx context.Context, presetName string, kanataExecutable string, kanataConfig string, tcpPort int, hooks config.Hooks) error {
func (r *Runner) Run(ctx context.Context, presetName string, kanataExecutable string, kanataConfig string, tcpPort int, hooks config.Hooks, extraArgs []string) error {
r.instancesMappingLock.Lock()
defer r.instancesMappingLock.Unlock()

Expand Down Expand Up @@ -90,7 +90,7 @@ func (r *Runner) Run(ctx context.Context, presetName string, kanataExecutable st
}

instance := r.kanataInstancePool[instanceIndex]
err := instance.RunNonblocking(ctx, kanataExecutable, kanataConfig, tcpPort, hooks)
err := instance.RunNonblocking(ctx, kanataExecutable, kanataConfig, tcpPort, hooks, extraArgs)
if err != nil {
return fmt.Errorf("failed to run kanata: %v", err)
}
Expand Down
Loading