# Branching on a boolean option -- without calling the shell

**URL:** <https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929>\
**Category:** Recipes & Guides\
**Created:** [March 23, 2020, 2:00pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929 "2020-03-23T14:00:31Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ftonneau](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/ftonneau/32/295_2.png) [@ftonneau](https://discuss.kakoune.com/u/ftonneau)\
**Post date:** [March 23, 2020, 2:00pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/1 "2020-03-23T14:00:32Z")

</div>

In Kakoune scripts, branching on the value of a boolean option, `myvar`, may be done by calling the shell inside a `try ... catch` construction:

```
try %{
    evaluate-commands %sh{
        if ["$kak_opt_myvar" = false]; then
            printf %s\\n fail
        fi
    }
    commands_1
} \
catch %{
    commands_2
}

```

which looks bloated and contorted to me. (One could use a wrapper to make the code look simpler, but then the wrapper needs to be defined elsewhere.)

Recently I have been using a trick to avoid calling the shell and inflating the code. The trick is to change the type of the `myvar` option to `str` instead of boolean, setting `myvar` to `nop` when I want it to be true and to `nay` when I want it to be false.

Now the branching looks like this:

```
try %{
    eval %opt(myvar)
    commands_1
} \
catch %{
    commands_2
}

```

This is Kakoune’s eval, not the shell’s. When `myvar` is “true”, `eval %opt(myvar)` goes through and we execute `commands_1`. When `myvar` is “false”, `eval %opt(myvar)` fails (because there is no such command as nay) and we execute `commands_2`.

But perhaps most of you, professional coders, are already using this sort of hack? In any case, I like the look of the resulting code. You are free to decide whether this is more clever than stupid or vice-versa 🙂!

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [March 23, 2020, 5:59pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/2 "2020-03-23T17:59:55Z")

</div>

> [@ftonneau](#):
>
> But perhaps most of you, professional coders, are already using this sort of hack? In any case, I like the look of the resulting code. You are free to decide whether this is more clever than stupid or vice-versa 🙂!

No, at leas I’m not thought about it! Nice trick!

I was using this custom command:

```auto
require-module kak
add-highlighter shared/kakrc/code/if_else regex \b(if|else)\b 0:keyword

define-command -docstring "if <condition> <expression> [else [if <condition>] <expression>]: if statement that accepts shell-valid condition string" \
if -params 2.. %{ evaluate-commands %sh{
    while [true]; do
        condition="[$1]"
        if [-n "$3"] && ["$3" != "else"]; then
            printf "%s\n" "fail %{if: unknown operator '$3'}"
        elif [$# -eq 3]; then
            printf "%s\n" "fail %{if: wrong argument count}"
        elif eval $condition; then
            [-n "${2##*&*}"] && arg="$2" || arg="$(printf '%s' "$2" | sed 's/&/&&/g')"
            printf "%s\n" "evaluate-commands %& $arg &"
        elif [$# -eq 4]; then
            [-n "${4##*&*}"] && arg="$4" || arg="$(printf '%s' "$4" | sed 's/&/&&/g')"
            printf "%s\n" "evaluate-commands %& $arg &"
        elif [$# -gt 4]; then
            if ["$4" = "if"]; then
                shift 4
                continue
            else
                printf "%s\n" "fail %{if: wrong argument count}"
            fi
        fi
        exit
    done
}}

```

That allows me to chain `if` `else` `if` … `else` blocks as in C-like languages, but I mostly use it for single `if else`, like this, to branch my configuration depending on where I run Kakoune:

```auto
plug "andreyorst/base16-gruvbox.kak" domain gitlab.com theme %{
    if %[-n "${PATH##*termux*}"] %{
        colorscheme base16-gruvbox-dark-soft
    } else %{
        colorscheme base16-gruvbox-dark-hard
    }
}

```

The problem is that I mostly want to use shell conditionals as those are far more versatile compared to Kakoune ones, but your example can be used to make some code that uses `try` `catch` approach more appealing. I wonder if this can be turned into function, as in my example

---

<div class="post-metadata">

**Author:** ![ftonneau](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/ftonneau/32/295_2.png) [@ftonneau](https://discuss.kakoune.com/u/ftonneau)\
**Post date:** [March 23, 2020, 11:42pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/3 "2020-03-23T23:42:12Z")

</div>

I forgot to say that a similar trick can be used to define a procedure (= command) with two variants. Instead of declaring two different commands, declare a single command along these lines:

```
define-command -params 1 my-procedure %{
    try %{
       eval %arg(1)
       commands_1
    } \
    catch %{
        commands_2
    }
    shared_commands ...
}

```

Calling the procedure with either `nop` or `nay` as an argument value will execute one variant or the other.

---

<div class="post-metadata">

**Author:** ![occivink](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/occivink/32/27_2.png) [@occivink](https://discuss.kakoune.com/u/occivink)\
**Post date:** [March 24, 2020, 10:57pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/4 "2020-03-24T22:57:17Z")

</div>

One thing that I don’t get with your trick is how do you set the option to the desired value, don’t you need a branch at that point? Let’s say, how would you check if your current selection is 5 characters long?

---

<div class="post-metadata">

**Author:** ![ftonneau](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/ftonneau/32/295_2.png) [@ftonneau](https://discuss.kakoune.com/u/ftonneau)\
**Post date:** [March 24, 2020, 11:37pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/5 "2020-03-24T23:37:12Z")

</div>

> [@occivink](#):
>
> One thing that I don’t get with your trick is how do you set the option to the desired value, don’t you need a branch at that point?

Not necessarily. Setting the option to “true” or “false” (nop or nay) may be done in a separate command that you may call during your editing session (e.g., “do you want the script to use feature X [yes|no]?”). The option-setting command may also be called by a hook that fires when opening a buffer of a specific filetype.

Even when setting the option to “true” or “false” requires a branch, this branch (A) may occur earlier in the script, in a part separate from the later branch or command (B). For example, you may set the option to “nop” or “nay” depending on the result of an `<a-k>...` test done on the current selection. Then you may need to call other commands before finally calling (B) with the value of the previously set option.

Of course, my trick is superflous if you just need to do some test and execute some action immediately, depending on the result of the test. The trick is useful only when option-setting is done separately from the final branch – and especially useful if several procedures depend on the previously set option at different points in time.

---

<div class="post-metadata">

**Author:** ![danr](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/danr/32/700_2.png) [@danr](https://discuss.kakoune.com/u/danr)\
**Post date:** [March 26, 2020, 2:28pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/6 "2020-03-26T14:28:00Z")

</div>

Nice trick, hadn’t thought of this!

You can allow the variable to have the value `true` and `false` by defining `true`:

```auto
def true nop

```

Now `eval true` does not fail, as desired.

---

<div class="post-metadata">

**Author:** ![FlyingWombat](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/flyingwombat/32/120_2.png) [@FlyingWombat](https://discuss.kakoune.com/u/FlyingWombat)\
**Post date:** [March 31, 2020, 6:11pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/7 "2020-03-31T18:11:45Z")

</div>

Nice! I’ve done something similar with setting option values as commands and running `eval` on the option.

With how many posts of this sort that have popped up, I’m becoming more and more convinced that [conditional control flow](https://github.com/mawww/kakoune/issues/2777) should be properly included in kakscript. Though, I guess the percentage of kak files that use things like this is still pretty small.

That or, once [mrsh](https://mrsh.sh/) is ready, have a compile option to integrate the shell into Kakoune itself.

---

<div class="post-metadata">

**Author:** ![evanrelf](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/evanrelf/32/474_2.png) [@evanrelf](https://discuss.kakoune.com/u/evanrelf)\
**Post date:** [April 2, 2020, 3:07am UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/8 "2020-04-02T03:07:16Z")

</div>

Normal user configs probably don’t need conditionals very often, but a ton of plugins _depend_ on conditionals. Adding it to kakscript would be a nice quality of life improvement, and could improve performance as well.

---

<div class="post-metadata">

**Author:** ![SeerLite](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/seerlite/32/1152_2.png) [@SeerLite](https://discuss.kakoune.com/u/SeerLite)\
**Post date:** [October 29, 2020, 9:46pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/9 "2020-10-29T21:46:42Z")

</div>

Checking if an `int` is a specific value without shell:

```auto
def check-0-0 nop
try %{
	eval "check-0-%opt{indentwidth}"
	echo "indentwidth is 0"
} catch %{
	echo "indentwidth is different from/greater than 0"
}

```

I know a few plugins that could benefit from this.

---

<div class="post-metadata">

**Author:** ![alexherbo2](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/alexherbo2/32/1140_2.png) [@alexherbo2](https://discuss.kakoune.com/u/alexherbo2)\
**Post date:** [October 29, 2020, 10:44pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/10 "2020-10-29T22:44:32Z")

</div>

Kakoune primarily operates on buffers, so you can use a scratch buffer.

```auto
edit -scratch
set-register '"' %opt{my_option}
execute-keys R
set-register / my-regex
execute-keys <a-k> <ret>

```

It is nice, but a bit verbose, and ultimately, we do not care about the buffer thing.

In a recent version of Kakoune, @mawww introduced user hooks, allowing us to create our own hooks. As a bonus, we can leverage branching without opening a shell or a scratch buffer.

```auto
define-command if -params 3 -docstring 'if <value> <regex> <commands>' %{
  hook -group if global User %arg{2} %arg{3}
  trigger-user-hook %arg{1}
  remove-hooks global if
}

```

**Example**

```auto
if %opt{my_plugin_enabled} true %{
  echo Tchou!
}

```

I realized and used this trick in [snippets.kak](https://github.com/alexherbo2/snippets.kak).

---

<div class="post-metadata">

**Author:** ![ftonneau](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/ftonneau/32/295_2.png) [@ftonneau](https://discuss.kakoune.com/u/ftonneau)\
**Post date:** [October 29, 2020, 10:44pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/11 "2020-10-29T22:44:51Z")

</div>

I assume one could also test for string equality: check-value-%opt{…}

---

<div class="post-metadata">

**Author:** ![danr](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/danr/32/700_2.png) [@danr](https://discuss.kakoune.com/u/danr)\
**Post date:** [March 19, 2021, 10:15am UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/12 "2021-03-19T10:15:46Z")

</div>

I thought about this too but isn’t it so that the program flow will be “incorrect”?

```auto
if %opt{my_plugin_enabled} true %{
  echo Tchou!
}
echo Ouch!

```

This will output:

```auto
Ouch!
Tchou!

```

Which is reversed from what you would expect from an `if`.

---

<div class="post-metadata">

**Author:** ![alexherbo2](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/alexherbo2/32/1140_2.png) [@alexherbo2](https://discuss.kakoune.com/u/alexherbo2)\
**Post date:** [March 19, 2021, 10:26am UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/13 "2021-03-19T10:26:43Z")

</div>

I haven’t thought about it, it’s a good catch. 👍

---

<div class="post-metadata">

**Author:** ![prion](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/prion/32/404_2.png) [@prion](https://discuss.kakoune.com/u/prion)\
**Post date:** [June 19, 2021, 4:37am UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/14 "2021-06-19T04:37:05Z")

</div>

A slight variant I used today when writing a prompt command because I wanted different behaviour when `%val{text}` was empty.

```auto
define-command if-empty -params 2 %{
    try %{
        eval "nop%arg{1}"
        eval %arg{2}
    }
}

define-command if-not-empty -params 2 %{
    try %{
        eval "nop%arg{1}"
    } catch %arg{2}
}

```

Here’s the usage in a case insensitive select command. Without it you end up selecting everything when the prompty is empty. I included the entire snippet in case anyone wants to use this but fair warning, it segfaults on the last official release, works fine if you build from latest master.

```auto
declare-option str-list nocase_initial_selections
define-command -hidden nocase-restore %{
    select %opt{nocase_initial_selections}
}
define-command nocase-select %{
    set-option window nocase_initial_selections %val{selections_desc}
    prompt -on-abort nocase-restore -on-change nocase-select-impl select: nop
}
define-command -hidden nocase-select-impl %{
    select %opt{nocase_initial_selections}
    if-not-empty %val{text} %{
        try %{ exec <esc> s '(?i)' %val{text} <ret> }
        prompt -on-abort nocase-restore -on-change nocase-select-impl -init "%val{text}" select: nop
    }
}

```

be careful not to search for `;q!` though. this method has a few unfourtunate edge cases now that I think about it…

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [June 23, 2021, 9:17pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/15 "2021-06-23T21:17:51Z")

</div>

Here’s the lambda calculus approach:

```auto
define-command true -params 2 %{ eval %arg{1} }
define-command false -params 2 %{ eval %arg{2} }
define-command if -params 3 %{ eval -verbatim %arg{1} %arg{2} %arg{3} }

if true %{echo -debug 1} %{echo -debug 2}

if false %{echo -debug 1} %{echo -debug 2}

```

Turns out you can define `true` and `false` as functions in kakscript.

`true` is a function that takes two braches, and executes the first  
`false` is a function that takes two branches, and executes the seconf

`if` is a function that takes thre arguments, first is `truef` or `falsef` and the branches. It then passes the branches to the test function, which chooses the branch.

I gave it a bit of testing and it seems to work for complex branches.

You can use `%sh{}` as a test as a bonus:

```auto
if %sh{ ["a" = "b"] && echo true || echo false } %{
    echo -debug "that's true"
} %{
    echo -debug "that's false"
}

```

This prints `that's false` in the debug buffer.

Single branches can be acheived with `when` and `unless`:

```auto
define-command when -params 3 %{ eval -verbatim %arg{1} %arg{2} nop }
define-command unless -params 3 %{ eval -verbatim %arg{1} nop %arg{2} }

```

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [June 26, 2021, 11:05am UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/16 "2021-06-26T11:05:54Z")

</div>

I am now convinced that this is the answer to this problem. I’ve did a bit more testing, and it works really well

---

<div class="post-metadata">

**Author:** ![almr](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/almr/32/934_2.png) [@almr](https://discuss.kakoune.com/u/almr)\
**Post date:** [June 29, 2021, 10:42am UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/17 "2021-06-29T10:42:14Z")

</div>

Yeah, this is probably the right approach. The only thing that concerns me here is the `eval`, because I don’t fully understand it. If there’s an `eval`, there must be always be a related `escape`.

For `sh`, eval-escaping is simple: apostrophe-escape all strings (`' -> '\''` then surround). What is the equivalent escaping rule for `kakscript`'s eval? And can it be done programatically without `%sh`?

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [June 29, 2021, 5:37pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/18 "2021-06-29T17:37:52Z")

</div>

TBH I don’t understand it either. I really wanted for it to work, so perhaps that’s why it works 😃

@occivink suggested to use `--verbatim` escaping to be more portable, but I’m not expert here, and I don’t know why `--verbatim` is needed in `if` but is not needed in `true` or `false` for example, and adding it there breaks stuff.

However note, that Kakoune’s `eval` has nothing to do with shell’s `eval`. It’s just a short way of writing `evaluate-commands`. So maybe escaping with `--verbatim` once is sufficient.

---

<div class="post-metadata">

**Author:** ![almr](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/almr/32/934_2.png) [@almr](https://discuss.kakoune.com/u/almr)\
**Post date:** [June 29, 2021, 6:19pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/19 "2021-06-29T18:19:09Z")

</div>

Try this:

```auto
def -override -params .. echo-args %{ nop -- %sh{
  env printf '- |%s|\n' "$@" 1>&2
}}
def -override -params .. eval-echo-args %{
  eval echo-args %arg{@}
}

eval echo-args '''a ''''b'''
echo-args 'a ''b'

```

It’s the only way I got them to match. IOW, if you want `eval ...` to have the same effect as `...`, each argument must be surrounded in triple quotes, and inside the surround each quote must be quadrupled.

Can this escaping be done in pure kakscript, no `sh`? Can I define a command that takes a list of arguments and recursively builds up a string with those rules? Because if I could, a lot of things become possible by switching to continuation-passing style.

---

<div class="post-metadata">

**Author:** ![andreyorst](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/andreyorst/32/29_2.png) [@andreyorst](https://discuss.kakoune.com/u/andreyorst)\
**Post date:** [June 29, 2021, 6:34pm UTC](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/20 "2021-06-29T18:34:05Z")

</div>

I don’t qute understand why this is needed? You provide balanced strings to `if` which are `eval`ed by kakoune, without shell (`%{this is a string}`), so those are already escaped by you. This escaping is preserved with `--verbatim`, as far as I understand this.

I’ve ported my configuration to use this `if` instead of my previous implementation [Branching on a boolean option -- without calling the shell - #2 by andreyorst](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929/2), and it works without need to escape anything.

[Next page](https://discuss.kakoune.com/t/branching-on-a-boolean-option-without-calling-the-shell/929.md?page=2)
