跳到主要內容

sublime——解決從命令提示符輸入數據的問題

· 閱讀需 1 分鍾

Sublime Text默認的編譯配置會掠過scanf等輸入函數,直接在輸出窗口顯示運行結果,當需要輸入數據時很不方便。其實可以自己修改sublime的編譯配置來達到目的。

假設%DIR%是sublime安裝目錄;

找到%DIR%\Packages\C++.sublime-package文件,復制一份到其它目錄,把文件後綴改為zip,解壓後找到C++ Single File.sublime-build文件,可用記事本打開並復制內容;

選擇sublime菜單->工具(Tools)->編譯系統(Build System)->新編譯系統(New Build System),新建一個編譯系統,把剛剛復制的內容粘貼到新建的文件中;

修改其中的"variants"項下面,"name": "Run"後面的"shell_cmd"項;

假設原來是:

"shell_cmd": "g++ -m32 "${file}" -o "${file_path}/${file_base_name}" && "${file_path}/${file_base_name} ""

則修改為:

"shell_cmd": "g++ -m32 "${file}" -o "${file_path}/${file_base_name}" && start cmd /c "${file_path}/${file_base_name}""

CTRL+S或點擊菜單文件(File)->保存(Save)保存文件,命名為User-C++.sublime-build(或其它)。

大功告成。

Sublime Text——便攜版編譯環境配置

· 閱讀需 3 分鍾

實驗室電腦沒有GCC,於是在U盤裡復制了一份MinGW的C++編譯環境。由於懶得每次配置環境變量,就想把MinGW放到Sublime目錄裡,直接使用。

但sublime的編譯系統默認的工作目錄是目標文件所在的目錄,所以編譯時提示找不到g++命令。由於U盤的盤符經常會改變,所以也無法固定設置。找了很久,終於找到了辦法。

sublime定義了一組特殊變量:

$file_path
The directory of the current file, e.g. C:\Files.
$file
The full path to the current file, e.g.C:\Files\Chapter1.txt.
$file_name
The name portion of the current file, e.g.Chapter1.txt.
$file_extension
The extension portion of the current file, e.g.txt.
$file_base_name
The name-only portion of the current file, e.g.Document.
$folder
The path to the first folder opened in the current project.
$project
The full path to the current project file.
$project_path
The directory of the current project file.
$project_name
The name portion of the current project file.
$project_extension
The extension portion of the current project file.
$project_base_name
The name-only portion of the current project file.
$packages
The full path to thePackagesfolder.
其中,$packages是可以定位到sublime安裝目錄中的 "Data\Packages" 目錄的。

配置方法

假設%DIR%是sublime安裝目錄;

復制MinGW目錄到%DIR%\Data\Packages目錄;

找到%DIR%\Packages\C++.sublime-package文件(注意和上面的Packages目錄不是同一個),復制一份到其它目錄,把文件後綴改為zip,解壓後找到C++ Single File.sublime-build文件,用記事本打開它,復制內容;

選擇sublime菜單->工具(Tools)->編譯系統(Build System)->新編譯系統(New Build System),新建一個編譯系統,把剛剛復制的內容粘貼到新建的文件中;

修改"working_dir" 後面的"${file_path}" 為"${packages}\MinGW\bin"(g++.exe等所在目錄),其他的也可以根據需要自己修改,注意反斜槓要轉義;

CTRL+S或點擊菜單文件(File)->保存(Save)保存文件,命名為User-C++.sublime-build(或其它)。

大功告成。

數組名和指針那點事

· 閱讀需 6 分鍾

今天在查數組名的意義的時候,聯系到指針的知識,對指針有了一種新的理解。

數組是一種特殊的變量,數組名具有雙重含義(初始):

指向數組第一個成員的指針(如果是多維數組則數組成員也為數組);

代表數組本身(其實說成"指向整個數組的指針"更合適)。

一直對第二個含義不太理解,因為感覺上比較抽象,不知道有什麼實際意義。

