开发工具 Linux 窗口之间快速切换 - 加速你的开发效率!

zw963 · 2013年10月12日 · 最后由 sanivbyfish 回复于 2013年10月15日 · 14998 次阅读

废话少说, 这是一篇在 Linux 下的各个窗口之间快速切换的文章.

先说下 Spec.

  1. 假设开发过程中, 涉及到以下界面: Terminal, Editor, Browser, 外加一个随便什么鬼玩意儿. 例如: 某个 PDF 阅读软件, 在阅读 PDF.

  2. 地球人都知道 ALT TAB, 但是最大的问题是: 如果开的多了, 你常常需要 ALT + TAB TAB ... 很多次. 在 Win 7 下, 对于系统托盘, 有类似于 Win + 0, Win + 1 的快捷键, 我相信很多 Linux 发布版也有类似功能. 如果你用的很爽, 而且也不打算换发布版, 下面不用看了.

  3. 我要求所有 UNIX Like 系统都通用 (只要有 X), 即: 使用 Linux 下一些最基本的功能来实现.

  4. 我要求在任何桌面, 按下一个快捷键, 会立即弹出我想要的以上任一窗口, 再按一次, 一定会返回到原来的窗口. 例如: 我的快捷键是: C-M 立即激活 Terminal (当然, 你可以开任意多个 TAB), C-I 会激活到 Emacs 的某个 Frame (或创建一个), C-; 会激活 Firefox.

当然你也可以任意组合, 例如: 你打开一个 pdf 再看一本书, 然后 C-m 切换到 Terminal 下写点东西, 然后直接 C-i 打开 Emacs 做点笔记, 然后再次 C-i 回到之前的 pdf, C-; 浏览下网页, 再次 C-; , 又返回 pdf...

  1. 好吧我知道很多 XD 都是多显示器, 而且显示器很大, 常常拆分成好几块儿, 鼠标玩的也很转, 如果你那样很爽, 我没有任何意见, 这只是我个人的习惯, 分享给同好者吧.

准备工作

  1. 首先, 你需要一个叫做 Xbindkeys 的工具. 传送门: http://www.nongnu.org/xbindkeys/ 他的用途是: 绑定任意全局快捷键到一个脚本或命令, 他是基于纯 X 的. 你甚至不需要 Gnome 或 KDE , 仅仅启动一个 Xterm, 就可以用它.
  2. 你需要一个 dropdown Terminal, 就是一个下拉式的全屏 Terminal. 当你按下快捷键时, 自顶向下, 会弹出 Terminal. 当你再次按下快捷键或点击任何其他窗口时, 自动隐藏了. 如果你没有, 我推荐一个足够简单, 对我来说也足够好的 XFCE Terminal. 传送门: http://git.xfce.org/apps/xfce4-terminal/.
  3. wmctrl, 很多发布版应该带这个小命令了, 可以让你激活指定的窗口, 甚至不同 Work Space 之间也可以切换. 如果碰巧你没有, 传送门: http://tomas.styblo.name/wmctrl/
  4. 你需要 xprop 命令... 我想哪怕是最老的 UNIX , 只要有 X 都应该有这个命令吧 ?

步骤


首先我们要编写两个公共函数, 这些函数可以方便的在所有脚本中被使用.

这些公共函数你可以单独放在一个文件中, 然后稍后通过 find, 全部 source, 你可以直接放到你的 .bashrc 里面.

第一个函数主要用来获取某个窗口的 id , 名称之类的信息, 我的函数是这样的

function GET_CURRENT_FRAME_VARIABLE () {
    if [ $(uname -o) != Cygwin ]; then
        CURRENT_WND_ID=$(xprop -root _NET_ACTIVE_WINDOW 2>/dev/null |cut -d ' ' -f 5|cut -d"," -f1) &&
        CURRENT_WND_NAME=$(xprop -id $CURRENT_WND_ID _NET_WM_NAME 2>/dev/null |cut -d '"' -f2) &&
        echo "[0m[32m($CURRENT_WND_ID)[0m"

        [ $(xprop -id $CURRENT_WND_ID WM_WINDOW_ROLE |cut -d'"' -f2) == "xfce4-terminal-dropdown" ] &&
        DROPDOWN_TERMINAL=true
        return 0
    fi
    return 1
}

export -f GET_CURRENT_FRAME_VARIABLE

