mawww / kakoune

mawww's experiment for a better code editor
http://kakoune.org
The Unlicense
9.95k stars 716 forks source link

[REQUEST] named args expansion #4444

Open TeddyDD opened 2 years ago

TeddyDD commented 2 years ago

Feature

Kakoune uses some kind of internal args parser for -whatever flags in built-in commands. I propose to expose this funtionality to the users.

When kak encounter the following command:

:foo -bar 1 -baz "2 3" -- hello world --
Expansion Content In %sh{}
%arg{@} hello world -- no changes
%arg[1} hello no changes
%arg{2} world no changes
%arg{3} -- no changes
%arg{bar} 1 $kak_arg_bar
%arg{baz} 2 3 $kak_arg_baz
%arg{asdf} error or empty string? not defined?

Named args wouldn't be checked by -params n..m positional parameters count.

Optional: named args detected in command body could be completed automatically.

Usecase

Arguments can be parsed easily in shell. This feature however has two advantages

Quick & dirty example of command using this feature:

define-command -params 1.. go-tests %{
    nop %sh{
        args=""
        if [ -n "$kak_arg_template" ]
        then
            args="$args -template $kak_arg_template"
        fi
        gotests -w "$args" -only "$@" "$kak_buffile"
    }
}

# calls
:go-tests MyFunc
:go-tests -template testify MySecondFunc

You still need if per named option, but there is no need for while/case/shift loop you usually use for parsing flags in shell.

alexherbo2 commented 2 years ago

What should happen with flags (a switch without parameter) or repeated options?

TeddyDD commented 2 years ago

Good question. I can't recall any Kakoune command with repeated option so they could be not supported.

Flags are bigger issue since parser won't be able to infer if flag should have parameter. Perhaps flags should be declared explicitly, not inferred:

define-command -named-args "foo,bar,baz" -flags "toogle1,toogle2" -params 1.. %{ ... }

Alternatively we could require that flags with parameters would have -flag=arg syntax, but that's a lot of changes.

alexherbo2 commented 2 years ago

For reference, Nushell has custom commands with flags. It could be a good inspiration to take.

https://youtu.be/PO6EW7_a1tE?t=506

Screwtapello commented 2 years ago

Following the precedent of things like getopt, and things like range-specs options, you might just have a string:

define-command -named-args anchor=|style=normal|markup|title= -params 1 info %{ ... }

...where:

Assuming the above command definition, if the command were called as:

info -title greetings "hello there"

...then we'd have:

Expansion Value
%arg{anchor} Empty string
%arg{style} normal
%arg{markup} Empty string
%arg{title} greetings
%arg{1} hello there

As an added bonus, it would be a lot easier to make rich completions for commands, since Kakoune would know what switch names are available and what the default value for each one should be. You can do that today, with -shell-script-candidates, but it would be much simpler.

Before (untested):

prev_token=""
i=0
while [ "$i" -lt "$kak_token_to_complete" ]; do
    prev_token=$1
    shift
    i=$(( i + 1 ))
done

case "$prev_token" in
    # Switches where there's no exhaustive list of completions
    -anchor|-title)
        ;;
    # Switches where there is an exhaustive list of completions
    -style)
        printf "%s\n" normal above below menu modal
        ;;
    # After any other token, including -markup, the list of switches
    # is as good a completion as any.
    *)
        printf "%s\n" -anchor -style -markup -title
esac

After:

case "$kak_token_to_complete" in
    style)
        printf "%s\n" normal above below menu modal
        ;;
esac