今天看到一個例子,終於開悟。

int ary[3];
printf("ary = %p\n" "ary + 1 = %p\n", ary, ary + 1);
printf("&ary = %p\n" "&ary + 1 = %p\n", &ary, &ary + 1);

輸出結果:

ary = 0xffb38dc8
ary + 1 = 0xffb38dcc
&ary = 0xffb38dc8
&ary + 1 = 0xffb38dd4

這就比較有意思了,很明顯,ary和&ary都指向了數組的首地址; ary+1相對ary增加了4,一個int型的長度,指向數組第二個成員首地址; 而&ary+1相對&ary則增加了3*4=12,正好是整個數組的大小。

因此數組名稱的第二個含義是只有當數組名前有&時才體現(可能還有其他情況),單獨使用時則相當於一個指向數組成員類型的指針(初始指向第一個成員首地址,另注意數組成員也可以是數組)。

所以對於一個一維數組int ary[3],它的數組名的含義有兩層:

1):
int pAry = ary; //pAry复制了ary的第一层含义
// OR:
// int pAry = &ary[0];

2):
typedef int ARY[3];
ARY *pAry = ary; //pAry复制了ary的第二层含义

以前有一個疑惑。對於二維數組ary2[3][3],ary2,ary2[0]和&ary2[0][0]的值是一樣的,都是整個數組的首地址。但*ary2的值竟然也是一樣的,這是為什麼呢?

先用之前的方法調試看看:

int ary2[3][3];
printf("ary2 = %p\n" "ary2 + 1 = %p\n", ary2, ary2 + 1);
printf("*ary2 = %p\n" "*ary2 + 1 = %p\n", *ary2, *ary2 + 1);

輸出結果:

ary2 = 0xff9fa4a0
ary2 + 1 = 0xff9fa4ac
*ary2 = 0xff9fa4a0
*ary2 + 1 = 0xff9fa4a4

首先ary毫不意外地體現了數組名的第一層含義: 指向數組第一個成員的指針。由於是二維數組,所以數組的第一個成員也是一個數組,它擁有3個整型成員,大小是12字節。所以ary2+1相對ary2增加12。

那麼*ary2中ary2到底體現的哪一層含義呢?*ary2的實際意義又是什麼?

明顯,ary2+1相對ary增加了4,一個整型的大小,所以ary2是相當於ary2[0]的第一層含義的,即指向ary2[0]的第一個成員ary[0][0]。反推回去,如果ary2中ary2是第二層含義(指向整個數組的指針)的話,那ary2應該得到的是整個數組的數據,而不是一個指針值。所以ary2中ary2是體現的第一層含義,即指向數組第一個成員(ary2[0])的指針。

但是這樣解釋新的問題又來了,運算符不是取出指針指向的值嗎?那ary2[0]取出的應該是什麼呢?應該是ary2[0]這個數組!但我們得到的結果呢?是一個int*型的指針!

這個問題折磨了我很久。它看起來並不重要,因為這不影響我們的實際操作,只要知道結論就夠了。但強迫症還是讓我被迫想出一個說服自己的說法:

問題的關鍵還在於開篇對數組名的解讀。數組的名稱可以當成數組本身的指針,也可以當成數組的第一個成員的指針。對於一維數組,這樣的描述看上去沒有問題,因為ary是可以取出數組第一個成員的值的,數組名像指針一樣。但到了二維數組,情況就不一樣了。直接取二維數組名ary2的值取出來的是ary2[0][0]的地址值,對數組名進行運算,*ary2取出來的還是ary2[0[0]]的地址值。

