非程序员的GNU Emacs使用心得...... 大话Emacs—Shell Mode
大话Emacs—Shell Mode 第一回 引子
Shell Mode 是 Emacs 里面很有意思的一个模式。通常来说在 Emacs 里面运行 shell 主要有3种途径。一种是使用 Emacs Terminal Emulator。这种模式基本就是在Emacs里面模拟一个Terminal,然后在这个Terminal里面运行subShell。从用户体验角度来说呢,How to say? 他就是一个 Terminal, 是吧。另外一种途径是使用 Shell Mode。在这种模式下用户是通过一种间接的方式和 Shell 进行交互。也许有些人觉得间接这个词感觉比较不爽。其实吧,你们不正是通过操作系统,甚至应用程序,间接的和你们的机器打交道才混到现在的吗?(环顾四周,玩儿过 ENIAC 的家伙没有过来砸场子吧?)
所
以说,间接本身就是一种美。在 Emacs Shell Mode 方式中,真正和用户直接交互的实际上是一个 Shell
buffer。用户只是将命令输入到这个 Shell buffer 当中,然后由 comint.el 负责把它转交给实际的
Shell;命令产生的输出再由 comint.el 负责接收并且插入到 Shell buffer 中来。这样做有什么好处?没看出来吗?我们说到了
Shell buffer,它是个 buffer,一个普通的 buffer,一个没有任何低级趣味的 buffer!要知道 Emacs
最大的本事就是操作 buffer。也就是说 Emacs 当中能在一个 buffer
里面使用的任何功能,都可能直接朝这个地方来招呼了!不止这些,还要加上comint.el所提供的专有命令。所以在这种模式下,你所面对的不再是一个独
立的 mode,你能调动的是整个的
Emacs。从吹牛的角度说,那家伙,几乎就没有它办不了的事儿。。。是吧?除了。。。运行全屏幕的应用程序,比如说
vim。。。这个,话说,你可以使用 Terminal mode 嘛。
好了,不再罗嗦了。让我们来看几个小小的案例,初步体会一下间接的工作模式究竟带来了哪些变化。
大话Emacs—Shell Mode 第二回 半拉命令真头疼
不要说你从来就没有头疼过。做人要诚实。
在这样一个“月黑风高”的下午,当你满怀信心的在 shell
提示符前输入了一行命令,快要结束的时候,突然想起来还有一个参数。。。还不能确定他究竟应该是什么?貌似要先执行另外一条命令去确认一下。。。呃。。。在这个时候,你觉得应该怎么做?说实话,马上说,不要想!
你是不是会用 Ctrl c 杀掉这行输入,然后输入那条确认的命令。再然后,重新输入刚刚输入的那条命令。。。再再然后呢,看着屏幕上的那条刺眼的半拉子命令,告诉我,你一定想过这样一件事情———— “那么,我刚才输的那行命令不是就白输了吗?!” (外面的风,又紧了一些。。。)唉,算了吧。白输了就白输了呗,这有什么了不起的?我还是赶紧干活儿吧。我还要早点儿下班,回去关家里的窗户呢。可是,可是又有一条该死的命令被输了一半!谁能告诉我另一个命令参数究竟应该是什么?为什么越是着急就有越多的麻烦? (外面雨已经下起来了,风还是一点都没有停息。。。) 这一刻,我们的主人公终于觉得忍无可忍,“我要捍卫我的劳动成果!绝对不能让我的宝贵生命浪费在无休止的重复输入中!”(台上做振臂高呼状,台下观众西红柿臭鸡蛋准备中)
什么什么?你们要换台了?好的,好的,赶紧讲正题。 咱们前文书说过,Emacs Shell Mode 的一个显著特点就是这种间接的工作方式。用户所作的一切只是把一行行文字输入到 Shell buffer 里面去,然后由 comint.el 转交给后台的 Shell 进程。这就意味着,如果你没告诉 comint.el 把你的文字转交给 Shell,那个后台的 Shell 进程根本就不会知道你在前面已经想出几百个主意只等着算计它了。(回头瞧瞧,它还在后边傻乐呢)
现在镜头切换。在这个新的场景里面,我们的主人公是工作在 Shell Mode 里面的。现在主人公输入了一条半拉子命令,然后突然想起来需要确认一个奇怪的参数。。。现在主人公不必在振臂高呼了。只见他脸上掠过一丝难以察觉的笑容,然后向上移动光标,在屏幕上寻找一块空白干净的地方。不幸这会儿屏幕上都挺满,只见我们的主人公不慌不忙的输入 C-o 组合键,自己生成了一个空白行,然后在这块空白的区域里快速的敲下那行确认的命令,然后轻击回车,comint.el 把这行确认的命令发送到 Shell 执行,并且将命令的输出拿回到 Shell buffer,这个时候,guess what? 刚才那条输了一半的半拉子命令,还在原来的地方,跟那儿等着你呢。乐去吧你就。(台下观众开始鼓掌,凡是鼓掌的,一会儿散戏之后,都跟我到后台领冰棍吃。)
这就是间接的魅力。没说命令非得是在 Shell 提示符前才能够输入。那是 Shell 订的规矩。凭什么啊?我就不乐意跟这种 Shell 打交道。现在我们是在一 buffer 里头。在这里头我乐意怎么写,我就怎么写。等我写完了,我告诉我们家邻居,那 comint,人家乐意去找 shell,我让他们俩去打交道。我们觉得这儿舒服,我们跟这儿玩儿我们自己的。这多爽阿。
大话Emacs—Shell Mode 第三回 我叫你的名字,你敢答应吗?
《西游记》里面说有这么一集,说的是金角大王,银角大王偷了太上老君的宝葫芦,只要是一叫孙行者的名字,那猴子立刻就自己个儿的跑到这个葫芦里头化为脓水
了。后来呢,孙行者为了逃避这太上老君的宝葫芦,给自己起了无数的名字,什么叫者行孙啦,行者孙啦,甭管叫什么吧,只要金角大王叫对了他的名字,这孙悟空
都会抑制不住的跑到人家的宝葫芦里头去。
好的,好的,我只说这么小段《西游记》啊。我保证这一节只讲正题啊,而且里面一定有 code 啊。其实你们后头肯定会听到,我在这开场白里面说的《西游记》里面的情节绝对不是废话。我在这里一样有一个 “我叫你的名字,你敢答应吗?”的宝葫芦。
咱
们前文书不是说过吗?Emacs Shell Mode 是通过一个 Shell buffer 来和用户交互的。因为这是个
buffer,所以你几乎可以随心所欲作一个 buffer
能做的任何事情。包括随便想在哪儿写,随便想在哪儿删,随便想在哪儿保存和查找。在这里我们还可以用的更为复杂一些,甚至可以通过对 buffer
里面的内容进行处理,让他自动生成我们需要的命令。
这里讲一个实例给大家看看。登录到我们的一台机器上,看一下有哪些 WebSphere MQ 的 Queue Manager?
看
起来这里有 10个 Queue Mananger。现在我需要把他们都启动起来。启动 Queue Manager 的命令是 strmqm,
要命的是这个命令一次只接受一个 Queue Manager
名字作为参数。而我需要启动10个。而且每一个都很慢。我可不想像个傻瓜似得一直等在这里输入这10条命令。而且这些名字也全都起的各不一样,谁都不挨
谁,就是用循环搞着也不方便。那该怎么办呢?事实上我可以让 Emacs 来帮我构造这10条命令。做起来很简单, 因为我们是在 shell
buffer 里面,我只需要选中上面这段输出,按下 M-| 组合键,或者使用 shell-command-on-region 命令,用一行
sed 命令来处理这段选中的区域。
sed -n -e '/Ended/s/QMNAME(\([^)]*\)).*/strmqm \1/p'
回车之后,就看到这样一个 buffer 。这实际上就是一个 \*Shell Command Output*\ 的临时 buffer,显示的就是刚才那条 sed 的执行结果。这个结果正是我们想要的 10条构造好的启动命令。
什
么?你说 sed 这个东西
这么复杂,写来写去多麻烦的啊,下回万一写错了。。。是吧?多耽误事儿的?那是啊。这种复杂的玩意儿为什么要每次都写呢?我连产品的安装目录都不愿意每次
都写一遍。我可以把它定义成一个命令缩写,就叫做 sedstrmqm。这个名字好记多了吧? 方法也很简单。因为这是一个很长的命令,先用 M-b
命令数一数这行命令一共包含有多少个所谓的 word。也就是说按多少次 M-b 组合键 可以把光标从 p' 后面一路移动到 sed 前面,在这里是
10次。那么就输入 C-u 10 M-x add-global-abbrev 命令,然后用 sedstrmqm 作为缩写名就可以了。
说
了这么多了,我们刚才弄出来那10条命令在还在隔壁屋呆着呢。总得有人去把他们弄过来。拷贝粘贴当然比较没面子了。还要先搞到那个
buffer,然后再搞回这个 buffer 。。。那隔壁班的 MM 早就看的不耐烦了。既然有 MM
在座就一定要秀一点炫的东西出来。就像开头说到的金角大王那样,在 Minibuffer 里面输入 M-x come-here, 然后跟 MM
说:我叫你的名字,你敢答应吗? 回车之后在 minibuffer 提示区会出现一个 Input Buffer Name: 的提示,默认的
name 就是我们想要的 *Shell Command Output* buffer,直接回车就会看到那个 buffer
里面的内容自动的进到我们的宝葫芦里面来了。
怎
么样?好玩儿吧?会玩儿吗?没玩儿过吧?( 呃,这个好像是陈佩斯小品里头的词儿 ) 事实上,这个 come-here
也很简单,一共就两行代码。但是呢,真的很有玩儿头。 我在我自己的 Emacs 扩展里面还有一个很好玩儿的
jump,这是用在多窗口模式下的。通常我会在 Emacs 里开4个 Shell Mode
窗口登录到多台工作机器中去,当我在一个窗口里面敲完一行命令,这行命令通常也需要在另外的机器上运行一遍。在这个时候我会告诉他
jump!就是自动跳到另外的窗口中去,省得我再把它拷贝粘贴过去了。jump 的代码也很简单,起作用的也就两三行。下回我们讲到多窗口的时候再讲。
好了,今天的评书连播节目到此结束。听众朋友们,下次节目请关注我们的节目预告。请大家一起说,我们的口号是,让我们把工作都玩儿成游戏吧!!! (全体演员上台鼓掌,鞠躬,后台领冰棍去喽。。。。)
(defun come-here (&optional arg) "Bring content from specific buffer to current buffer" (interactive (list (let (( arg (read-buffer "Input buffer Name: " "*Shell Command Output*") )) (insert-buffer-substring (get-buffer arg)) )) ) )
posted on 2010-08-17 15:39 David Young 杨博华 阅读(2069) 评论(2) 编辑 收藏 举报