# Display general usage function __to_usage echo 'Usage:' echo ' to (BOOKMARK|DIR) Go to BOOKMARK or DIR' echo ' to add [BOOKMARK] [DEST] Create a BOOKMARK for DEST' echo ' Default BOOKMARK: name of current directory' echo ' Default DEST: path to current directory' echo ' to add DEST Create a bookmark for DEST if it is a directory' echo ' to ls List all bookmarks' echo ' to mv OLD NEW Change the name of a bookmark from OLD to NEW' echo ' to rm BOOKMARK Remove BOOKMARK' echo ' to clean Remove bookmarks that have a missing destination' echo ' to resolve BOOKMARK Print the destination of a bookmark' echo ' to help Show this message' echo echo "Bookmarks are stored in: $TO_DIR" echo 'To change, run: set -U TO_DIR ' return 1 end # https://github.com/fish-shell/fish-shell/issues/6173#issuecomment-1067114363 function is_empty_dir test -d "$argv" or return 1 # not a directory, so not an empty directory # count counts how many arguments it received # if this glob doesn't match, it won't get arguments # and so it will return 1 # because we *want* an empty directory, turn that around. # the `{.*,*}` ensures it matches hidden files as well. not count $argv/{.*,*} >/dev/null end function __to_dir if test -n "$TO_DIR" echo $TO_DIR return end set -l dir if test -d "$HOME/.tofish" && not is_empty_dir $HOME/.tofish set dir $HOME/.tofish else if test -n "$XDG_DATA_HOME" set dir $XDG_DATA_HOME/to-fish else set dir $HOME/.local/share/to-fish end set -U TO_DIR $dir echo $TO_DIR end function __to_bm_path echo (__to_dir)/$argv end function __to_resolve readlink (__to_bm_path $argv) 2>/dev/null end function __to_print __to_resolve $argv | string replace -r "^$HOME" "~" | string replace -r '^~$' $HOME end function __to_ls for l in (__to_dir)/* basename $l end end function __to_rm command rm -v (__to_bm_path $argv[1]); or return $status __to_update_bookmark_completions end function __to_add -a bm dest # if there are no arguments if test -z "$bm" # use the current directory set dest (pwd) set bm (basename $dest) else # if there are two arguments if test -n "$dest" # use them as bookmark name and destination set dest (realpath $dest) # if there is only one argument else # if the argument is a directory if string match -q '*/*' $bm && test -d "$bm" # use it as the destination set dest (realpath $bm) set bm (basename $dest) else # if not a directory # use it as the bookmark name set dest (pwd) end end end if __to_resolve $bm > /dev/null echo "ERROR: Bookmark exists: $bm -> "(__to_print $bm) >&2 return 1 end if not test -d "$dest" echo "ERROR: Destination does not exist: $dest" >&2 return 1 end if string match -q '*/*' $bm echo "ERROR: Bookmark name cannot contain '/': $bm" >&2 return 1 end switch (uname) case Darwin command ln -s $dest (__to_bm_path $bm); or return $status case '*' command ln -sT $dest (__to_bm_path $bm); or return $status end echo $bm "->" (__to_print $bm) __to_update_bookmark_completions end function __to_complete_directories set -l cl (commandline -ct | string split -m 1 /) set -l bm $cl[1] set -l bmdir (__to_resolve $bm) if test -z "$bmdir" __fish_complete_directories else set -e cl[1] if test -z "$cl" __fish_complete_directories $bmdir/ | string replace -r 'Directory$' $bm else __fish_complete_directories $bmdir/$cl | string replace -r 'Directory$' $bm end end end function __to_update_bookmark_completions complete -e -c to complete -c to -k -x -s h -l help -d 'Show help' # Subcommands complete -c to -k -n '__fish_use_subcommand' -f -a 'help' -d 'Show help' complete -c to -k -n '__fish_use_subcommand' -x -a 'resolve' -d 'Print bookmark destination' complete -c to -k -n '__fish_use_subcommand' -x -a 'clean' -d 'Remove bad bookmarks' complete -c to -k -n '__fish_use_subcommand' -x -a 'mv' -d 'Rename bookmark' complete -c to -k -n '__fish_use_subcommand' -x -a 'rm' -d 'Remove bookmark' complete -c to -k -n '__fish_use_subcommand' -f -a 'ls' -d 'List bookmarks' complete -c to -k -n '__fish_use_subcommand' -x -a 'add' -d 'Create bookmark' # Directories complete -c to -k -n '__fish_use_subcommand' -r -a '(__to_complete_directories)' # Bookmarks for bm in (__to_ls | sort -r) complete -c to -k -n '__fish_use_subcommand; or __fish_seen_subcommand_from rm mv resolve' -r -a (echo $bm | string escape) -d (__to_print $bm) end end function to -d 'Bookmarking tool' set -l dir (__to_dir) # Create tofish directory if not test -d "$dir" if command mkdir $dir echo "Created bookmark directory: $dir" else echo "Failed to Create bookmark directory: $dir" return 1 end end # Catch usage errors set -l cmd $argv[1] set -l numargs (count $argv) switch $cmd # subcommands that don't take an argument case ls help clean if not test $numargs -eq 1 echo "Usage: to $cmd" return 1 end # subcommands that require an argument case rm resolve if not test $numargs -eq 2 echo "Usage: to $cmd BOOKMARK" return 1 end # add has 2 optional arguments case add if not test $numargs -ge 1 -a $numargs -le 3 echo 'Usage: to add [BOOKMARK] [DEST]' echo ' to add DEST' return 1 end # subcommands that require 2 arguments case mv if not test $numargs -eq 3 echo 'Usage: to mv OLD NEW' return 1 end end switch $cmd # Add a bookmark case add __to_add $argv[2..-1] return $status # Remove a bookmark case rm __to_rm $argv[2] return $status # List all bookmarks case ls for bm in (__to_ls) echo "$bm -> "(__to_print $bm) end return 0 # Rename a bookmark case mv set -l old $argv[2] if not __to_resolve $old > /dev/null echo "ERROR: Bookmark not found: $old" return 1 end set -l new $argv[3] __to_add $new (__to_resolve $old); or return $status __to_rm $old; or return $status return 0 # Clean case clean for bm in (__to_ls) if not test -d (__to_resolve $bm) __to_rm $bm end end return 0 # Resolve case resolve __to_resolve $argv[2] return $status # Help case -h --help help __to_usage return 0 # Default case '*' set -l name $argv[1] if test -z "$name" __to_usage return 1 end set -l dest (__to_resolve $name) if test -z "$dest" if test -d "$name" echo "cd \"$name\"" | source - else echo "to: No such bookmark “$name”" >&2 return 1 end else if test -d "$dest" echo "cd \"$dest\"" | source - else echo "to: Destination for bookmark “$name” does not exist: $dest" >&2 return 1 end end end