所以認為,編譯器並沒有為數組名在內存中分配空間,而是由編譯器自己做了一個簡單的映射,將數組名的值設為其第一個類型為數組的定義類型的成員的地址(比如int ary[][]的定義類型就是int),然後由編譯器對不同的操作請求對數組名做出不同的解釋。比如,對於三維數組int ary[2][2][2],編譯器把標識符ary[i][i]的值設為ary[i][i][0]的地址值,而對於標識符ary[1],由於ary[1]的第一個成員ary[1][0]不是int型,所以繼續拆分,直到找到第一個int型的成員ary[1][0][0],將ary[1][0]的值置為ary[1][0][0]的地址值。

由此類推,ary, ary[0], ary[0][0]它們的值是一樣的!都是ary[0][0][0]的地址值!不同的只是它們各自管理的內存空間範圍不同而已,並且它們管理的空間起點是相同的,都是ary[0][0][0]的首地址。注意,數組名的值都是直接被編譯器記錄的,而不是寫入內存,所以是不能對數組名賦值的,對數組名的操作其實是對其具有內存空間的成員的操作。這點和指針不一樣,因為指針本身其實是一個變量,它自己本身是有內存空間的,所以多級指針和多維數組變量名有本質區別!指針是一級一級的依次取值,才能得到最裡層的數據,而數組是名依靠映射關系所以直接取得數據。

關於Visual Studio中printf(printf_s)函數用%n輸出值的問題

· 閱讀需 4 分鍾

今天遇到件有趣的事。看到有人問以下代碼為什麼出錯:

scanf(...);
printf("%n...");

在下才疏學淺,也是剛開始學習,以前並沒有注意到輸入輸出函數還有個%n可以用,實在汗顏。就查詢了%n的含義:

將到此字符之前為止,一共輸出的字符個數保存到一個整型變量,不輸出文本。

意思差不多理解了,所以我給他的代碼加了一個指向整型變量的指針:

int val;
// ...
printf("%n...", &val);

一調試運行,還是報錯,選擇繼續調試,VS拋出異常:

Unhandled exception at 0x00007FF8A866765C (ucrtbased.dll) in Project1.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.

我也看不懂,感覺就是參數有問題,又把&val改成val試試,萬一呢。

還是報錯。

我看來看去,感覺沒問題,又把網上人家給的實例代碼直接復制過去:

int i,j;
printf("joidg%nkdjdkjfj%n", &i, &j);
printf("%d,%d", i, j);

這下總沒問題了吧?

可惜,還是同樣的錯誤。

我有點懵逼,又想可能網上的解釋有問題吧,或許是%n本來只能用在scanf函數中(已經測試通過),但網上給出printf中用%n的例子不少,我不認為是偶然。

又查了一波權威一點的資料:

MSDN的解釋:

Type of input expected:No input read from stream or buffer.
Type of argument:Pointer to int, into which is stored number of characters successfully read from stream or buffer up to that point in current call to scanf functions or wscanf functions.

唔,這是scanf的參數說明,但沒有在printf的說明中找到相同的,因為人家printf函數壓根沒有特別解釋參數,就給了個“格式化文本”的模糊限定。

無奈,硬著頭皮又運行了一下代碼,這次把VS C++運行庫給的警告記下了,又去查這個錯誤說明(之前因為不能直接復制忽略了......)。

在MSDN官方網站查詢“n fomate specifer disabled”關鍵字,終於在某個帖子裡看到了相同問題。這是鏈接

同時也終於找到printf函數的參數說明,裡面的確有%n的說明的。這是鏈接

這下總算真相大白,原來是編譯器的問題,GNU的編譯器支持這種格式,而微軟的Visual C++不支持。

換了sublime用G++編譯試試,果然,代碼通了。

但是有個問題,我同時也用虛擬機試了Windows 7環境下VC++6.0,結果也能正常運行,原因何在?或許VC++6.0採用的標準和VS2015(本機環境)不一樣?

不過相對於這個問題,我更好奇為什麼VS的printf不支持%n格式,,而gcc卻支持。

英文不好,那個帖子看著有點頭疼。所以想找找中文博客。

果然知道了問題,查詢工作事半功倍,一下就找到了完美解決所有疑惑的博客(連解決方案都有了):

