Fish-shell: 支持历史扩展(例如,bash 的 !!、bang bang 和 !$、bang Dollar、tokens)

创建于 2012-08-20  ·  98评论  ·  资料来源: fish-shell/fish-shell

看起来双爆炸不起作用,并且以某种方式被解释为 sudo 尝试定位失败的程序。 这发生在使用从源代码编译的鱼壳的 Ubuntu 12.04 LTS 上。

复现步骤:

  1. 执行任何命令:

    $ls

  2. 以 root 身份执行前面的命令:

    $须藤!!
    须藤:!!:找不到命令

    预期行为:

命令sudo !!以 root 身份执行先前执行的命令 ( ls )。

我还通过遵循 bash 中的重现步骤检查了该问题不是由sudo引起的,其行为符合预期。

另请注意,Mac OS X 10.7 上较早版本的 fish-shell 没有此问题, sudo !!按预期工作。

duplicate

最有用的评论

function sudo
    if test "$argv" = !!
        eval command sudo $history[1]
    else
        command sudo $argv
    end
end

sudo !!对于出于某种原因仍然使用!!的人。

所有98条评论

它在文档常见问题解答中进行了讨论: http ://fishshell.com/docs/current/faq.html#faq -history

感谢您的澄清。

我理解删除历史字符的基本原理。 然而,虽然我理解这样做的基本原理,并且可以使用 Ce 和 Ca 代替 End 和 Home,但对于许多用户,尤其是那些习惯使用的用户! 和那些没有 Home 键和 End 键的笔记本电脑上的人,输入 sudo 仍然容易得多! 比 Up+C-a+sudo。

您还会考虑恢复历史替换令牌的功能吗?

因为这是一种罕见的情况! 使用起来更舒服,请尝试以下功能:

function sudo!!
    eval sudo $history[1]
end

仅由“sudo !!”调用。

或者我使用的另一种可能性:

function .runsudo --description 'Run current command line as root'
    commandline -C 0
    commandline -i 'sudo '
    commandline -f execute
end
bind \es .runsudo

然后按 MS 我运行当前命令行, sudo 放在它前面。
或者通过修改此示例,您可以创建一个函数,将前一个命令行放在当前命令行中并将其绑定到例如“\e!”。 这种方法比简单地使用 '!!' 更好因为它让您有机会在执行前查看和更新​​命令行。

我对最后一个命令做了一些改动:

  function .runsudo --description 'Run current command line as root'
    set cursor_pos (echo (commandline -C) + 5 | bc)
    commandline -C 0
    commandline -i 'sudo '
    commandline -C "$cursor_pos"
  end
  bind \es ".runsudo"

它保存光标位置而不是直接执行它。

!$ 也很高兴

function sudo
    if test "$argv" = !!
        eval command sudo $history[1]
    else
        command sudo $argv
    end
end

sudo !!对于出于某种原因仍然使用!!的人。

谢谢。 有相当多的人使用 sudo !! 鉴于许多其他 shell 包括 bash 和 zsh 都支持此语法。 须藤!! 比使用 home 键和 end 键更容易打字,因为这些键离得更远。

我建议默认情况下将上述功能包含在鱼壳中。

