Two of the most common commands I run when I cd into a directory are:

  1. git status (which i do through git-number)
  2. ls -lh (aliased automatically as ll through fish)
  • If this directory is not a git repo, then I usually am thinking of command 2.
  • If however it is a git repository then
    • I’d like to know if any files have been changed in this directory and
    • which ones specifically (which is command 1).

Wouldn’t it be nice if I could just hit the ↩ (enter key) and have this automatically happen?

Solution for fish users

If you’re using fish, I got you covered:

# filename: fish/conf.d/magic-enter.fish
function magic-enter-cmd --description "Issue git status or ls on hitting enter in a dir"
    set -l cmd ll
    set -l is_git_repository (fish -c "git rev-parse --is-inside-work-tree >&2" 2>| grep true) # Special variable indicating git.
    set -l in_root_folder (fish -c "git rev-parse --show-toplevel >&2" 2>| grep (pwd))
    set -l repo_has_changes (git status -s --ignore-submodules=dirty)

    if test -n "$is_git_repository"
        if test -n "$in_root_folder"
            if test -n "$repo_has_changes"
                set cmd git-number
            end
        end
    end

    echo $cmd
end

function magic-enter
    set -l cmd (commandline)
    if test -z "$cmd"
        commandline -r (magic-enter-cmd)
        commandline -f suppress-autosuggestion
    end
    commandline -f execute
end

bind \r magic-enter

Solution for zsh users

If you’re using zsh, I adapted the native solution like so:

# filename: magic-enter.plugin.zsh
# Default commands
: ${MAGIC_ENTER_GIT_COMMAND:="git-number"}  # run when in a git repository
: ${MAGIC_ENTER_OTHER_COMMAND:="ll"}        # run anywhere else

magic-enter() {
  # Only run MAGIC_ENTER commands when in PS1 and command line is empty
  # http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#User_002dDefined-Widgets
  if [[ -n "$BUFFER" || "$CONTEXT" != start ]]; then
    return
  fi


  is_git_repository=$(git rev-parse --is-inside-work-tree)
  in_repo_root_folder=$(git rev-parse --show-toplevel)
  repo_has_changes=$(git status -s --ignore-submodules=dirty)

  if [ "$is_git_repository" = true ] && [ "$in_repo_root_folder" = $PWD ] && [ ! -z "$repo_has_changes" ]; then
    BUFFER="$MAGIC_ENTER_GIT_COMMAND"
  else
    BUFFER="$MAGIC_ENTER_OTHER_COMMAND"
  fi
}

# Wrapper for the accept-line zle widget (run when pressing Enter)

# If the wrapper already exists don't redefine it
(( ! ${+functions[_magic-enter_accept-line]} )) || return 0

case "$widgets[accept-line]" in
  # Override the current accept-line widget, calling the old one
  user:*) zle -N _magic-enter_orig_accept-line "${widgets[accept-line]#user:}"
    function _magic-enter_accept-line() {
      magic-enter
      zle _magic-enter_orig_accept-line -- "[email protected]"
    } ;;
  # If no user widget defined, call the original accept-line widget
  builtin) function _magic-enter_accept-line() {
      magic-enter
      zle .accept-line
    } ;;
esac

zle -N accept-line _magic-enter_accept-line

Remember to source this in your .zshrc:

source magic-enter.plugin.zsh

Revisions

  • Make a change to only check git status in a root folder.
  • Reddit /u/colemaker360 reminded me that the ^/dev/null redirect strategy is now deprecated with fish 3.
  • Redditor /u/jblondreddit pointed out that porcelain can be a slow.
  • Add solution for zsh users