使用printf修改變量的值 —— VS2008中使用%n輸出遇到的問題及解決方法

原來是因為printf函數使用%n可以提供一個變量指針,所以允許printf修改一個變量的值,存在安全隱患,VS就默認禁止了這種用法。而且提供了開啟的方法:定義一個宏控制就行了(其實VS很多地方採用這種方法提供配置,只是自己不知道)。

#define _set_printf_count_output 1

反思一下,從同樣的地方查資料,為什麼自己連根毛都沒找到,人家卻能完美解決問題呢?這是一種能力體現,查閱文獻不是一件非常簡單的事情,也是需要技巧和經驗的積累。

善於發現,善於思考,善於學習。

共勉。

PS. 突然發現s_s這個符號好可愛的有沒有。

Ubuntu某些用戶無法通過SSH遠程登陸問題

· 閱讀需 2 分鍾

網上看到很多博客都是解決root用戶無法登陸的,也不知道是不是因為是虛擬主機自動配置好的原因,我的ubuntu直接可以root登陸。這裡也貼一下root用戶無法登陸的解決方案。

修改ssh配置文件:

vi /etc/ssh/sshd_config

找到PermitRootLogin yes,去掉注釋;或者把no改為yes;沒有則添加。

但是我的問題並不是這個,我的root用戶可以登陸。但我之前創建的一個新用戶newuser,通過puTTY登陸時提示:

error: server unexpectly closed network connection!

網上找了一些不多的解決方案(更多是解決root用戶不能登陸的),其中有一個:

修改/etc/ssh/sshd_config配置文件,配置<AllowUsers newuser root>。

很遺憾,失敗。

後來靈機一動,查看了/etc/passwd文件,對比發現newuser和root的最大區別:

root的用戶組是root,而newuser之前為了設置ftp的特殊訪問權限(不限制目錄)而設置成了ftp用戶組,然後為了增加權限給添加到了root組(其實好像沒有鬼用,還是修改sudoer給sudo權限來得有用),所以newuser的用戶組為,root,ftp。

鬼使神差(死馬當活馬)地,把newuser添加到了newuser用戶組,然後訪問,哈,竟然成了!

不過,好像每個用戶最多只能屬於兩個組,所以現在ftp用戶組被擠下去了,就只能把root組去掉而重新設置了ftp組。

另外,之前在/etc/ssh/sshd_config文件添加了行<AllowUsers newuser root>,注釋掉後發現並不影響(也對,不然之前沒有的時候root為什麼可以登陸),應該是ubuntu默認Allow all user了。


1/15/2018

後來才知道,【1】處所謂的把ftp擠下去了才是重點。並不是要用戶組和用戶名相同才能登陸,而是用戶組不能包含ftp。可能是為了限制ftp用戶的權限吧。

之所以知道這個是因為後來手賤把ftp用戶組添加上去了......然後......嗝。

取消了ftp用戶組,果然又可以了!

之前說了添加ftp用戶組是為了方便特殊權限的ftp訪問,其實我在vstpd.conf中配置了特殊訪問用戶列表(默認文件/etc/vsftpd.chroot_list),取消了ftp用戶組後並沒有任何影響(不知道和配置的那個東西有沒有關系)。

[轉載]Tmux 速成教程-技巧和調整

· 閱讀需 61 分鍾

轉自:http://blog.jobbole.com/87584/

簡介

有些開發者經常要使用終端控制臺工作,導致最終打開了過多的標籤頁。如果你也是他們當中的一員,或者你正在實踐結對編程,那麼我推薦你讀一讀這篇文章。從上個月開始,我開始大量使用 Tmux 並且發現 Tmux 非常實用,所以我想應該寫一篇文章,與諸位分享一些有關使用 Tmux 的建議和專業方案。本文將先介紹 Tmux 是什麼,然後講解如何使用 Tmux,才能使其同 Vim 結合起來,打造出更高效、更優雅的終端工具。