!! 是一个很好的缩写候选 (#731)

表示支持!! 和相关的快捷方式。 添加它并没有什么坏处,感觉就像鱼只是在向用户推销个人哲学。

我目前对理想解决方案的想法是!! 应该是缩写(#731),我们实现了函数签名(#478)来支持子命令(一个接受命令的命令,比如 sudo)。 然后缩写在子命令位置扩展,因此'sudo !!' 会扩大。

添加我自己

尽管它很旧,但它确实应该成为 Fish 的默认功能。 没有理由不拥有它——如果你不想亲自使用它,那很好,但是拥有一个额外的命令并不会真正伤害任何人——人们喜欢以不同的方式做事。

道路 !! 在大多数 shell 中实现确实会伤害人。 例如,考虑这个命令:

echo fish is great!!

在 bash / zsh / tcsh 中,这会做一些意想不到和可怕的事情,因为 !! 是魔术语法。 这是鱼极力避免的那种奇怪的相互作用。

我的建议是实施!! 不是作为魔术语法,而是作为别名。 这意味着它只会在“命令位置”中做一些特殊的事情——它不会扩展参数。 它还保留了鱼的特征集,这是可取的。

为了使它有用,我们需要教 fish 关于子命令, sudo是最常见的例子,但也有timestrace等。 然后 fish 会扩展别名在“子命令位置”中,这本身就是一个很酷且有用的功能。

当您考虑sudo echo fish is great!!时,您提出的解决方案会崩溃。 所有语法都可以得出相同的论点: echo I really like fish (the shell)!是不是也令人困惑? 我还担心“子命令”列表将无法维护并且会降低灵活性。

使用别名,只有命令会被扩展,fish 会知道哪些参数是(子)命令,哪些不是。 所以sudo echo fish is great!!不会执行最后一个命令扩展,而是传递一个字面意思“很棒!!” sudo(从而回应)。 我声称这是用户所期望的。 有关设计和基本原理,请参阅有关缩写 (#731) 和函数签名 (#478) 的讨论。

SirCmpwn 是正确的,需要全面的函数签名是别名方法的一个缺点,而且其他句法元素也令人困惑。 现实生活中的例子包括使用 git (#434) 或通配符 (#967 等) 进行大括号扩展的烦恼。 语法的成本很高,当它与其他功能(例如#354)冗余时,我们会尝试消除语法。

无论如何,这就是我为什么支持的论点!! 作为基本句法元素是不行的。 但是,我愿意以不需要修改 fish 语法的方式介绍它。

我认为与{}比较是糟糕的。 在鱼中,大括号的工作方式与其他贝壳不同。 人们只有在期望它像 bash 和朋友一样工作时才会绊倒它。 这 !! 语法应该与其他常见的 shell 一样工作。 还, !! 不是我期望在命令中经常看到的足以引起问题的东西。 事实上,我希望人们尝试使用但未能使用的次数! 鱼的数量远远超过有人使用文字的次数!! 在一个命令中。

我声称!在其他 shell 中令人困惑,如果不以这种方式实现它会更好。 例如,在http://codegolf.stackexchange.com/a/17776/3103 上,我输入了简单的“你好,世界!” 用 UNIX shell 编写的程序由于!而失败(在 Ridiculous Runtime Errors 问题中)。 它甚至获得了七票赞成,所以我可以想象当你不想使用它时,这个功能会令人惊讶。

但是, !!本身应该没问题,因为用户多久将!!作为令牌写入? 再说一次,添加!!会鼓励添加其他历史替换模式,其中一些可能很烦人。

添加我自己 - 我的第一个周末遇到了鱼。 绝对应该支持。

添加我自己 - 需要这个。

对于那些希望这样做的人来说,前面讨论中提到的函数和绑定为我提供了一个比典型的sudo !!更简单的工作流程,用于预先添加sudo或执行最后一个命令。

你应该试试他们。 它让我重新审视我的 readline 和 zsh 配置以获得类似的绑定。

它将七次击键(其中两次移动)转换为一次绑定。

不管_你_喜欢什么 - 真的有什么理由吗!! 不被支持? 每个人都有不同的适合他们的东西,虽然有些人可能喜欢使用向上箭头,但很多人喜欢使用 !!,老实说,为什么会是一件坏事? 那些不想要它的人不必使用它。

实施起来肯定不难吧?...

是的,我知道您可以将它与 fish 脚本一起编写,但它_不_以与 bash 或类似 shell 中相同的方式工作,这在很多时候都非常方便。

请参阅我上面对一种与鱼哲学保持一致的方式的

“回声鱼很棒!!”的说法比使用 '!!' 更好因为历史有点弱,但我明白这一点。 似乎是一个简单的“设置 shell_history 高级”或其他东西可以让人们愿意冒险“回声鱼很棒!!” 收到错误信息。

尽管如此,我的 '!!' 用例类似,但可以通过一些功能增强来避免。

例如在我的 mac 上使用 bash:
$ brew 更新
$ brew 过时了
$ brew 获取!!

所以我有点经常将上一个命令的输出用于新命令。
用鱼我可以做到这一点:
$ brew fetch (brew 过时)
现在在某些时候这可能是我可以使用的建议,但我真正需要的是能够在 () 块中搜索历史记录。
例如:
$ brew fetch (bre)

不幸的是,尽管 fish 对使用 () 代替“混淆”反引号等子命令感到相当自豪,但它并没有真正将它们视为这样,直到您按 Enter 键。 至少我看到的是这样。

如果 fish 允许在第一个 '(' (又名子命令)之后进行历史搜索,我认为没有 ! 历史操作会更容易处理。

如果我理解这个建议,那就是当你按下向上箭头时,它应该只在最里面的子命令而不是整个命令行中执行历史替换。

:-1:

我仍然支持简单地实现 bash 风格的!!

我更喜欢 :up_arrow:、Ctrl+p 和在子命令位置工作的命令历史搜索而不是引入 !!

其他 shell 的整个历史 API 令人困惑,人们通常只记得! 从中。

正确的。 这会很方便,而且很容易替换'!!' 或者 !keyword 使用。

真的很喜欢!!作为缩写的想法。

看起来最近的每晚构建中的缩写只允许在命令位置使用缩写,希望它能够被更新为能够用作这种情况的参数。

此功能被高估了,只需使用sudo cmdeval sudo $cmd

@bucaran我没有完全遵循。 !!是为了速度,我如何将!!的速度与cmd匹配?

您的意思是创建一个名为$cmd的变量作为最后一个命令吗? 它不是本机变量。

谢谢

@mdsib是的,我想我记得在另一个问题中讨论过不允许在参数位置使用缩写。 当时最好不要实施。 这肯定会改变这一点。

我认为这个帖子的要点是它不会很快发生,我应该取消订阅这个 Github 问题并切换到 zsh。 再见!

不是因为!!不在这里,而是因为一个相当简单的功能的 Github 问题已经开放了 3 年,但由于哲学上的废话而没有实施。

看到人们试图说服其他人一个功能没什么大不了的,这很有趣。 当然,你不想要它,所以你不在乎......就像你试图说服人们不喜欢绿色,因为你认为蓝色更好。
尽管如此,由于“简单”功能似乎无法实现,如果有人喜欢现有功能但又想添加更多功能,也许他们应该只对鱼进行分叉。 似乎那样会更快到达某个地方。

我做了 ~/bin/!! 看起来像这样:

#!/bin/fish
eval $history[1]

在短期内,它可以帮助我解决缺少的功能和我输入 !! 的倾向。
我也做了 ~/bin/!vi:

#!/bin/fish
for f in $history
    echo $f | grep '^vi'
    if test "$status" = "0"
        eval $f
        exit $status
    end
end

不理想,但足以使我的外壳现在更频繁地执行我期望的操作。

@SirCmpwn !!是一个简单的功能,这对我来说并不明显。 例如,bash 支持:

ls some_long_file.txt
!!:s/ls -l/cat/

应该这样用!! 是否支持? 说“鱼应该支持!!”的用户可能对这意味着什么有不同的看法。

你对此有强烈的感受,所以我鼓励你(或任何人)就如何撰写提案!! 将在鱼中工作(语义,而不是实现)。 究竟支持什么语法? 这种扩展与其他类型的扩展(如变量或流程扩展)有何关联? 展开后的字符串中将如何进行参数拆分? 你可以使用转义来防止它吗?

这是一个真诚的请求。 功能不是由单个用例定义的; 我们需要一个具体的建议来讨论。

如果你说“我希望这个案例有效,我不在乎如何”,那么这很好且有效。 但在实施任何事情之前,必须有人制定细节。

近期内,一个具体的计划是实现全局别名,然后制作 !! 成一。 另一种方法是合并 docopt 工作,为 sudo 提供一个函数签名,然后 make !! 变成一个普通的别名。 往哪个方向看我们想不想!! 应该到处扩张,或者只是在指挥位置。

@ridiculousfish你说的对,'!!' 功能请求需要相当详细。 我从未使用过您给出的特定示例,因为我总是这样做:
$ ls -l some_long_file.txt
$ ^ls-l^猫

显然这也行不通。 这对我来说将是单独的功能请求,因为我最近才开始测试鱼,所以我没有打扰。

“fish:在期望命令名称时遇到重定向。Fish 不允许在命令之前进行重定向操作。”

似乎很容易将命令位置中的 '^' 视为替代,因为它与现有功能不冲突。 但这是一个单独的问题,只是提及它,因为您是对的,应该对“!!”有明确的定义。 (或只是一般的历史替换)意味着。

以下是我使用的几个示例:

$ !!
$ some command `!!`
$ !keyword 
$ !123

谢谢@gillham ,这样的信息在设计功能时非常有用。

我还注意到@nyarly有一个巧妙的解决方法!!!$在这里: https :

更好的修复 #5:
Fish 是历史驱动的,当忘记 sudo 或以其他方式用非工作命令污染您的历史时,实际上可能值得您花时间(从长远来看)从历史中手动删除它。 是的,那是打开一个新终端,执行 bash 并编辑 ~/.config/fish/fish_history。 当我跳过这一点时,鱼一次又一次地将我引导到错误的命令上。

至于@nyarlymkdir …; cd !$习惯,我正在做mkcd …

function mkcd --description 'mkdir and cd'
        mkdir $argv[1]
        and cd $argv[1]
end

请注意,从历史中擦除不需要 bash 恶作剧:

history --delete --prefix some_command

fish_config history还可以让您通过点击来完成。

可以使用https://github.com/fish-shell/fish-shell/wiki/Bash-Style-History-Substitution- (!!-and-!$) 在 Fish 中很好地复制此功能——也许是问题所在应该关闭?

:-1: :-1: 除非实现了完整的 bash 兼容模式。

我认为这是一个滑坡。 如果这是在 fish 中实现的,那么单个 !s 和 ksh 历史功能呢? $() 呢? Fish 是一个 csh 风格的 shell。 如果人们不能/不会适应,那么 zsh ...

我从这次讨论中得到的启示是为发现这个问题的人提供的 tl;dr。 (超过 3 年)

  1. 团队不想开发该功能,因为他们不使用它。
  2. 有很多人想要这个功能,因为他们使用它。
  3. 团队似乎不愿意实现现有的功能,但愿意做一些事情
    如果我们给他们足够的数据,那么效果类似。
  4. 人们要么接受没有该功能,要么实施最有效的解决方法,要么移动
    到另一个项目。

我是后者之一,虽然我希望这个问题得到解决,但我不能合理地使用 fish 并在没有大量工作的情况下添加我使用的机器数量的解决方法(我需要在不同的机器上设置不同的配置),我使用 ! ! 对我有要求的地方就够了。 所以我会关注这个讨论,希望有一天鱼能满足我的用例。

@tetra-archos 还没有人提出具体的建议,所以我们对“功能”是什么没有把握。 既然你显然对此有强烈的感觉,如果你如此倾向,如果你建议作为一个起点应该采取什么样的行为,这将是一个很大的帮助。 否则,至少列出您使用的历史替换表单会很有用。

请注意,完整的 bash 历史替换行为非常复杂,而且是可配置的,因此“只做 bash 所做的事情”是不可能的。

目前还没有人提出具体的方案,所以我们对“特征”是什么还没有一个确切的认识。

@tetra-archos:这绝对是至关重要的。 到目前为止,大部分内容都是“我们想要“!!”!!” 也许是“!$”(这是“插入最后一个命令的最后一个参数”)。 但是,如果要实施它(或替代方案),需要敲定很多细节。

例如:

  • 您想要历史替换的哪一部分 - 它只是“在此处插入最后一个命令”(“!!”)和“在此处插入最后一个命令的最后一个参数”(“!$”),还是所有其他内容,例如“ !!:s/string1/string2"(我宁愿添加一个通用的“替换”模式,比如 emacs 的“查询替换”或 vim 的“:s/”,这样你也可以在 _before_ 执行错误的命令之前这样做)? “插入我的历史记录中的第五个命令”(“!5”) - 我从未完全理解 - 或“插入倒数第五个命令”(“!-5”)怎么样? “单词指示符”和“修饰符”怎么样?
  • 您是否希望命令立即执行(即您输入sudo !! ,按回车键并立即执行整个操作)还是可以先插入它以便您可以仔细检查 - 这就像bash 与“histverify”选项(我倾向于后者)?
  • 一定要“!!”吗? 和 "!$" 或者可以用不同的方式使用,即肌肉记忆是你的问题吗? 但是,如果是这样的话,我们永远不会是 100%,而且历史替换_是_bash 的一小部分

如果只是肌肉记忆,您还可以将以下内容放入您的fish_user_key_bindings:

bind '!!' 'commandline -i "$history[1]"'
bind '!$' 'history-token-search-backward'

(这个问题,为什么我们可能不应该在默认绑定中使用它,是因为它会在您输入“!”后等待检查第二个字符)

我认为!!是不好的做法

命令sudo !!不会告诉任何人 shell 将实际执行什么。
如果我想在“ a nfang”处使用sudo执行p以前的命令,我输入

^p ^a sudo

我建议添加一条消息,告诉人们使用行编辑命令 ^p 和 ^a 而不是使用历史功能。

!!: command not found, try 'Ctrl-p Ctrl-a' to prefix the previous command with 'sudo' or any other  prefix

我也讨厌!!fish_vi_mode替代^p ^a一种更简单的方法:

^v k I

因为你不喜欢做某事的方式并不会降低它的有效性。
2015 年 11 月 10 日上午 8:14,“Ivan Tham”通知@ github.com 写道:

我恨 !! 也。 一种更简单的方法 fish_vi_mode 作为 ^p 的替代方法
^一:

^vk 我


直接回复此邮件或在 GitHub 上查看
https://github.com/fish-shell/fish-shell/issues/288#issuecomment -155416048
.

反过来也是如此。

这个问题的双方都有合理的需求和担忧。 我认为主要的阻碍是找到正确的方法而不是快速而肮脏的方法

我同意,我不反对其他方式来做到这一点,他们只是不
满足我(显然还有其他人)的需求。
2015 年 11 月 10 日下午 12:19,“Eric Mrak”通知@github.com 写道:

反过来也是如此。

这个问题的双方都有合理的需求和担忧。 我觉得
主要阻碍是找到_正确_的方式来做到这一点,而不是快速和
肮脏的方式


直接回复此邮件或在 GitHub 上查看
https://github.com/fish-shell/fish-shell/issues/288#issuecomment -155494929
.

重申早期讨论中提到的方法并稍微扩展它们:我发现键绑定比“!!”更适合我。

我已经编写了这个可以绑定到某个键的函数(对我来说是 ^S, bind \cs 'prepend_command sudo' )。 如果命令行有内容,它会在前面加上 sudo。 如果没有内容,它会将 sudo 放在历史记录中的最后一项。 所以sudo !!<Enter>现在变成了^S<Enter>

function prepend_command
  set -l prepend $argv[1]
  if test -z "$prepend"
    echo "prepend_command needs one argument."
    return 1
  end

  set -l cmd (commandline)
  if test -z "$cmd"
    commandline -r $history[1]
  end

  set -l old_cursor (commandline -C)
  commandline -C 0
  commandline -i "$prepend "
  commandline -C (math $old_cursor + (echo $prepend | wc -c))
end

有人说配置这样的东西太复杂了。 一种可能的解决方案可能是在功能上包含一些类似于我在 fish 中的功能的东西,因此至少将其配置为单行。

当然,这并不能满足some_command --with-subshell-param (!!)等其他要求。

@Ahti这真的很糟糕,刚刚开始工作,看起来它会是一种享受,一会儿会回来报告!

是的,到目前为止这胜过sudo !! 。 在命令执行到一半并意识到它应该是sudo时,我经常遇到这种情况。 ^s ,即刻sudo前缀!

就我个人而言,除了sudo !! ,我从未在任何上下文中使用过!! ,所以这不会打扰我。

巧合的是,我刚刚尝试了 fish_vi_mode 并且非常喜欢它。 然而,在 Vi 模式下^s似乎不再绑定。 建议?

好的,我在 config.fish 中有键绑定。 我找到了 #2254 然后找到了https://github.com/faho/fish-shell/commit/f7e8ad632a388d5f1c5eb4cfc33f3cdb1f7fd831然后找到了http://stackoverflow.com/a/16675092/292408确认我应该将 mysbinding尚不存在的功能。

那行得通,现在当我处于 Vi 命令模式时[N]前缀按预期工作。

我们已经有了 Alt-P 来运行寻呼机中的当前管道; 我想知道我们是否也应该添加 Alt-S?

我认为@Ahti是每个人都在寻找的一个非常优雅的解决方案。 直接到键绑定,无需担心随机扩展或奇怪的边缘情况。 它只是放置文本供您根据需要使用或取消。

我喜欢@nyarly的替换和@Ahti的键绑定解决方案。
就个人而言,我仅在sudo !!的上下文中使用!! sudo !!

哎呀! 这个线程现在已经快四年了。 我最近买了 ǃǃ.com 和 ǃǃ.net(Github 不会让我超链接,显然,所以复制和粘贴)如果有人想要的话。

嘿! 这很酷! @geoff-codes 你是怎么做到的?)

他们最近开始允许 .com 和 .net “国际化”域名。
screen shot 2016-05-11 at 4 53 48 am

不过,目前对它的支持仍然存在很多问题。 例如,他们让我注册ⵌⵑ.com 而不是ⵌǃ.com。

我不知道你可以注册!!.com,这太疯狂了。

从这个问题中吸取的教训:如果你曾经写过一个 Unix shell,你应该确保实现的唯一功能是 sudo !!,因为人们似乎没有它就活不下去。

不过说真的,我从人们那里得到消息说这很好用:

@bucaran是的,确实,情况似乎就是这样😆。

国际化域名 - IDN:

https://en.wikipedia.org/wiki/Internationalized_domain_name

编辑:这篇文章太慢了,还有像@geoff-codes 这样的注册! 这一定是一项明智的投资。 一个两个字符(sorta).com!

#!.com会拿走蛋糕。 是否有禁止 com TLD 的规则,或者他们应该解决的问题?

在用于 Windows 演示的 bash 中,演示者输入了一些东西
像这样:

$> 回声你好 Windows!

我希望你们都能猜到发生了什么。
2016 年 5 月 11 日下午 1:57,“Aaron Gyes”通知@ github.com 写道:

国际域名 - IDN

2016 年 5 月 11 日凌晨 4:44:58,蒂莫菲 ([email protected]) 写道:

嘿! 这很酷! @geoff-codes https://github.com/geoff-codes 是怎么做的

去做?)


您收到此消息是因为您订阅了此线程。
直接回复此邮件或在 GitHub 上查看
<
https://github.com/fish-shell/fish-shell/issues/288#issuecomment -218435761


您收到此消息是因为您发表了评论。
直接回复此邮件或在 GitHub 上查看
https://github.com/fish-shell/fish-shell/issues/288#issuecomment -218438118

那么,我应该切换到 bash 吗?

@base698 - 我最终推出了一个渔夫插件来支持历史替换的两个最常见的用例:!! 整个最后一个命令和 !$ 最后一个参数。 老实说,我基本上已经打破了自己的习惯,因为fish的命令行编辑太好了。 不过,我真的很喜欢能够

> which tool
> cat (!!)

例如检查脚本

一旦你安装了fisherman,你就可以用fisher install nyarly/fish-bang-bang安装插件。

为了完整起见(并给出一个正确的例子)
这是我提到的 youtube 视频的屏幕截图,这是“!!”的一大特色。 现在也可以在 Windows 上使用的模式。
bangpatternbash

https://www.youtube.com/watch?v=2dB0igTfhfg&feature=youtu.be&t=760

他想执行git commit -a -m "Rawr!!"

结果git commit -a -m "Rawrclear"

就像我喜欢鱼一样,! 太有用了。 不确定sudo !!但也是将以前的信息传递给新命令的一种方式。 例如:

find . -name something | grep "pattern"然后我会玩这个模式,直到我得到我想要的。
然后我会将它传递给这样的东西 (someCommand !! )。 目前,在鱼中,这需要太多步骤。 解决方法对我来说不够好。

zsh 扩展!! 以便您可以对其进行编辑。 所以必须回到zsh。

如果您使用的是fisherman(您应该如此),您可以安装nyarly/fish-bang-bang并获得!!!$任意命令扩展

@nyarly是的,我试过了。 但我不喜欢它在输入第二个!后立即扩展的方式。 感觉很别扭。 zsh 感觉更好,因为它在您输入空格或按 Enter 后会扩展。

编辑:没关系,我做不到。 我忘记了将 ZSH 设置为我想要的样子是多么烦人。 nyarly 的插件将不得不这样做。

我很高兴这没有实施! 它违反了鱼的正交性定律和用户焦点定律。 Bash 的历史替换需要太多的思考,超出!!!$以及可能s^ 。 这就是为什么人们只使用这些。 Fish 的解决方案更具交互性,允许对参数进行更一般的替换。 它在笔画数量方面足够有效,并且与!!同样有效。

一些用户错过了!!!$并且不想学习不同的方式。 Fish 是否应该将这些特性作为边缘情况实现(参见正交性定律)? 还是所有的 Bash 历史替换? 还是其他外壳的所有功能? 用户能想到的所有功能?

对于想要复制和粘贴某些内容的任何人,这是一个修复程序:

把它放到 ~/.config/fish/functions/fish_user_key_bindings.fish

function bind_bang
  switch (commandline -t)
  case "!"
    commandline -t $history[1]; commandline -f repaint
  case "*"
    commandline -i !
  end
end

function bind_dollar
  switch (commandline -t)
  case "!"
    commandline -t ""
    commandline -f history-token-search-backward
  case "*"
    commandline -i '$'
  end
end

function fish_user_key_bindings
  bind ! bind_bang
  bind '$' bind_dollar
end

链接到https://github.com/fish-shell/fish-shell/issues/288#issuecomment -7869918 中的@siteshwar URL 已损坏。 你能编辑你的评论来为阅读这个仍然开放的问题的人修复它吗?

我编辑了他的评论以指出我们现在主持常见问题的地方。

现在鱼有&&和|| (https://github.com/fish-shell/fish-shell/issues/4620) 它非常接近于完全替代 bash!

我真的很困惑——

因此,声明其第 1 设计目标的 shell 是:

1. Everything that can be done in other shell languages should be possible to do in fish

...不允许我做的所有其他壳最常用的操作之一?

鱼常见问题说用户应该改为

First press Up, then Home, then type "sudo ".

伙计,这太牵强了。 在过去的六个月中,有多少用户出于某种原因点击了“主页”按钮? 在那个长度上,我可以争辩说,从手册页中自动解析命令与仅仅打开该死的 man 文件并自己找到它是不够正交的

@andysalerno
您想要执行的操作是在 sudo 前面执行上一个命令
和鱼提供了这个功能
虽然不是进入
First type "sudo ", then press shift+1, then press shift+1
我做
ctrl+p, ctrl+a, type "sudo "
这在 bash 中的工作方式相同
既然你提到了常见问题,我又检查了一遍,有人删除了关于这个快捷方式的部分现在不见了。 (我创建了 https://github.com/fish-shell/fish-shell/pull/3879 来解决这个问题)
这个快捷方式之所以有效,是因为它遵循了readline库,该库被广泛实现或模仿用于行编辑。
如果我找到时间,我将创建一个拉取请求将其添加到常见问题解答中
我可以理解您的沮丧,使用Home键确实不是一种选择,因为该键在许多键盘(例如我所有的 3 个键盘)上都位于不同的位置。

谢谢你再次提出这个问题。 我认为有一个简单的(只有修饰符和字母键,没有主页键,没有箭头键)、快速(没有太多的击键)和 _documented_ 这样做很重要。

太棒了,我不知道 ctrl+p ! 我比这个更喜欢这个!!

编辑:
有没有其他方法可以重新评估上次运行的命令? 我发现自己在 bash 中做了很多这样的事情:

> man -w fish  # prints location of man file for fish
/usr/share/fish/man/man1/fish.1

> less $(!!)

它没有那么简洁,但您可以使用 eval 和 history 变量来做到这一点:

> man -w fish
/usr/share/fish/man/man1/fish.1

> less (eval $history[1])

但更好的方法是使用 alt-p。 如果在键入命令后按 alt-p,Fish 会将命令输出减少到更少:

> man fish alt-p > man fish ^&1 |less;

我不了解所有反爆炸的人......在很多情况下,爆炸的东西比这样的“变通办法”更快、更方便,比如:
First press Up, then Home, then type "sudo ".

一旦你习惯了 Bang 命令就是他妈的魔法......我真的希望鱼人改变主意并将它们添加回来。至少有一些好的,比如:

!!
!WORD
!WORD:p
!:n
!$
!^
!n:n
!:gs/MISTAKE/FIX
!#
!#^

鱼很不错,继续努力

有没有支持的方式来执行历史上的最后一个命令? 我不介意必须输入它,因为我只是使用宏在我的另一个 tmux 窗口中调用命令。 但我的用例是我只想能够做这样的事情:

$ echo "hi"
hi
$ x
hi
$ x
hi

我试过eval $history[1] ,但第二个电话爆炸了。 这就是!!命令的有用之处。 不能真正接受的一件事是使用箭头键。 鱼中是否有任何命令支持此用例?

我现在能想到的最好的方法是使用前导空格来防止将其添加到历史记录中:

$ function x ; eval $history[1] ; end
$ echo "hi"
hi
$  x    # note leading space
hi
$  x
hi

我知道这当然不是很好。 然而,在这个简单的情况下, history-search-backward绑定似乎就足够了? 默认情况下,这是箭头键,但您可以添加或更改它。

哦! 这是个好主意,我没有考虑使用前导空间。 我得试试。

更新
这非常适合我的用例。 $ eval $history[1] #note extra leading space

这很可能是我不能和鱼呆在一起的原因。 虽然它优雅而简单,但它在许多方面缺乏标准的快捷方式,这使得它没有效率:

第一项。 我想用 sudo 重复上一个命令:

sudo !!

1)点击向上按钮
问题,我必须在 May 键盘上按向上按钮。 大约有四分之一的时间我会想念它,然后必须低头看键盘才能准确地看到它的位置,并且可能会修复丢失的任何东西。 然后...
2) 按 Home 或 Ctrl-A
家是另一个延伸,位于不同键盘上的许多不同位置,我将不得不寻找它。 Ctrl-A 来得更自然,所以我猜是可行的。
3) 输入“sudo”并回车。
好吧,这只是七次击键,但其中一次很容易出错并导致我的工作流程在很大一部分时间被中断。

下一项,我想对上一个最后一个参数进行分类:

ls -l /etc/network/iptables
cat !$

或者用鱼:
1) 输入“猫”
2) Alt-Up
好吧,这又不是很自然。 我很少按 Alt 键,而经常按它旁边的 Super (Cmd/Windows/whatever) 键,这会完全改变我所处的上下文。