CURRENT_WND_ID 获取任意窗口的 ID CURRENT_WND_NAME 获取对应名称.

最后一段, 是判断当前 Terminal 窗口是不是 xfce4-terminal-dropdown. 之所以这样做, 是我可能会开两个 Terminal, 一个非 dropdown, 一个 dropdown, 标题一模一样. 只能通过这种方式判断了. 如果当前 Terminal 是 dropdown, 那么返回一个值为 true 的变量 DROPDOWN_TERMINAL, 否则变量值为空.

记得写完后, source .bashrc


第二个函数是一个通用模板, 其中保存了一大坨用来切换窗口的公共代码

function switch_to () {
    GET_CURRENT_FRAME_VARIABLE &>/dev/null

    eval local $2_wnd_id=$(cat $SHM_TMP/.$2_wnd_id) &>/dev/null
    eval local before_$2_wnd_id=$(cat $SHM_TMP/.before_$2_wnd_id) &>/dev/null

    if [ $CURRENT_WND_ID == "$(eval echo \${$2_wnd_id})" ]; then
        wmctrl -i -a "$(eval echo \${before_$2_wnd_id})"
    elif [ "$(egrep -e "$1" <<< "$CURRENT_WND_NAME")" -a $CURRENT_WND_ID != "$(eval echo \${$2_wnd_id})" ]; then
        echo $CURRENT_WND_ID > $SHM_TMP/.$2_wnd_id &&
        wmctrl -i -a "$(eval echo \${before_$2_wnd_id})"
    else
        [ "$DROPDOWN_TERMINAL" ] || echo $CURRENT_WND_ID > $SHM_TMP/.before_$2_wnd_id

        [ $CURRENT_WND_ID != "$(eval echo \${$2_wnd_id})" ] && wmctrl -i -a "$(eval echo \${$2_wnd_id})" ||
        wmctrl -a "$1" &>/dev/null || exec ${@:3} &
    fi
}

export -f switch_to

这逻辑稍稍有点杂乱, 但是基本原理可以说下, 不过提前声明, 你完全可以无视这一坨代码, 你只要稍后按照我的方式调用即可.

1) 如果不是 Emacs 窗口, 那么首先保存当前窗口的 id 到 $SHM_TMP 目录下的某个文件中. 2) 切换到之前保存的 id 对应的窗口, 如果不成功, 尝试选择一个, 还不行, 新启动一个. 3) 切换成功之后, 将激活的这个 Emacs 窗口 id 保存起来. 4) 如果是原先的 Emacs 窗口, 切换回到来之前的窗口. 5) 如果是一个新的 Emacs 窗口 (我常常会存在多个), 那么将新的窗口 id 存起来. 稍后快捷键就在新的窗口和原窗口之间切换了.

大概懂点编程的人应该都可以看个大概懂了...

几个地方稍稍提下:

1) GET_CURRENT_FRAME_VARIABLE 调用的之前定义的那个函数. 2) $SHM_TMP 是我的一个全局变量, 我设的是 /dev/shm, 你也可以设 /tmp, 随你. 3) wmctrl -i -a 是切换到 id, 格式大概为: 0x03e00075, 你可以 wmctrl -l 看看. wmctrl -a 是按照名字切换, 可以模糊匹配.

设定脚本快捷键

home 下面新建一个 .xbindkeysrc, 加入以下内容:

# cat emacs_frame

"switch_to_firefox"
Control + semicolon

"emacs_frame"
Control + i

然后启动 xbindkeys & 启动 daemon. 你应该将这个加到 .bashrc 当中, 让它自动启动.

最后一步, 编写在 xbindkeys 中调用的那两个脚本

因为有了上面那一坨公共逻辑代码, 脚本写起来就很简单了, 只需要一行.

# cat emacs_frame
#!/bin/sh


emacs_frame_pattern=$($MY_EDITOR -e '(concat "  " "-" "  " invocation-name "@" system-name)'|sed 's#"##g')
switch_to "$emacs_frame_pattern" "emacs" "$MY_EDITOR -nc --eval (nav)"
# cat switch_to_firefox 
#!/bin/sh

# 使用方式: switch_to '标题模板' ' 关键字' '调用的命令'
switch_to 'Mozilla Firefox' "firefox" "firefox [email protected]"

最后, 重要的一点: 记得给这个文件加 x 执行属性. chmod +x emacs_frame switch_to_emacs.