本文將會包含以下內容:

  • Tmux 的基礎
  • Tmux 中最棒的功能
    • 窗口(Window)
    • 窗格(Pane)
    • 會話(Session)
    • 快速在文本間移動光標或復制文本
    • 非常輕巧的結對編程功能
  • 調整 Tmux 以增強其同 Vim 的集成度
    • 調整背景的配色方案
    • 調整光標的形狀
    • 調整粘貼時的文本縮進
  • 其他能夠提升 Tmux 體驗的工具或技巧
    • 用 Tmuxinator 自動創建會話
    • 改變 Tmux 狀態欄的顏色
請注意,在撰寫本文的過程中,我安裝了以下這一組軟件,並在測試時使用了這些版本:
  • Tmux 1.9a
  • Vim 7.4
  • iTerm 2.1
  • Mac OS (Mavericks and Yosemite)
讓我們開始吧!

基礎知識

什麼是Tmux?

Tmux 是一個工具,用於在一個終端窗口中運行多個終端會話。不僅如此,你還可以通過 Tmux 使終端會話運行於後臺或是按需接入、斷開會話,這個功能非常實用。稍後,我們將會看到如何充分地利用這個功能。

如圖所示,這就一個是 Tmux 的會話:

從圖中我們可以看出:

  • 左側:Vim
  • 右側:系統 Shell
  • 左下方:Tmux 會話的名字(“pomodoro-app”)
  • 下方的中部:當前會話中的 Tmux 窗口(“app log”、“editor”和 “shell”)
  • 右下方:當前的日期

如何安裝 Tmux?

在 Mac OS 中安裝:

  • 安裝 Homebrew
有關安裝 homebrew 的詳細的信息可以參考這裡
  • 安裝 Tmux

在 Ubuntu 中安裝:

在終端輸入如下命令:

Tmux 的快捷鍵前綴(Prefix)

為了使自身的快捷鍵和其他軟件的快捷鍵互不幹擾,Tmux 提供了一個快捷鍵前綴。當想要使用快捷鍵時,需要先按下快捷鍵前綴,然後再按下快捷鍵。Tmux 所使用的快捷鍵前綴默認是組合鍵Ctrl-b(同時按下Ctrl鍵和b鍵)。例如,假如你想通過快捷鍵列出當前 Tmux 中的會話(對應的快捷鍵是 s),那麼你只需要做以下幾步:
  • 按下組合鍵Ctrl-b(Tmux 快捷鍵前綴)
  • 放開組合鍵Ctrl-b
  • 按下s
這裡有一些小建議:

首先我建議對調Ctrl鍵和Caps-Lock鍵的功能。

通過按下Caps-Lock鍵來代替Ctrl鍵將會非常實用。因為在編碼過程中,你需要頻繁地按下Ctrl鍵,而由於Caps-Lock與手指在鍵盤的起始位置處於同一直線,所以按下Caps-Lock鍵會更加容易、便捷。

其次,我建議將 Tmux 的快捷鍵前綴變為Ctrl - a。用Caps-Lock鍵替代了Ctrl鍵之後,由於Caps-Lock鍵與a鍵離得更近,所以按下Ctrl - a就將會比按下Ctrl - b更容易、更便捷。

若要將快捷鍵前綴變更為Ctrl-a,請將以下配置加入到 Tmux 的配置文件~/.tmux.conf中:

Tmux 的配置文件

每當開啟一個新的會話時,Tmux 都會先讀取~/.tmux.conf這個文件。該文件中存放的就是對 Tmux 的配置。

小提示:如果你希望新的配置項能夠立即生效,那麼你可以將下面這一行配置加入到文件~/.tmux.conf中。

這樣配置了之後,每當向~/.tmux.conf文件中添加了新的配置,只需要按下Ctrl-b r就可以重新加載配置並使新的配置生效,從而免去了開啟一個新的會話。