像所有主要竞争者一样,Fish 需要更好的历史扩展。 它的不足是降低了高端用户的生产力。

@wrecklass因为我无法从手指中取出sudo !! ,所以我写了https://github.com/nyarly/fish-bang-bang ,我会向您推荐。

此外,IIRC,fish 附带 Alt-S 用于“前置 sudo”,如果您的命令当前为空,它将适用于最后一个历史记录条目,与 Alt-P 将附加| less

并且仅仅因为它不断出现,(“即为什么不 !! 在鱼中工作的方式与它的 bash 一样”)我想说明: !字符的特殊处理是其中之一把我从 bash 赶走了。 作为一个长期的鱼用户,如果这种行为是为了安抚少数声音而带来的,我会非常失望。

sudo !!就是这么标准的东西。 我知道 Fish 非常努力地试图摆脱古老的 bash 语法,但是通过推掉合法有用的功能以支持个人哲学,我认为我们停止了进步。

@ClickSentinelfish并坚持使用bash 。 :笑脸:

我们目前的计划是实现全局缩写,然后也可以支持“!!” 等。 参见#5003。

我正在关闭这个问题,因为它已经走到了尽头。

@tukusejssirs@ClickSentinel ,您是否尝试将https://github.com/fish-shell/fish-shell/issues/288#issuecomment -306212011 中的代码添加到您的配置中?

