From 9d2b53450ac038bcef7c62191770e9b85b6017f9 Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Mon, 21 Mar 2016 16:51:39 -0700 Subject: [PATCH] limit size of cd history to 25 directories The existing implementation grows the $dirprev array without bounds. Besides causing what would appear to be a memory leak it also makes the nextd and prevd commands more expensive than they need to be. It also makes it harder to create a useful "menu" cd command. In addition to implementing a reasonable limit on the size of the $dirprev array I've reformatted the code using fish_indent. Update the documentation to include mentions of the $dirprev and $dirnext variables as well as the limit on how much directory history is kept. Fixes 2836 --- doc_src/cd.txt | 2 +- doc_src/dirh.txt | 2 ++ doc_src/nextd.txt | 1 + doc_src/prevd.txt | 1 + share/functions/cd.fish | 57 ++++++++++++++++++++++------------------- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/doc_src/cd.txt b/doc_src/cd.txt index 3153c383d..a2cb95885 100644 --- a/doc_src/cd.txt +++ b/doc_src/cd.txt @@ -14,7 +14,7 @@ If `DIRECTORY` is a relative path, the paths found in the `CDPATH` environment v Note that the shell will attempt to change directory without requiring `cd` if the name of a directory is provided (starting with `.`, `/` or `~`, or ending with `/`). -Fish also ships a wrapper function around `cd` that understands `cd -` as changing to the previous directory. See `prevd`. +Fish also ships a wrapper function around the builtin `cd` that understands `cd -` as changing to the previous directory. See also `prevd`. This wrapper function maintains a history of the 25 most recently visited directories in the `$dirprev` and `$dirnext` global variables. \subsection cd-example Examples diff --git a/doc_src/dirh.txt b/doc_src/dirh.txt index d25b9c2ad..77e03e185 100644 --- a/doc_src/dirh.txt +++ b/doc_src/dirh.txt @@ -10,3 +10,5 @@ dirh `dirh` prints the current directory history. The current position in the history is highlighted using the color defined in the `fish_color_history_current` environment variable. `dirh` does not accept any parameters. + +Note that the `cd` command limits directory history to the 25 most recently visited directories. The history is stored in the `$dirprev` and `$dirnext` variables. diff --git a/doc_src/nextd.txt b/doc_src/nextd.txt index 8d7c90350..e02598a9b 100644 --- a/doc_src/nextd.txt +++ b/doc_src/nextd.txt @@ -11,6 +11,7 @@ nextd [ -l | --list ] [POS] If the `-l` or `--list` flag is specified, the current directory history is also displayed. +Note that the `cd` command limits directory history to the 25 most recently visited directories. The history is stored in the `$dirprev` and `$dirnext` variables which this command manipulates. \subsection nextd-example Example diff --git a/doc_src/prevd.txt b/doc_src/prevd.txt index cd0c99ac4..f1e9e6cb3 100644 --- a/doc_src/prevd.txt +++ b/doc_src/prevd.txt @@ -11,6 +11,7 @@ prevd [ -l | --list ] [POS] If the `-l` or `--list` flag is specified, the current history is also displayed. +Note that the `cd` command limits directory history to the 25 most recently visited directories. The history is stored in the `$dirprev` and `$dirnext` variables which this command manipulates. \subsection prevd-example Example diff --git a/share/functions/cd.fish b/share/functions/cd.fish index 8faa469d7..a1b6b2ac9 100644 --- a/share/functions/cd.fish +++ b/share/functions/cd.fish @@ -1,36 +1,41 @@ # -# The following functions add support for a directory history +# Wrap the builtin cd command to maintain directory history. # - function cd --description "Change directory" + set -l MAX_DIR_HIST 25 - # Skip history in subshells - if status --is-command-substitution - builtin cd $argv - return $status - end + if test (count $argv) -gt 1 + printf "%s\n" (_ "Too many args for cd command") + return 1 + end - # Avoid set completions - set -l previous $PWD + # Skip history in subshells. + if status --is-command-substitution + builtin cd $argv + return $status + end - if test $argv[1] = - ^/dev/null - if test "$__fish_cd_direction" = next ^/dev/null - nextd - else - prevd - end - return $status - end + # Avoid set completions + set -l previous $PWD - builtin cd $argv[1] - set -l cd_status $status + if test "$argv" = "-" + if test "$__fish_cd_direction" = "next" + nextd + else + prevd + end + return $status + end - if test $cd_status = 0 -a "$PWD" != "$previous" - set -g dirprev $dirprev $previous - set -e dirnext - set -g __fish_cd_direction prev - end + builtin cd $argv + set -l cd_status $status - return $cd_status + if test $cd_status -eq 0 -a "$PWD" != "$previous" + set -q dirprev[$MAX_DIR_HIST]; and set -e dirprev[1] + set -g dirprev $dirprev $previous + set -e dirnext + set -g __fish_cd_direction prev + end + + return $cd_status end -