男人忽略别名

男人忽略别名

nvim在 Bash 中,我有一个别名(在我输入时运行vim)。但当我打字时,man vim我得到的人是vim,不是nvim。有点道理,但当然我真正想要的是“在 shell 中或从脚本中运行 vim 时得到的手册”,而不是“我不使用的程序的手册”。有没有某种方法可以配置别名或 man 以这种方式工作,或者我是否希望每次运行 man 时记住/查找别名,以确保我正在查找有关正确应用程序的正确版本的信息?

答案1

不,man无法真正查找所有别名并提供您已别名的程序的联机帮助页。您可以做的是为联机帮助页设置另一个别名:

alias manvim="man nvim"  

答案2

在 bash 中,您可以用来type vim查找vim在提示符下键入时发生的情况。因此,您可以替换man为检查其参数并“做正确的事情”的 shell 函数。

932% type ls
ls is hashed (/bin/ls)
933% type vim
vim is aliased to `nvim'

正如您所看到的, 的输出type需要一些解析和依赖于大小写的逻辑,但对于简单的情况来说这当然不是什么大问题。别名扩展可以包含多个单词(例如 I alias lfto ls -AF),但这也很容易处理。

如果别名是管道,那就会变得更困难(我可能会显示第一个命令的联机帮助页,并希望得到最好的结果),如果您的命令是 shell 函数而不是别名,则毫无希望。因此,我将解压缩别名并将其他所有内容传递给man而不进行修改。这是概念证明(仅支持一个参数,没有选项man):

function man {
    # Find out if the command is an alias, an executable, etc.
    local cmd

    p=$(type $1)
    case `set $p; echo $3` in
       aliased) cmd=($(set `command alias $1`; echo $2 | sed "s/.*='\([^ ]*\).*/\1/"));;

       *) cmd=$1;;
    esac

    command man $cmd
}

定义它,并根据您的要求man vim查找您的别名并显示 的联机帮助页nvim

答案3

如果您的 shell 以这种方式处理别名:

$ type vim
vim is aliased to `nvim'
$ type -t vim
alias

然后试试这个。以下 shell 函数将检查其参数是否为别名。如果是这样,它将提取别名的第一个空白分隔单词并man在其上运行。

man() {
  cmd="$1"
  if [ "$(type -t "$cmd")" == "alias" ]
  then cmd=$(type "$cmd" | sed -e 's/.*`//' -e "s/[ '].*//")
  fi
  command man $cmd
}

更全面的解决方案将合并$IFS而不只是查找空白,并允许包含`和的别名'

答案4

这是一个坏主意。人们可以使用 shell 函数,该函数可能会也可能不会找到别名命令。相反,我几乎总是不会覆盖事物的默认名称,尤其是不要让命令运行一些完全不同的命令。耙子太多,踩不下去。考虑到这个警告,在 ZSH 中这个函数可能看起来像这样

# test aliases, for testing
# simple no args
alias emacs=ls
# with flags; need to pick first word and hope that's a command...
alias nano='ls -al'
# and oops there's also the ENV prefix form...
alias notepad='ASDF=blah ls -F'
# and also be sure to test with something-that-is-not-an-alias ...

# TODO call this `man` to actually override the man
function crazyman {
  local -a cmd args

  # one may simply type `man ... foo` or there could also be multiple
  # man pages to be viewed `man ... foo bar` so must iterate over all
  # the hopefully-not-options-or-section-names arguments and try alias
  # lookups and all such... `man ls -w` may also be legal depending on
  # the getops, by the way.
  while :; do
    if [[ -n $1 ]]; then
      while :; do
        # try to skip over `man 1 foo` or `man -w foo` forms to find what
        # is hopefully the foo command
        #
        # TODO 'n' section for TCL complicated as there could also be a
        # 'man n' command alongside "man n expr" or whatnot; this assumes
        # there is no 'man n' page that would ever be looked up. Other
        # non-numeric-prefixed man section names may also need to be
        # handled here, depending on the vendor...
        if [[ $1 =~ "^[0-9-]|^n$" ]]; then
          args+=($1)
          shift
        else
          break
        fi
      done

      cmd=(${(z)aliases[$1]})

      if (( #cmd )); then
        # aliases might be simple foo='bar ...' or more complicated
        # foo='ENV=asdf ... bar ...' where we need to dig to try to find
        # the bar command, and perhaps other complications as well :/
        # I did say this was a bad idea...
        while :; do
          if [[ $cmd[1] =~ "=" ]]; then
            shift cmd
          else
            break
          fi
        done
        args+=($cmd[1])
      else
        args+=($1)
      fi
      shift
    else
      break
    fi
  done

  command man $args
}

command man $args替换为print -l command man $args,进行一些手动测试(考虑到上述代码中的边缘情况数量,建议进行适当的单元测试):

% crazyman emacs
command
man
ls
% crazyman nano 
command
man
ls
% crazyman notepad
command
man
ls
% crazyman notepad nano
command
man
ls
ls
% crazyman nosuchalias
command
man
nosuchalias
% 

将此代码移植到其他 shell 中作为练习留给读者。或者,简化并且不要使用此代码,因为其复杂性不会带来太大好处。

相关内容