几年来我一直有一个变体(从我的配置中的一个问题(这个问题,也许?)修改而来,它是我最依赖的外壳人体工程学之一。(另外,特别是对于附加案例)我在我的变体中使用!$之前的字符串进行向上的令牌搜索,这是我在 bash 中工作时最讨厌的事情之一。)

我的变种(或者我可能偷了变种……不记得了 :man_shrugging: ):

function bind_bang
    switch (commandline --current-token)[-1]
    case "!"
        # Without the `--`, the functionality can break when completing
        # flags used in the history (since, in certain edge cases
        # `commandline` will assume that *it* should try to interpret
        # the flag)
        commandline --current-token -- $history[1]
        commandline --function repaint
    case "*"
        commandline --insert !
    end
end

function bind_dollar
    switch (commandline --current-token)[-1]
    # This case lets us still type a literal `!$` if we need to (by
    # typing `!\$`). Probably overkill.
    case "*!\\"
        # Without the `--`, the functionality can break when completing
        # flags used in the history (since, in certain edge cases
        # `commandline` will assume that *it* should try to interpret
        # the flag)
        commandline --current-token -- (echo -ns (commandline --current-token)[-1] | head -c '-1')
        commandline --insert '$'
    case "!"
        commandline --current-token ""
        commandline --function history-token-search-backward


    # Main difference from referenced version is this `*!` case
    # =========================================================
    #
    # If the `!$` is preceded by any text, search backward for tokens
    # that contain that text as a substring. E.g., if we'd previously
    # run
    #
    #   git checkout -b a_feature_branch
    #   git checkout master
    #
    # then the `fea!$` in the following would be replaced with
    # `a_feature_branch`
    #
    #   git branch -d fea!$
    #
    # and our command line would look like
    #
    #   git branch -d a_feature_branch
    #
    case "*!"
        # Without the `--`, the functionality can break when completing
        # flags used in the history (since, in certain edge cases
        # `commandline` will assume that *it* should try to interpret
        # the flag)
        commandline --current-token -- (echo -ns (commandline --current-token)[-1] | head -c '-1')
        commandline --function history-token-search-backward
    case "*"
        commandline --insert '$'
    end