Tmux 中最棒的功能

提示:下面這截圖也許與你使用 Tmux 時看到的界面略有不同。這是因為我修改了 Tmux 的狀態欄配置,如果你也想修改成和截圖中一樣的效果,那麼可以參照“美化 Tmux 的狀態欄”這一節中的步驟。

窗格

我認為沿豎直方向分割屏幕是個不錯的主意,這樣我就可以在一邊使用 Vim,而在另一邊查看代碼運行結果,如果需要的話,有時我還會再打開一個控制臺。下面我就要講解如何利用 Tmux 實現這一切。

從圖中可以看出:

  • 左側:Vim(左上方是一個 Ruby 的類文件,左下方是針對這類編寫的測試文件)
  • 右側:一個 Bash 的會話
要創建一個豎直放置的窗格很容易,待開啟了一個 Tmux 會話之後,只需再按下Ctrl-b %,一個豎直窗格就出現了。另外,若要把屏幕沿水平方向分割,則只需要按下Ctrl-b "。在 Tmux 的窗格間移動光標也很簡單,只需要先按下 Tmux 的快捷鍵前綴,然後再按下對應的方向鍵就可以讓光標進入到目標窗格了。

窗口

在Tmux中,窗口是個窗格容器,你可以將多個窗格放置在窗口中,並根據你的實際需要在窗口中排列多個窗格,也是完全取決於你的需要。例如,我經常是這樣做,先開啟一個叫作“server”的窗口用於運行應用程序的服務器(在這個窗口中可以看到服務器的日志),然後開啟另一個叫作“editor”的窗口用於編寫代碼。在這個窗口中有兩個窗格,一個用於 Vim,一個用於運行測試代碼。最後再開啟一個叫作“shell”的窗口用於通過 Bash shell 運行命令。Tmux 的窗口功能非常實用,因為在一個窗口中可以創建出多個窗格,這樣在一個窗口中就能同時查看所有窗格內容,通過這種方法可以高效地利用有限的屏幕空間。

在 Tmux 的會話中,現有的窗口將會列在屏幕下方。下圖所示的就是在默認情況下 Tmux 列出現有窗口的方式。這裡一共有三個窗口,分別是“server”、“editor”和“shell”。

若要創建一個窗口,只需要按下Ctrl-b c;若要切換窗口,只需要先按下Ctrl-b,然後再按下想切換的窗口所對應的數字,該數字會緊挨著窗口的名字顯示。

會話

一個 Tmux 會話中可以包含多個窗口。會話功能非常簡單易用,例如可以為一個特定的項目創建一個專用的 Tmux 會話。若要創建一個新的會話,只需要在終端運行如下的命令: 假設我還需要開發另一個項目,於是我就會為此再新建一個會話。雖然進入了新的會話,但是原來的會話並沒有消失。所以我可以在稍後回到之前的會話繼續工作。若要創建一個新的會話,只需要按下Ctrl-b :,然後輸入如下的命令: 除非顯式地關閉會話,否則 Tmux 的會話在重啟計算機之前都不會消失。只要還沒有重啟計算機,你都可以自由地從一個項目的會話跳轉到另一個。

在 Tmux 的會話間切換

若要獲取現有會話的列表,可以按下Ctrl-b s。下圖所示的就是會話的列表:

列表中的每個會話都有一個 ID,該 ID 是從 0 開始的。按下對應的 ID 就可以進入會話。如果你已經創建了一個或多個會話,但是還沒有運行 Tmux,那麼可以輸入如下命令以接入已開啟的會話。

在文本間快速移動光標,復制文本

在 iTerm2 中,要想快速地復制內容就不得不鍵盤和鼠標一起用,這一點我一直很不喜歡。我想一定會有不需要使用鼠標且更快捷的復制方法。幸運的是,Tmux就提供了只用鍵盤就可以完成復制的功能,這源於 Tmux 是從命令行啟動的,而在命令行界面是無法使用鼠標的。

