Search code examples
fish

Fish shell: flip a boolean value


Am I going crazy? I want to flip a boolean variable. I came up with this:

function toggle_light_colorscheme
  if eval $LIGHT_COLORSCHEME
    set -U LIGHT_COLORSCHEME false
  else
    set -U LIGHT_COLORSCHEME true
  end
end

Does fish even have booleans? I suspect not. But it has false and true commands, I can man them. Anyway, I might not need a boolean. All I want to do is to have a global variable which, when set, would mean that I'm using a light color scheme in fish and vim. If it's not set I'm using the dark one. There has to be a simpler way of doing this, I wanted something like:

set -U LIGHT_COLORSCHEME (not $LIGHT_COLORSCHEME)

Solution

  • Does fish even have booleans?

    No. In fact it doesn't really have types at all, like the POSIX shells that it is inspired by. Every variable is a list of strings.

    But it has false and true commands

    Yes. These commands return 1 and 0, respectively. Any return status != 0 is taken to be an error code and therefore false, and 0 is true (in this respect it's the inverse of C).

    All I want to do is to have a global variable which, when set, would mean that I'm using a light color scheme in fish and vim. If it's not set I'm using the dark one.

    Sure, that can be made to work. There's a few different ways to go about this. Either you use the fact that the variable has an element as signifying that it is true, or you use that it is e.g. 1.

    The former would work like

    # Check if variable is "true" by checking if it has an element
    if set -q LIGHT_COLORSCHEME[1]
    # ...
    # Flip the variable
    set -q LIGHT_COLORSCHEME[1]; and set -e LIGHT_COLORSCHEME[1]; or set LIGHT_COLORSCHEME 1
    

    (of course you could also make a "flip" function - unfortunately "not" is a keyword that operates on command return statuses, not variable values)

    The latter would look like

    if test "$LIGHT_COLORSCHEME" = 1 # the "=" here tests string-equality, but that shouldn't matter.
    # ...
    # Flip the variable
    test "$LIGHT_COLORSCHEME" = 1; and set LIGHT_COLORSCHEME 0; or set LIGHT_COLORSCHEME 1
    

    I came up with this:

    function toggle_light_colorscheme if eval $LIGHT_COLORSCHEME

    You have misunderstood what eval does. It runs its arguments as code. I.e. it'll try to execute the value of LIGHT_COLORSCHEME as a command. So if you have a command called "1" somewhere in $PATH, it'll run that!

    To test conditions, use test.