Last active
July 5, 2018 19:55
-
-
Save pwwang/5ad96bbfb034a91af851c411f0b12a23 to your computer and use it in GitHub Desktop.
Fish cd with symbolic path kept.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# for prevd and nextd, cd - | |
function __fish_move_last -d "Move the last element of a directory history from src to dest" | |
set -l src $argv[1] | |
set -l dest $argv[2] | |
set -l size_src (count $$src) | |
if test $size_src = 0 | |
# Cannot make this step | |
printf (_ "Hit end of history…\n") | |
return 1 | |
end | |
# Append current dir to the end of the destination | |
set -g (echo $dest) $$dest $PWD2 | |
set ssrc $$src | |
# Change dir to the last entry in the source dir-hist | |
builtin cd $ssrc[$size_src] | |
set PWD2 $ssrc[$size_src] | |
# Keep all but the last from the source dir-hist | |
set -e (echo $src)\[$size_src] | |
# All ok, return success | |
return 0 | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function __is_parent -S -a path1 path2 -d 'Tell if path1 is the parent of path2 directly' | |
# /home/user = /home/user | |
if test "$path1" = "$path2" | |
echo -n 'yes' | |
return | |
end | |
# /home/user /home/user/a/b | |
set -l len1 (string length "$path1/") | |
if test (string sub -s 1 -l $len1 "$path2") = "$path1/" | |
echo -n 'yes' | |
return | |
end | |
echo -n 'no' | |
end | |
function __type_of_path -S -d 'Get the type of path: abs, rel or home' | |
# test home fiist | |
# empty is also going to home | |
if test -z "$argv" -o (__is_parent "$HOME" "$argv") = 'yes' -o (__is_parent '~' "$argv") = 'yes' | |
echo "home" | |
else if test (string sub -s 1 -l 1 "$argv") = "/" | |
echo "abs" | |
else | |
echo "rel" | |
end | |
end | |
function __sanitize_path -S -d 'Sanitize concatenated path' | |
set -l ret "$argv" | |
# remove repeated / | |
set ret (string replace -ar '/{2,}' '/' -- "$ret") | |
# remove /./ | |
set ret (string replace -ar '/\./' '/' -- "$ret") | |
# change a/b/c/../d to a/b/d | |
while string match -q -r '[^/]+/\.\.' "$ret" | |
set ret (string replace -r '[^/]+/\.\.' '' -- "$ret") | |
set ret (string replace -ar '/{2,}' '/' -- "$ret") | |
end | |
# remove repeated / | |
# change a/c/. to a/c | |
set ret (string replace -ar '/\.$' '' -- $ret) | |
#set ret (string replace -ar '\./' '' -- $ret) | |
# remove last / | |
set ret (string replace -r '/$' '' -- $ret) | |
echo -n $ret | |
end | |
# Change directory and keep symbols in path | |
function cd --description "Change directory" | |
set -l MAX_DIR_HIST 25 | |
set -l previous | |
set -l cd_status | |
if test (count $argv) -gt 1 | |
printf "%s\n" (_ "Too many args for cd command") | |
return 1 | |
end | |
# Skip history in subshells. | |
if status --is-command-substitution | |
builtin cd $argv | |
return $status | |
end | |
# Avoid set completions. | |
if test "$PWD2" | |
set previous $PWD2 | |
else | |
set -xg PWD2 | |
set previous $PWD | |
end | |
if test "$argv" = "-" | |
if test "$__fish_cd_direction" = "next" | |
nextd | |
else | |
prevd | |
end | |
return $status | |
end | |
switch (__type_of_path $argv) | |
case "abs" | |
set PWD2 (__sanitize_path "$argv") | |
case "rel" | |
set PWD2 (__sanitize_path "$previous/$argv") | |
if test -d "$PWD2" | |
# if realpath is a different directory, use the real one | |
test (realpath "$PWD2") != (realpath "$PWD/$argv") | |
and set PWD2 (__sanitize_path "$PWD/$argv") | |
else | |
set PWD2 (__sanitize_path "$PWD/$argv") | |
end | |
case "home" | |
test -z "$argv" | |
and set PWD2 "$HOME" | |
or set PWD2 (__sanitize_path "$argv") | |
end | |
builtin cd $PWD2 | |
set cd_status $status | |
if test $cd_status -eq 0 -a "$PWD" != (realpath "$previous") | |
set -q dirprev | |
or set -l dirprev | |
set -q dirprev[$MAX_DIR_HIST] | |
and set -e dirprev[1] | |
# nextd, prevd cannot recogize ~ | |
set -g dirprev $previous | |
set -e dirnext | |
set -g __fish_cd_direction prev | |
else if test $cd_status -ne 0 | |
set PWD2 $previous | |
end | |
return $cd_status | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Introduction
In fish shell,
$PWD
orpwd
is always absolute path. But sometimes this is annoying:This function overwrites fish's
cd
function and save the shortened path in$PWD2
(as$PWD
is readonly 😞 )You can use it in the any powerline themes.
It also works when you jump back and forth:
How does it work?
Basically, it depends on the
$argv
you pass tocd
. If it is an absolute path, then go to that path (assign the path to$PWD2
);, if it is a path with$HOME
prefix, then replace the prefix with~
, otherwise, it should be a relative path, then concatenate it with current path.Install
Download this file and put it in
~/.config/fish/functions/
or viafisherman
:fisher https://gist.github.com/pwwang/5ad96bbfb034a91af851c411f0b12a23
Compatible fish themes
fisher
pwwang/theme-bobthefish