Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting a folder name from path in Fish Shell

Tags:

fish

I have multiple directories like this

~/project/foo/Debug
~/project/bar/Debug
... and so on

Folders project and Debug are constants.

I am in Debug Directory, foo and bar are the project names. When I am in the ~/project/bar/Debug, is it possible to set a variable to string bar, and when when I am in directory ~/project/xxxxx/Debug set the that variable to xxxxx?

like image 393
user1135541 Avatar asked Jan 04 '23 09:01

user1135541


2 Answers

As faho pointed out in his answer the recently added string builtin can be used for this if efficiency is critical. However, in this case I would probably use the traditional solution for its clarity and simplicity:

set var (basename (dirname $PWD))

If you don't want to pay the cost of two, very cheap, external commands I would do this rather than use a regex:

set components (string split -- / $PWD)
set var $components[-2]

You can even do that in a single statement:

set var (string split -- / $PWD)[-2]
like image 174
Kurtis Rader Avatar answered Feb 11 '23 12:02

Kurtis Rader


The current directory is available via the PWD variable, so you can test that:

set -g string # define variable globally
if test $PWD = ~/project/foo/Debug
     set string foo
else if test $PWD = ~/project/bar/Debug
     set string bar
end

Of course, that will become unwieldy if there's more than three projects, or if the list changes over time, so you can use fish's builtin string tool to perform matching and replacing on it.

set -g string
if string match -q '/projects/*/Debug'
     set string (string replace -r '.*/projects/([^/]+)/Debug' '$1' -- $PWD)
end

I suspect what you really want is to display your project name in place of the working directory in your prompt. If that is so and you use git, you can use this

function prompt_pwd --description 'Print the current working directory, shortened to fit the prompt'
    set -q argv[1]; and switch $argv[1]
        case -h --help
            __fish_print_help prompt_pwd
            return 0
    end

    # This allows overriding fish_prompt_pwd_dir_length from the outside (global or universal) without leaking it
    set -q fish_prompt_pwd_dir_length; or set -l fish_prompt_pwd_dir_length 1

    set -l tmp
    set -l gitdir
    # Replace everything up to the vcs root with [rootname]
    # under the assumption that that is the name of the "project".
    # TODO: On my machine, it seems that the last two components are the safer bet, e.g.
    # kwin/tiling
    # exercism/cli (go)
    # elves/elvish (go)
    # new/exa-git (aur)
    # dev/fish-shell
    #
    # Either that, or a more robust system of abbreviations,
    # a non-hacky solution for which needs dictionaries.
    if set gitdir (git rev-parse --show-toplevel ^/dev/null)
        set tmp (string replace -- $gitdir '' $PWD)
        # Underline the "project name"
        # FIXME: The coloring here will leak, but I can't see a way to just undo underlining.
        set gitdir \[(set_color -u)(string replace -r '.*/' '' -- $gitdir)(set_color normal; set_color $fish_color_cwd)\]
    else
        # Replace $HOME with "~"
        # Only if we're not in a gitdir, otherwise $HOME/dev/$HOME would give weird results.
        set realhome ~
        # FIXME: This will give weird results if any special regex chars are in $HOME,
        # but it should be a regex match because we only want it replaced at the beginning of the string.
        set tmp (string replace -r '^'"$realhome"'($|/)' '~$1' $PWD)
    end
    # The test will return false if $fish_... is non-numerical,
    # and the replace will not replace anything, so the PWD will be unshortened.
    # This is okay.
    if [ $fish_prompt_pwd_dir_length -eq 0 ]
        echo -s $gitdir $tmp
    else
        # Shorten to at most $fish_prompt_pwd_dir_length characters per directory
        # but only after the gitdir
        echo "$gitdir"(string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '$1/' $tmp)
    end
end

which could also be adapted to e.g. mercurial or similar, though in my experience mercurial is rather slow to start and hence not something you want to happen every prompt.

Save it in ~/.config/fish/functions/prompt_pwd.fish.

like image 20
faho Avatar answered Feb 11 '23 11:02

faho