end

function fish_user_key_bindings
    bind ! bind_bang
    bind '$' bind_dollar
end

谢谢@scooter-dangle 这比#228更好用

在某些情况下,Fish 会提供更惯用的方式来执行某些操作:

LANG=C :
fish: Unsupported use of '='. To run ':' with a modified environment, please use 'env LANG=C :…'

也许!!也可以在默认情况下生成这样的消息,建议另一种更惯用的方式来做到这一点?

但是,该提案应该同样有效。 比较:

  • sudo !!<enter> ,均来自手在键盘上的基本位置
  • <up><home>sudo <enter> ,如Fish 的常见问题解答中在键盘上。
  • <C-p><Ca>sudo <enter> ,无需动手即可访问,它也适用于 Bash、ZSH 等的默认设置,因此用户可以在不得不处理其他 shell 时养成可移植的新习惯。

对于!$ ,建议<alt-.>看起来不错,不是吗?

@psychoslave请停止评论所有旧问题,尤其是已关闭的问题。

还锁了这个。 它已经回答了大约五十次。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Limeth picture Limeth  ·  3评论

rwz picture rwz  ·  3评论

spacekookie picture spacekookie  ·  3评论

pluckytree picture pluckytree  ·  3评论

pawlosck picture pawlosck  ·  3评论