V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
skywind3000
V2EX  ›  Linux

十行代码实现路径书签功能

  •  2
     
  •   skywind3000 ·
    skywind3000 · 2019-02-25 23:03:55 +08:00 · 2322 次点击
    这是一个创建于 2131 天前的主题,其中的信息可能已经有所发展或是发生改变。

    路径书签 /别名,用来给目录取个名字,要用时快速跳转,它不是用来代替:z.lua / z.sh / autojump 这类第一梯队的 cd 辅助工具的,而是作为他们的一个补充。

    找了一堆类似插件,不但是用麻烦,实现居然有 500+ 行代码,所以我准备写个十多行的版本,更加好用:

    function m() {
      MARKPATH="${MARKPATH:-$HOME/.local/share/marks}"
      [ -d "$MARKPATH" ] || mkdir -p -m 700 "$MARKPATH" 2> /dev/null
      case "$1" in
        +*) 
          ln -snf "$(pwd)" "$MARKPATH/${1:1}" 
          ;;
        -*)
          rm -i "$MARKPATH/${1:1}" 
          ;;
        /*) 
          find "$MARKPATH" -type l -name "*${1:1}*" | \
              awk -F "/" '{print $NF}' | MARKPATH="$MARKPATH" xargs -i \
              sh -c 'echo "{} ->" $(readlink "$MARKPATH/{}")'
          ;;
        "")
          command ls -1 "$MARKPATH/" | MARKPATH="$MARKPATH" xargs -i \
              sh -c 'echo "{} ->" $(readlink "$MARKPATH/{}")'
          ;;
        *)
          local dest="$(readlink "$MARKPATH/$1" 2> /dev/null)"
          [ -d "$dest" ] && cd "$dest" || echo "No such mark: $1"
          ;;
      esac
    }
    

    把上面函数保存成 m.sh 然后再你的 shell rc 里加一行:

    source /path/to/m.sh
    

    就可以是用了,如果懒得创建文件,把这个函数贴到你的 shell rc 文件里也行,使用方法如下:

    m             # 列出当前所有书签
    m foo         # 跳转到名为 foo 的标签
    m +foo        # 将当前路径添加成书签 foo
    m -foo        # 删除名为 foo 书签
    m /foo        # 搜索名称里包含 foo 的书签
    

    是用起来比其他书签插件打字更少,也更符合直觉,当然我们还可以加一段补全功能:

    if [ -n "$BASH_VERSION" ]; then
      function _cdmark_complete() {
        local MARKPATH="${MARKPATH:-$HOME/.local/share/marks}"
        local curword="${COMP_WORDS[COMP_CWORD]}"
        if [[ "$curword" == "-"* ]]; then
          COMPREPLY=($(find "$MARKPATH" -type l -name "${curword:1}*" \
              2> /dev/null | awk -F "/" '{print "-"$NF}'))
        else
          COMPREPLY=($(find "$MARKPATH" -type l -name "${curword}*" \
              2> /dev/null | awk -F "/" '{print $NF}'))
        fi
      }
      complete -F _cdmark_complete m
    elif [ -n "$ZSH_VERSION" ]; then
      function _cdmark_complete() {
        local MARKPATH="${MARKPATH:-$HOME/.local/share/marks}"
        if [[ "${1}${2}" == "-"* ]]; then
          reply=($(command ls -1 "$MARKPATH" 2> /dev/null | \
              awk '{print "-"$0}'))
        else
          reply=($(command ls -1 "$MARKPATH" 2> /dev/null))
        fi
      }
      compctl -K _cdmark_complete m
    fi
    

    该补全代码写的稍微啰嗦了点,但是主要是同时兼容 bash/zsh,有了这些补全代码,你输入完 m 命令后按 tab,能帮你补全书签名称。

    好了,前后代码加起来,不超过 50 行,比其他那些 400-500 行的垃圾插件优雅多了。

    3 条回复    2019-02-26 20:16:37 +08:00
    carlhan
        1
    carlhan  
       2019-02-25 23:27:12 +08:00
    试了一下感觉不错。

    P.S. macOS 上用的话,需要把 `xargs -i` 换成 `xargs -I'{}'`
    1073850525
        2
    1073850525  
       2019-02-26 11:22:07 +08:00
    请问一下补全代码怎么用呀
    skywind3000
        3
    skywind3000  
    OP
       2019-02-26 20:16:37 +08:00
    @1073850525 把补全的代码贴到 m 这个函数后面啊。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5479 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:31 · PVG 16:31 · LAX 00:31 · JFK 03:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.