完了, 写了一堆, 其实一点都不复杂... 写到这里, 其实你也看出来了, dropdown 的 Terminal, 并非必须的. 你完全可以将 Terminal 放到一个新的 Workspace, 来达到同样的 (当未激活时, 完全隐藏窗口) 效果, 只不过, 少了 dropdown 特效而已.

好吧, 我有理由相信在 Apple 占大多数的咱社区, 对这文章有兴趣的不多, 如果你觉得没什么用, 嘴下留情呀. 也许有人觉得有用呢?

你就不能用 Emacs 看 PDF 么

#2 楼 @bhuztez

回 B 大, Emacs 的 PDF 功能那就是个玩具呀! 首先它是整个加载的, 速度超级慢, 会加载全部页面, CPU 负荷超高, 即使加载完成, 效果也很悲剧. 貌似都不知道怎么放大.

可以试试平铺窗口管理器,比如 xmonad, awesome wm

感谢分享

深度定制,真的可以方便自己。

试试 @tualatrix 的 Manico

类似的工具: mac 下我用 apptivate

linux 下 绑定快捷键:

#!/bin/sh

# jump-or-exec by wmctrl

REXP="$1"
CMD="$2"

wmctrl -x -a $REXP && exit
exec $CMD &

楼主这种定制纯粹是折腾。

  1. 关掉一些开发过程中不需要的应用,保证当前窗口只有你用到的工具(Ubuntu 的工作区非常好用)。
  2. 养成一个较有规律的切换习惯(比如我一般 Terminital 开三个 tab, 第一个就在项目根目录可以运行 git 或者临时修改 hosts,第二个是 Rails Console,第三个是 Rails Server)。
  3. 尝试平铺式窗口管理器如 @doitian 所列出的

楼主确实整的很复杂啊, 我都是 IDE full screen, terminal 是 multi tabs, 外加 browser 跑 javascript tests。 窗口如果过多的话,可以使用 mission control 或者 alt tab, 切换代码和 terminal 的时候, 就四指切换屏幕。

真正追求效率的话只能说别开太多工作之外的窗口。 或者双机多屏工作。

#4 楼 @doitian

两种都曾经简单试过, 不得要领, 也就没有深入.

#7 楼 @as181920

道行尚浅, 谈不上深度, 目前的精力, 也不可能放到这一块. 够用即可. 我觉得这文章主要意义在于: 让大家认识这几个通用的小工具, 在即使对底层不是很了解的前提下, 尽量个性化的实现自己所需的功能. 例如: 我重启 Rails Server 以及 重启测试, 都是通过快捷键, 并且通过 notify-send 发送消息. 而且, 既然你能找到所需的窗口, 你也可以针对某个窗口定制特殊的行为, 例如: 让某个窗口的 Alt + F4 失效.

#9 楼 @gihnius 受教了, 这脚本的确很酷, exec 是神来之笔.

恭喜你重新发明了 WM……

自己用的舒服就好了,我在 Linux 下面大部分只用 Awesome,有时候有的小屏幕的机器,我用 Awesome + Gnome

现在用得不多了,原因很简单我用 Mac 了。。。。而且我开发 API 为主,不需要 browser 啦。

以前用 applescript + 系统快捷键面板, 现在用 alfred, 自己加个 hotkey launch file group 的 workflow 就可以了

一直想找一个这样功能的东西,没找到

修改了下内容, 提取了个 switch_to 方法出来, 脚本中只需要一行就行了.

我想大家就算不懂 shell, 或者不愿意看那一大坨屎一样的代码, 也可以自己写快捷键脚本了吧...

guake 一个下拉 Terminal

#9 楼 @gihnius 你好,请问一下,没在 Google 上搜到 apptivate,是在哪里下载呢?

#10 楼 @hbin 我 也是 不喜欢 折腾的人

任务栏开三行的人飘过

#15 楼 @gene_wu 怒顶 Awesome, Arch 加 Awesome 简直神了。

楼主的头像好风骚

又更新了下, 现在即使你完全不懂 bash shell, 照着我说的做, 你也可以自己随意定制快捷键喽~~

本人第一篇精华帖, 哈哈~

#21 楼 @gihnius 这个蛮不错的,你们一般都设什么快捷键

需要 登录 后方可回复, 如果你还没有账号请 注册新账号