Macbook終端vim使用系統剪切板
- 系統自帶的, 可執行程序是 /usr/bin/vim, 安裝目錄是 /usr/share/vim/, 版本7.3.
- 我使用 homebrew 后順手安裝了一次 vim, 安裝目錄:/usr/local/Cellar/vim/, 版本7.4. 可執行程序是 /usr/local/Cellar/vim/7.4.052/bin/vim , 並且有一個指向它的鏈接: /usr/local/bin/vim -> ../Cellar/vim/7.4.052/bin/vim
- 為了解決剪切板的問題, 我安裝了 macvim. 這樣還會有一份 vim: /Applications/MacVim.app/Contents/MacOS/Vim, 版本7.4 執行 which vim 的結果: /usr/bin/vim 可見, 盡管我用 homebrew 以及 macvim 安裝了新的 vim 7.4, 但是系統默認使用的還是自帶的7.3的老版本. 而執行 /usr/bin/vim --version | grep clipboard 又發現, 這個版本不支持 clipboard. 這就是問題的根本原因. 我將 /usr/bin/vim 給重命名了一下, 此時再 which vim, 就指向 /usr/local/bin/vim 了, 問題也解決了. 希望對遇到此問題的同學有幫助. 再次謝謝大家!
補充一下:
- which vim可以看到當前使用的vim是哪個,vim --version可以看到當前使用的vim支持哪些feature,'+'前綴表示擁有的feature,'-'前綴表示未擁有;
- '+clipboard'是支持使用系統剪切板的feature;
- 如果你當前使用的vim不支持clipboard,那需要brew install view裝一個新的;
- 安裝新的以后,要把這個新的vim設置為默認vim,通常使用alias設置一下別名,或者通過環境變量設置,或者刪掉舊的,做個軟連接;
- 確認+clipboard以后,在.vimrc文件中加入set clipboard=unamed,就可以在vim中使用系統剪切板了;
復制粘貼探秘
Vim作為最好用的文本編輯器之一,使用vim來編文檔,寫代碼實在是很愜意的事情。每當學會了vim的一個新功能,就會很大地提高工作效率。有人使用vim幾十年,還沒有完全掌握vim的功能,這也說明了vim的強大。而這樣何嘗不是一件好事呢,只要有的學習,就有的提高。
最近使用Vim來寫博客,發現在Vim中粘貼Python代碼后,縮進就全亂了。仔細研究了以下,原來是自動縮進的緣故,於是做如下設置
:set noai nosi
取消了自動縮進和智能縮進,這樣粘貼就不會錯行了。但在有的vim中不行,還是排版錯亂。
后來發現了更好用的設置:
:set paste
進入paste模式以后,可以在插入模式下粘貼內容,不會有任何變形。這個真是灰常好用,情不自禁看了一下幫助,發現它做了這么多事:
- textwidth設置為0
- wrapmargin設置為0
- set noai
- set nosi
- softtabstop設置為0
- revins重置
- ruler重置
- showmatch重置
- formatoptions使用空值
下面的選項值不變,但卻被禁用: - lisp
- indentexpr
- cindent
怪不得之前只設置noai和nosi不行,原來與這么多因素有關!
但這樣還是比較麻煩的,每次要粘貼的話,先set paste,然后粘貼,然后再set nopaste。有沒有更方便的呢?你可能想到了,使用鍵盤映射呀,對。我們可以這樣設置::
:map <F10> :set paste<CR>
:map <F11> :set nopaste<CR>
這樣在粘貼前按F10鍵啟動paste模式,粘貼后按F11取消paste模式即可。其實,paste有一個切換paste開關的選項,這就是pastetoggle。通過它可以綁定快捷鍵來激活/取消 paste模式。比如::
:set pastetoggle=<F11>
這樣減少了一個快捷鍵的占用,使用起來也更方便一些。
但,這是最方便的嗎?Vimer們對高效的追求永無止境。還有其他更好地方法嗎?
你可能想到了,vim寄存器。對,使用vim寄存器 “+p 粘貼即可。根本不用考慮是否自動縮進,是否paste模式,直接原文傳遞!:
"+p
要說vim寄存器,就要從vim文件間的復制粘貼說起。
Vim中,若要復制當前行,普通模式下按 yy 即可,在要粘貼的地方按 p 。這是vim將復制內容保存到了自己的寄存器中的緣故。如果在其他地方執行yy,新的內容將覆蓋掉原寄存器中內容。如果想保存原寄存器中內容而同時增加新的內容呢?這時就要在yy前增加標簽了。標簽以雙引號開始,跟着的是標簽名稱,可以是數字0-9,也可以是26個字母,然后就是復制操作,這樣就把復制內容保存到該標簽寄存器里。通過下面命令顯示所有寄存器內容::
:reg
其中注意兩個特殊的寄存器:”* 和 “+。這兩個寄存器是和系統相通的,前者關聯系統選擇緩沖區,后者關聯系統剪切板。通過它們可以和其他程序進行數據交換。
備注:
若寄存器列表里無”* 或 “+ 寄存器,則可能是由於沒有安裝vim的圖形界面所致。Debian/Ubuntu下可以通過安裝vim-gnome解決。
sudo apt-get install vim-gnome
選擇緩沖區和系統剪切板啥子區別?讓我們繼續研究。
選擇緩沖區和剪切板
不同於Windows,Linux系統里存在兩個剪切板:一個叫做選擇緩沖區(X11 selection buffer),另一個才是剪切板(clipboard)。
選擇緩沖區是實時的,當使用鼠標或鍵盤選擇內容時,內容已經存在於選擇緩沖區了,這或許就是選擇緩沖區的由來吧。
使用下面的命令查看選擇緩沖區的內容::
xclip -out
如果沒有xclip命令,Debian/Ubuntu下可以通過如下命令安裝::
$ sudo apt-get install xclip
可以使用鼠標中鍵或鍵入Shift+Insert來粘貼選擇緩沖區的內容。但對於有些GUI程序,比如gedit,只能通過鼠標中鍵調用選擇緩沖區的內容,使用Shift+Insert的話,調用的是剪切板的內容。
剪切板和Windows的剪切板類似,在選擇文字內容后,執行Ctrl + c或在菜單里選擇‘復制’的話,這時內容才存放到剪切板里。
使用下面的命令查看剪切板的內容::
$ xclip -out -sel clipboard
而使用剪切板的內容,則是Ctrl+v。 但在有些情況下,比如gnome-terminal,不能直接使用Ctrl+c,Ctrl+v,這時就要用Shift+Ctrl+c,Shift+Ctrl+v代替。
原格式粘貼
好了,了解了選擇緩沖區和剪切板,下面就是實現保留格式粘貼的完美解決方案:
方案一:
選擇文本內容
vim普通模式下按 “*p 將選擇緩沖區中內容粘貼進來
方案二:
復制文件內容
vim普通模式下按 “+ p 將剪切板內容粘貼進來
這時,如果要復制的內容也是vim編輯器中的內容,那么如何復制才更方便呢?
vim中的復制
vim有一個可視模式(Visual Mode),在此模式下可以選擇區域。可以在普通模式下鍵入v進入可視模式,也可以個性化一點,鍵入V進入行可視模式,或者鍵入Ctrl+v進入列可視模式。這時移動光標就可以選擇內容了。注意這時被選內容已經實時保存於選擇緩沖區了,當然你也可以鍵入”+y將此內容也保存到剪切板里,或者”ay將內容保存到標簽為a的寄存器中。但要知道,只有前兩個中的內容可以在其他程序中使用,而a寄存器中的內容只能在該vim編輯器內使用。
也可以通過鼠標來復制。這里首先要打開鼠標模式。:
:set mouse=a
這樣在普通模式下可以直接使用鼠標選擇區域復制到選擇緩沖區。但這種情況下不能復制到剪切板。
若要使用鼠標復制內容到剪切板,則需要做如下設置::
:set mouse=v
這種情況下,除了可以像上面一樣直接使用鼠標選擇區域復制到選擇緩沖區以外,還可以在右鍵菜單中選擇“復制”來保存到剪切板里。但新問題又出來了。若顯示行號,也會將行號一並選擇。你會想到,這好辦呀,如果不需要行號的話,在復制前,先執行set nonu來取消行號顯示唄。
其實沒必要這樣,如果不需要復制行號的話,用在可視模式下用鍵盤來選擇不就可以嗎?
並且,從上面的討論,我們不難得出,使用選擇緩沖區比使用剪切板要方便的多,可以節省很多步驟。
所以,最終我們得到了vim文件間復制粘貼的完美方案,文件傳輸的中轉使用選擇緩沖區。
補充:
設置vim中默認使用選擇緩沖區寄存器 “*:
set clipboard = unnamed
則可以直接通過y,p和系統選擇緩沖區進行數據交換。
(原文地址: http://blog.ossxp.com/2010/12/2190/)
vim文件間復制粘貼完美方案
- 在~/.vimrc中增加如下一行::
set mouse=v
- 復制內容到選擇緩沖區。
- 帶行號時,使用鼠標選擇內容區域。
- 不要行號,使用 “*yny 復制n行或可視模式下選擇。
- 將選擇緩沖區中內容粘貼到vim文件:普通模式下按 “*p 。
##SpaceVim和Vim共存
```vim
Can I try SpaceVim without overwriting my vimrc?
The SpaceVim install script will move your ~/.vimrc to ~/.vimrc_back. If you want to have a try SpaceVim without overwriting your own Vim configuration you can:
Clone SpaceVim manually.
git clone https://github.com/SpaceVim/SpaceVim.git ~/.SpaceVim
Then, start Vim via vim -u ~/.SpaceVim/vimrc. You can also put this alias into your bashrc.
##Simple vim config for server.
```vim
" Simple vim config for server.
" Version: 0.1
" Author: Anton Chen <contact@antonchen.com>
" Create Date: 2016-08-22 15:07:51
" Last Modified: 2018-07-24 21:53:38
let Author = 'Your Name <youremail@example.com>'
" Settings
" {{{
" Leader
let mapleader = ','
let g:mapleader = ','
" 高亮
syntax on
" 設置 256 色
let t_Co=256
" 歷史行數
set history=2000
" 文件類型識別
filetype on
" 開啟插件
filetype plugin on
" 開啟 indent 縮進
filetype indent on
" 基礎設置
set shortmess=atI " 不顯示歡迎信息
set helplang=cn " 首選幫助語言
set title " 終端標題
set magic " 開啟 magic 正則
set nobackup " 關閉備份
set nocompatible " 禁止 vi 模式
set backspace=indent,eol,start " 設置 <Backspace>
" set clipboard=unnamed " 拷貝到系統剪切板
" set whichwrap+=<,>,h,l " 左右移動跨行
set autoread " 文件在Vim之外修改過,自動重新讀入
set lazyredraw " 運行宏時不重繪
" 關閉錯誤提示
set novisualbell " 關閉閃爍提示
set noerrorbells " 關閉聲音提示
set t_vb=
set tm=500
" 配色
colorscheme molokai
let g:rehash256 = 1
" 高亮
" set cursorcolumn " 高亮當前列
" set cursorline " 高亮當前行
" 剩余 7 行時翻頁
set scrolloff=7
" 禁用鼠標
" set mouse=a
" 顯示
set ruler " 顯示當前行號與列號
set number " 顯示行號
set numberwidth=6 " 設置行號列寬度
" set nowrap " 關閉自動換行
set showcmd " 在狀態欄顯示正在輸入的命令
set showmode " 顯示當前Vim模式
" set showmatch " 當關閉如括號這樣的代碼時,光標跳轉到括號開始再跳回
" set matchtime=3 " 光標跳轉時間
" 搜索
set hlsearch " 高亮匹配
set incsearch " 開啟即時搜索
set ignorecase " 搜索時忽略大小寫
set smartcase " 字符串有大寫字母時大小寫敏感
" 縮進
set expandtab " 使用空格縮進
set smartindent " 智能縮進
set autoindent " 繼承縮進
set shiftround " 縮進寬度對齊到 shiftwidth 的整數倍
set tabstop=4 " <Tab> 寬度
set softtabstop=4 " 編輯模式下 <Tab> 寬度
set shiftwidth=4 " 自動縮進寬度
set smarttab " 插入 <Tab> 時使用 'shiftwidth'
" 補全
set wildmenu " 命令模式補全
set wildmode=full " 補全菜單樣式
set wildignore=*.o,*~,*.pyc,*.class " 排除補全
" 代碼折疊
set foldenable
" 折疊方法
" manual 手工折疊
" indent 使用縮進表示折疊
" expr 使用表達式定義折疊
" syntax 使用語法定義折疊
" diff 對沒有更改的文本進行折疊
" marker 使用標記進行折疊, 默認標記是 {{{ 和 }}}
set foldmethod=marker
" 代碼折疊自定義快捷鍵 <leader>zz
let g:FoldMethod = 0
map <leader>zz :call ToggleFold()<cr>
fun! ToggleFold()
if g:FoldMethod == 0
exe "normal! zM"
let g:FoldMethod = 1
else
exe "normal! zR"
let g:FoldMethod = 0
endif
endfun
" 上次文件編輯位置
if has("autocmd")
au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
endif
" 字體設置
if has("gui_running")
set guifont=Monaco:h14
endif
" 狀態欄
set laststatus=2 " 狀態欄高度
" set statusline=%<%f\ %h%m%r%=%k\ %m\ %r%y\ [%{(&fenc==\"\")?&enc:&fenc}%{(&bomb?\",BOM\":\"\")}\|%{&ff}]\ %-14.(%l,%c%V%)\ %P
" 轉換文件大小
function! Buf_total_num()
return len(filter(range(1, bufnr('$')), 'buflisted(v:val)'))
endfunction
function! File_size(f)
let l:size = getfsize(expand(a:f))
if l:size == 0 || l:size == -1 || l:size == -2
return ''
endif
if l:size < 1024
return l:size.' bytes'
elseif l:size < 1024*1024
return printf('%.1f', l:size/1024.0).'k'
elseif l:size < 1024*1024*1024
return printf('%.1f', l:size/1024.0/1024.0) . 'm'
else
return printf('%.1f', l:size/1024.0/1024.0/1024.0) . 'g'
endif
endfunction
" 定義狀態欄格式
set statusline=%<%1*[B-%n]%*
set statusline+=%2*[TOT:%{Buf_total_num()}]%*
set statusline+=%3*\ %{File_size(@%)}\ %*
set statusline+=%4*%m\ %F\ %*
set statusline+=%=%5*\ %r%y\ [%{(&fenc==\"\")?&enc:&fenc}%{(&bomb?\",BOM\":\"\")}\|%{&ff}]\ %-14.(%l,%c%V%)
set statusline+=%6*\ %P\ %*
" 自定義狀態欄顏色
" 終端
hi User1 cterm=bold ctermfg=237 ctermbg=39
hi User2 cterm=None ctermfg=39 ctermbg=242
hi User3 cterm=None ctermfg=251 ctermbg=240
hi User4 cterm=bold ctermfg=169 ctermbg=239
hi User5 cterm=None ctermfg=250 ctermbg=238
hi User6 cterm=None ctermfg=249 ctermbg=240
" GUI
hi User1 gui=bold guifg=#3a3a3a guibg=#00afff
hi User2 gui=None guifg=#00afff guibg=#6c6c6c
hi User3 gui=None guifg=#c6c6c6 guibg=#585858
hi User4 gui=bold guifg=#d75faf guibg=#4e4e4e
hi User5 gui=None guifg=#bcbcbc guibg=#444444
hi User6 gui=None guifg=#b2b2b2 guibg=#585858
" 文件格式
set fileformat=unix
" 新文件編碼
set nobomb " 禁止UTF-8 BOM
set encoding=utf-8
set termencoding=utf-8
" 自動識別文件編碼
set fileformats=unix,dos,mac
set fileencodings=utf-8,ucs-bom,cp936,gb18030,big5,euc-jp,euc-kr,latin1
" 如遇Unicode值大於255的文本,不必等到空格再折行
set formatoptions+=m
" 合並兩行中文時,不在中間加空格
set formatoptions+=B
" 選中顏色
hi Visual term=reverse cterm=reverse guibg=Grey
" }}}
" File type
" {{{
" Fix crontab
autocmd FileType crontab set nobackup nowritebackup
autocmd FileType python set tabstop=4 shiftwidth=4 expandtab ai
autocmd FileType ruby set tabstop=2 shiftwidth=2 softtabstop=2 expandtab ai
autocmd FileType yaml set tabstop=2 shiftwidth=2 softtabstop=2 expandtab noai nocin nosi inde=
autocmd BufRead,BufNewFile *.md,*.mkd,*.markdown set filetype=markdown.mkd
autocmd BufRead,BufNewFile nginx.conf set filetype=nginx
autocmd BufRead,BufNewFile */etc/nginx/*.conf set filetype=nginx
autocmd BufRead,BufNewFile */usr/local/nginx/conf/*.conf set filetype=nginx
autocmd BufRead,BufNewFile *.json set filetype=json
autocmd BufNewFile * exec ":call AutoSetFileHead()"
function! AutoSetFileHead()
let NewFileTime = strftime('%Y-%m-%d %H:%M:%S')
" .sh
if &filetype == 'sh'
call setline(1, "\#!/bin/bash")
call append(1, "\# Author: ".g:Author)
call append(2, "\# Create Date: ".NewFileTime)
call append(3, "\# Last Modified: ".NewFileTime)
call append(4, "\# Description: ")
call append(5, "HERE=$(cd -P -- $(dirname -- \"$0\") && pwd -P)")
normal G
normal o
endif
" python
if &filetype == 'python'
call setline(1, "\#!/usr/bin/env python")
call append(1, "\# encoding: utf-8")
call append(2, "\# Author: ".g:Author)
call append(3, "\# Create Date: ".NewFileTime)
call append(4, "\# Last Modified: ".NewFileTime)
call append(5, "\# Description: ")
normal G
normal o
endif
endfunc
autocmd FileType c,cpp,java,go,php,javascript,puppet,python,rust,twig,xml,yml,perl autocmd BufWritePre <buffer> :call <SID>StripTrailingWhitespaces()
function! <SID>StripTrailingWhitespaces()
let l = line(".")
let c = col(".")
%s/\s\+$//e
call cursor(l, c)
endfun
" }}}
" Key map
" {{{
" 禁用 Ex 模式
nmap Q <Nop>
" 禁用 <F1> 幫助
nmap <F1> <Nop>
" 行號
nmap <F2> :set nu! nu?<CR>
" 換行符
nmap <F3> :set list! list?<CR>
" 自動換行
nmap <F4> :set wrap! wrap?<CR>
" 粘貼模式
set pastetoggle=<F5>
" 格式化
nmap <F6> gg=G<C-o><C-o>
" nmap <F6> :call Format()<CR>
" function! Format()
" if &filetype != 'json'
" exec "normal gg=G\<C-o>\<C-o>"
" else
" %!python -m json.tool
" endif
" endfun
" 快速保存
nmap <leader>w :w<CR>
" 快速退出
nmap <leader>q :q<CR>
" 快速保存退出
nmap <leader>x :x<CR>
" U 重做
nmap U <C-r>
" 快速進入命令行
nmap ; :
" 關閉搜索 ,/
noremap <silent><leader>/ :nohls<CR>
" Bash模式:C-a 行首,C-e 行尾
map <C-a> <Home>
map <C-e> <End>
" 標簽跳轉
map <S-Up> :bp<CR>
map <S-Down> :bn<CR>
" 關閉方向鍵
" map <Left> <Nop>
" map <Right> <Nop>
" map <Up> <Nop>
" map <Down> <Nop>
" }}}
" Plugin
" {{{
" SuperTab
let g:SuperTabMappingForward = "<s-tab>"
let g:SuperTabRetainCompletionType = 0
let g:SuperTabDefaultCompletionType = "<C-N>"
" TagmaLast
let g:TagmaLastAutoUpdate = 1
let g:TagmaLastTimeFormat = '%Y-%m-%d %H:%M:%S'
" }}}