在文本間移動光標

在 Tmux 中可以使用與 Vim 極為相似的方式在文本間移動光標。正如你熟知的那樣,用k鍵可以將光標移動到上一行,用w鍵可以向後移動一個單詞等等。而且還可以通過把 Tmux 設為 vi 模式,使其與 Vim 的操作更加接近。為此,需要將以下配置加入到文件~/.tmux.conf中。

將復制下來的文本發送到系統的剪貼板中

在默認情況下,當從 Tmux 中復制文本時,復制下來的文本只能粘貼到同一個 Tmux 會話中。若要使復制下來的文本可以粘貼到任何位置,就需要讓 Tmux 將文本復制到系統的剪貼板。為此,我們需要這樣做:

安裝 retach-to-user-namespace。用 brew 安裝的話將會非常簡單,只需要運行下面這條命令:

在配置文件~/.tmux.conf中加入以下內容:

Select and copy text

既然已經設置成了 vi 模式,也安裝了 rettach-to-user-namespace,下面就讓我們來看看如何從 Tmux 的會話中復制文本吧。假設要復制的是 IP 地址,於是我們先運行了ifconfig命令。接下來就請跟隨以下的步驟:

首先按下Ctrl-b [進入復制模式,然後可以看到一小段高亮的文本出現在了屏幕的右上角 (“[0/0]”)(如下圖所示)。

接下來就可以像在 Vim 中一樣用jklh等鍵在文本間移動光標了。

把光標移動到想復制的文本上後再按下空格鍵就可以開始選擇文本了(這和在 Vim 中復制文本的步驟一模一樣)。

選擇完要復制的文本後再按下回車鍵。

這樣 IP 地址就復制下來並可以粘貼到任何地方了。

讓復制文本的操作更像 Vim

你還可以設置 Tmux 使用v鍵選擇文本,用y鍵復制文本。為此只需要將下面的配置項加入到配置文件~/.tmux.conf中。

高效的結對編程

你可以將 Tmux 會話的地址分享給他人,這樣他們就可以通過 SSH 接入這個會話了。由於會話是建立在 SSH 之上的,所以不會產生額外的開銷。通過使用高速的互聯網,對於那些連接到遠程會話上的用戶而言,他們會覺得這個會話就是運行在本地的。

在Tmux 中使用 Tmate

Tmate 是一個 Tmux 的管理工具,使用它不但能夠輕松地創建 Tmux 會話而且還能夠通過互聯網把該會話共享給其他人。若要使用 Tmate 共享 Tmux 會話,請按照以下步驟操作:
  • 安裝 Homebrew
  • 安裝 Tmate
  • 使用 Tmate 開啟一個新的會話
  • 從 Tmux 的會話中復制由 Tmate 產生的 SSH URL。如下圖所示,請注意屏幕下方的信息“[tmate] Remote session: ssh …”:
  • 利用剛剛復制下來的 URL 就可以邀請其他人通過 SSH 訪問你的會話了。
了解了如何利用 Tmux 的結對編程功能之後,還可以再利用您所喜愛的運營商提供的語音服務進一步加強會話交互性。

調整 Tmux 以增強其同 Vim 的集成度

調整背景的配色方案

當我第一次通過 Tmux 打開 Vim 時,我發現 Vim 的顏色沒有正確顯示。正如下圖所示,只有有字符的地方才有背景色。

這個問題是因為通過 Tmux 運行 Vim 需要配置一個特殊的終端參數(term parameter)。請將下面這行配置添加以你的 ~/.vim 文件中。

在更新了配置文件 ~/.vimrc 以後,顏色應該就可以正確顯示了。

調整光標的形狀

在默認情況下,當通過 Tmux 運行 Vim 時,無論當前 Vim 是處於插入模式、可視模式還是其他模式,光標的形狀都是一樣的。這樣就很難判斷當前的 Vim 模式是什麼。若要避免這個問題,就需要讓 Tmux 通知 iTerm 更新光標的形狀。為此,需要將以下配置加入到文件 ~/.vimrc 中。
if exists('$ITERM_PROFILE')
if exists('$TMUX')
let &t_SI = "<Esc>[3 q"
let &t_EI = "<Esc>[0 q"
else
let &t_SI = "<Esc>]50;CursorShape=1x7"
let &t_EI = "<Esc>]50;CursorShape=0x7"
endif
end

在這裡我要感謝 Andy Fowler,是他最先分享了調整光標的形狀這個技巧

調整粘貼時的文本縮進

在 Vim 中粘貼文本時可能會遇到這樣的問題,有時文本的縮進會發生變化,特別是在粘貼大量的文本時,這個問題會更加明顯。雖然可以通過在粘貼前執行:set nopaste來解決這個問題,但是這裡還有一種更好的解決方法。就是把下面這段配置加入到配置文件~/.vimrc中,這樣 Vim 就會自動地阻止粘貼文本時的自動縮進。 在這裡我要感謝 Marcin Kulik,是他最先分享了這個技巧

其他能夠提升 Tmux 體驗的工具或技巧

Tmuxinator (為項目自動創建會話)

假設你正在開發應用程序 A。在開發過程中,經常要創建 Tmux 會話,會話中包含“server”、“editor”(用於編寫代碼)和“shell”(用於運行系統命令)這 3 個窗口。不僅如此,在一天之中的某個特定的時間你還需要臨時進入到應用程序 B 的開發工作中。於是你又不得不創建另一個會話,雖然有略微的不同(比如目錄和某些命令),但是會話中還是要包含應用程序 A 中的那 3 個窗口。但是有了 Tmuxinator,你就可以為每個Tmux 會話聲明一個配置,然後用 1 條命令就能創建出這個會話了。這功能太棒了,不是嗎。

Tmuxinator 是一個 Ruby 的 gem 包,可用於創建 Tmux 的會話。它的工作方式是先在配置文件中定義會話中的細節,然後用 1 條命令創建出這些會話。下面就讓我們看看如何安裝 Tmuxinator 以及如何添加配置來為指定項目開啟一個會話。可以通過運行如下命令安裝 Tmuxinator 的 gem 包。

安裝好了 Tmuxinator 以後,就可以在系統 Shell 中運行tmuxinatormux命令了。下面就讓我們為上述的應用程序(有 3 個窗口,分別是“servers”, “editor” 和 “shell”)來創建一個配置文件吧。下面這條命令的作用是為這個項目創建並打開一個配置文件。 按下回車鍵後,就會自動打開文件~/.tmuxinator/project_a.yml。為了實現項目 A 所需的配置,你需要把project_a.yml的內容更新為: 一旦將上面的配置添加到了項目 A 的 Yaml 文件中,只需要運行下面這條命令就可以啟動 Tmux 的會話了。 當然如果願意的話,你也可以使用 Tmuxinator 命令的別名: 大功告成了。現在,每當想進入項目 A 的編碼工作時,就只需要運行 Tmuxinator 命令。

可以到這裡查看Tmuxinator的官方文檔。

美化 Tmux 的狀態欄

默認情況下,Tmux的狀態欄看起來是下圖這個樣子(圖中綠底部分):

我們可以根據需要改變狀態欄的外觀。對我來說,我喜歡下圖這種清爽的外觀。

為了達到上圖的效果,我將如下的配置加入到了配置文件 ~/.tmux.conf 中。

總結

在這篇文章中我們先介紹了 Tmux 的基本功能,然後介紹了 Tmux 中最棒的幾個功能。這之後介紹了一些配置以及幾個能夠提升 Tmux 體驗的工具。至此,諸位對 Tmux 的印象如何呢?你們是否也發現了什麼其他有用的功能或配置?如果有的話歡迎留言告訴我們。

感謝您閱讀本文!