Permalink: 2013-12-05 11:13:53 by ning in misc tags: all

Table of Contents

关于

这个系列视频来自: http://vimcasts.org/episodes/archive

作者每个月会录1-5个视频放出来.从2010年坚持到现在.

这个网站的作者经常进行 vim 课程, $250 每次.(4小时) 他也是 <Practical Vim> 的作者(豆瓣8.9分)

对tabstop 不熟悉的, 建议观看1,2,4

#1.Show invisibles

显示不可见字符:

set list
set nolist

修改使用的不可见字符样式:

" Use the same symbols as TextMate for tabstops and EOLs
set listchars=tab:▸\ ,eol:¬

#2.Tabs and Spaces

tabstop:tab符宽度
softtabstop:使用<-键删除的时候, 删除多少宽度
shiftwidth:用>, <缩进的时候, 插入多宽.
expandtab:输入的tab, shift 时, 都替换为空格.

默认值:

tabstop = 8
softtabstop = 0
shiftwidth = 8
no expandtab

不一样会很混乱

结论:

  • 保证 tabstop == softtabstop == shiftwidth

retab

#3.Whitespace preferences and filetypes

用autocommand实现对python 和Makefile 不同的缩进设置.

autocmd FileType html setlocal ts=2 sts=2 sw=2 expandtab
autocmd FileType css setlocal ts=2 sts=2 sw=2 expandtab
autocmd FileType javascript setlocal ts=4 sts=4 sw=4 noexpandtab

#4.Tidying whitespace

  • convert between tabs and spaces.
  • strip trailing whitespace,
  • how to remove blank lines from a file.

noexpandtab 的时候, retab 把space 变成tab, expandtab 的时候 retab 把tab变成space.

不错的函数例子, 保存当前位置:

function! <SID>StripTrailingWhitespaces()
    " Preparation: save last search, and cursor position.
    let _s=@/
    let l = line(".")
    let c = col(".")
    " Do the business:
    %s/\s\+$//e
    " Clean up: restore previous search history, and cursor position
    let @/=_s
    call cursor(l, c)
endfunction

删除空白行

:g/^$/d

g命令:

:g 表示范围 global command

d 是一个Ex command

#5.Indentation commands

就是讲>> 和 << 还有:

vmap <D-[> <gv (我用tab和shift-tab)
vmap <D-]> >gv
  • N模式下用 ==, V模式下用 = 格式化,
  • vi} 选择{}中的代码.
  • =i} 格式化{}中的代码

缩进规则

~/.vim/indent/python.vim

#6.Working with buffers

讲的不错:

:buffers
1 #    ".recent"                      line 2        # 是上一个活跃buffer
2      "./notes/misc/vim_usage.rst"   line 217
3 %a   "./notes/misc/vim-vimcasts.rst" line 123     %a是active buffer

如果修改了一下 .recent. 就需要 bn! 才能切到下一个buffer:

:ls
1 #h + ".recent"                      line 3            +表示有modify,  h 表示hidden
2 %a   "./notes/misc/vim_usage.rst"   line 217
3  a   "./notes/misc/vim-vimcasts.rst" line 0

bn时不要求buffer 一定要写入:

:set hidden
  • :ls show the buffer list
  • :bn open the next buffer in t he current window (cycles from the end of the list to the beginning).
  • :bp open the previous buffer in the current window (cycles from the start of the list to the end).
  • CTRL-^ switch to the alternate file

#7 Working with windows (5:32)

知识通过读 window 一节, 已经知道, 演示的例子不错.

移动焦点:

ctrl-w hjkl

移动窗口:

ctrl-w HJKL

#8 Working with tabs (3:17)

:tabedit xxx.txt

:tabonly

:3gt, 直接到第几个tab.
map <C-1> 1gt
map <C-2> 2gt
map <C-3> 3gt
map <C-4> 4gt
map <C-5> 5gt
map <C-6> 6gt
map <C-7> 7gt
map <C-8> 8gt
map <C-9> 9gt
map <C-0> :tablast<CR>

可惜在我这用不了

tabmove
tabmove 1

#9 How to use tabs (5:28)

这一节基本没有什么内容..

#10 <nice-demo>Creating the Vimcasts logo as ASCII art (5:47)

ASCII art

在线工具: http://patorjk.com/software/taag/#p=display&v=0&f=Bulbhead&t=hello

宏:

qavwr_jq
q      q  两个q作为起始和结束
 a        表示放在a这个寄存器.

这一节对vim 的:

  • V模式,
  • ctrl+v 模式,
  • 拷贝,
  • replace

等的介绍, 对初学者是 很好的例子 .

有用hint, 如何在ctrl+v (C-V)模式下, 只替换选中的内容:

aaxxxaaaaaabbbbbb
aaxxxaaaaaabbbbbb
aaxxxaaaaaabbbbbb
aaxxxaaaaaabbbbbb
aaxxxaaaaaabbbbbb

选中后 '<,'>s/./x/g, 替换是在整个行上的. 会把ab都替换

需要加上 \%V

:'<,'>s/\%V./x/g

#11 Using the changelist and jumplist (3:21)

changelist:

:changes
g;  到上一个编辑点.
g,
10g;  到倒数第10个编辑点.

   10   269    0 ============================
    9   197    8 #10 <nice>Creating the Vimcasts logo as ASCII art (5:47)
    8   269    0 ============================
    7   232    0
    6   269    0 ============================
    5   235    0
    4   269    0 ============================
    3   269    0 ============================
    2   238    4 :changes
    1   242    0
>   0   250    0
    1   247    9 ctrl+I
    2   269    0 ============================
    3   248    0
    4   269    0 ============================
    5   239   29 g;  到上一个编辑点.
    6   269    0 ============================
    7   269    0 ============================
    8   240   36 10g;  到倒数第10个编辑点.
    9   269    0 ============================
   10   269    0 ============================

jumplist, 比较熟悉了:

:jumps
ctrl+O
ctrl+I

#14 The :edit command (3:50)

:e

:help expand

map <leader>ew :e <C-R>=expand("%:p:h") . "/" <CR>

后, 通过,ew, 就可以:

e /home/ning/idning/blog_and_notes/notes/misc/

有点用处, 不过不大, 下面这个更有用些:

Thanks to Gary Bernhardt, here is a less horrible way of creating the same mappings:

cnoremap %% <C-R>=fnameescape(expand('%:h')).'/'<cr>

this allows you to expand the directory of the current file anywhere at the command line by pressing %%. A top tip from Max Cantor!

cmap 是命令行的map, 可以在命令行里面, 用%%表示当前文件路径, 这个收入我的.vimrc

#15 The file explorer (5:36)

:E, 用原生的目录管理器打开 一个目录, 支持排序,创建文件/目录, 删除, 重命名等:

" Netrw Directory Listing                                        (netrw v149)
"   /home/ning/idning/blog_and_notes
"   Sorted by time
"   Quick Help: <F1>:help  -:go up dir  D:delete  R:rename  s:sort-by  x:exec

%   create a new file
d   create a new directory
R   rename the file/directory under the cursor
D   Delete the file/directory under the cursor

#16 Soft wrapping text (4:54)

关于:

set wrap
set linebreak
set showbreak=◀  (在被wrap的行前面加个符号)

关闭wrap:

set nowrap (此时可以用zl来向右滚动)

开启wrap:

set wrap

此时默认是会断开单词的, 可以用 :set linebreak, 设置为不断开单词, (这和 :set list 是冲突的)

有用: 有wrap时候的移动 :

0 , $ , k , j 等前面加上 g , 就是按照break后的行来移动了(按照显示行移动)

#17 Hard wrapping text (5:23)

未看

强制断行.

选中一段``gq``就是按照80列格式化,

the textwidth setting is a number representing the maximum allowed width of a line. when set to zero, which is the default, vim will use the full width of the window up to a maximum of 80 characters. when set to a value above zero, vim will format lines of text so as not to exceed the value of textwidth.

相关设置:

set textwidth=xx " 一行最多多宽
默认 textwidth=0, 表示按照当前窗口宽度(但是得小于80)来做断行.

set wrapmargin=xx " 断行的时候, 右边空多少个字符(set nu后就需要这个了) 如果设置了textwidth, 则这个选项没有用
默认wrapmargin=0,
::set formatoptions=tcq
默认: formatoptions=tcroql

:set formatoptions+=a " 在输入的时候自动断行. 会比较奇怪. 不要设

两个format engine: formatexpr vs formatprg.

#18 Formatting text with par (5:12)

设置外部fromat engine:

:set formatprg=par

par 输出更好看, 能处理注释格式.

太复杂, 木有必要

#19 Spell checking (5:42)

:set spell
对txt文件有用, 写代码用不着.

~/.vim/spell/LL.EEE.add

#20 Running Vim within IRB (4:35)

IRB: interactive ruby shell

在irb解释器里面调用vim来编辑代码(比如定义一个多行的函数), 确实不错的特性

python 要有这个多好

#21 <nice-demo>Converting markdown to struct_ured HTML with a macro (9:25)

surround.vim 插件

用例子讲解.

非常好的例子, 应该再看一遍 , 虽然不是很常用, 而且可以用脚本实现, 但是用的多了, 还是很有效率!!

比如 "zdw 剪切到 z 寄存器 "zP 粘贴出来, 这样的寄存器, 一般多用在宏里面.

#22 <nice-demo>Selecting columns with visual block mode (4:21)

ctrl+v 非常好的例子, 自己已经用习惯了:)

textmate 也有这个功能.

ctrl+v 可以用

  • I
  • A
  • r 替换
  • d
  • p 粘贴
  • c 这个有用 , 删掉选中的, 再进入插入模式
  • C 这相当于按了 $ .
  • o 有用 到选中方块的对角.
  • o9 固定到块尾,(对V模式都一样)

例子:

############################
# nihao ,wo hao            #
#                          #
############################

#23 Converting HAML to ERB with Vim macros (7:36)

也是例子, 没有特别的东东, 例子需要对ruby 熟悉才比较好懂.

#24 Updating your vimrc file on the fly (2:51)

:source $MYVIMRC
autocmd bufwritepost .vimrc source $MYVIMRC

#25 Creating colorschemes for Vim (9:44)

默认放在~/.vim/colors/下面:

highlight Todo guifg=#990000 guibg=NONE gui=NONE
highlight link Comment Todo

对颜色没有特殊癖好.

#26 Bubbling text (6:23)

类似Eclise <ctrl+up> <ctrl-down> 之类的功能:

" Bubble single lines
nmap <C-Up> ddkP
nmap <C-Down> ddp
" Bubble multiple lines
vmap <C-Up> xkP`[V`]
vmap <C-Down> xp`[V`]

虽然自己基本不用, 不过还是 不错的tip

下面这个很有用

gV 选择刚编辑的地方:

" Visually select the text that was last edited/pasted
nmap gV `[v`]

#27 Synchronizing plugins with git submodules and pathogen (9:24)

用这种方法管理模块:

Installation:

    git clone git://github.com/nelstrom/dotvim.git ~/.vim

Create symlinks:

    ln -s ~/.vim/vimrc ~/.vimrc
    ln -s ~/.vim/gvimrc ~/.gvimrc

Switch to the `~/.vim` directory, and fetch submodules:

    cd ~/.vim
    git submodule init
    git submodule update

附带了一个简单的github用法介绍.

Pathgon: 10年10月就有了的, 现在已然3年过去了.

我用svn+vundle.

#28 Refining search patterns with the command-line window (7:51)

Refining 是提炼的意思

When you press : or / in Vim, you go into commandline mode. 此时:

ctrl-p:Show previous historical command/search
ctrl-n:Show next historical command/search
ctrl-f:Switch from commandline mode to the co mmandline window

在normal模式下:

  • q/: Open the commandline window with history of searches
  • q:: Open the commandline window with history of commands

command-line window, 需要练习, 对正则式来说也是不错的例子

在写command的时候, 可以用 ctrl+n 自动提示.

例子:

\v'.+'
\v'[^']+'
\v'('\w|[^'])+'
\v'(('\w|[^'])+)'

#29 Aligning text with Tabular.vim (5:11)

练习

:Tab /=
:Tab /:

下面这个如果用在输入等号的时候格式化应该不错:

inoremap <silent> <Bar>   <Bar><Esc>:call <SID>align()<CR>a

function! s:align()
  let p = '^\s*|\s.*\s|\s*$'
  if exists(':Tabularize') && getline('.') =~# '^\s*|' && (getline(line('.')-1) =~# p || getline(line('.')+1) =~# p)
    let column = strlen(substitute(getline('.')[0:col('.')],'[^|]','','g'))
    let position = strlen(matchstr(getline('.')[0:col('.')],'.*|\s*\zs.*'))
    Tabularize/|/l1
    normal! 0
    call search(repeat('[^|]*|',column).'\s\{-\}'.repeat('.',position),'ce',line('.'))
  endif
endfunction

#30 Undo branching and Gundo.vim (6:30)

每次回到normal 状态的时候, 记录一个undo record, 这很重要!!

例1

在riv.vim插件里面, 如果设置了:

let s:default.buf_imaps = {
    \'<BS>'         : 'riv#action#ins_backspace()',
    \'<CR>'         : 'riv#action#ins_enter()'   ,
    \'<KEnter>'     : 'riv#action#ins_enter()'   ,
    ...
}

这里粘贴一段多行文字的时候, 每次遇到<CR>都会切入normal模式, 造成多个undo history

例2

自己的修改LastModified 字段的插件, 每次保存的时候, 都会生成两个undo history, undo 的时候会跳到文件头.

不少人遇到这个问题:

都没有很好解决.

我通过在python里面判断, 如果last modify 正好是当天, 就不做update, 来减少undo history

undo branch

vim 7.0的特性

这里讲解非常好!!

因为undo, redo 只能在一个分支上走, 不能到一个已经被丢弃的分支, 但是可以通过 g+ , g- 回到上一个状态(可以在undo branch之间切换!) 类似时光机.

:earlier {count}    Go to older text state {count} times.
:earlier {N}s       Go to older text state about {N} seconds before.
:earlier {N}m       Go to older text state about {N} minutes before.
:earlier {N}h       Go to older text state about {N} hours before.
:earlier {N}d       Go to older text state about {N} days before.

gundo

这个插件, 可以展示undo branch的分支, 还能显示两次变换之间的diff.

也是用python做的!

很赞: https://github.com/sjl/gundo.vim

#31 Fugitive.vim - a complement to command line git (8:27)

Git run任何git命令:

:Git log
:Git lg

:Gwrite
:Gread
:Gremove
:Gmove

感觉没有必要

#32 Fugitive.vim - working with the git index (11:41)

Gstatus

  • 之后用 - 来修改是否要stage 一个文件, 很赞
  • 之后用 C 来开始commit

Gblame, Gdiff 是有点用.

#33 Fugitive.vim - resolving merge conflicts with vimdiff (11:35)

Gdiff 3路merge , 太复杂.

diffput, diffget 太夫在, dp 还好

#34 Fugitive.vim - browsing the git object database (9:45)

Gbrowser挺强大和方便, 但是少用

statusline显示git branch:

set statusline=%<%f\ %h%m%r%{fugitive#statusline()}%=%-14.(%l,%c%V%)\ %P

#35 Fugitive.vim - exploring the history of a git repository (10:04)

Fugitive.vim这个插件挺强大和方便, 但是这些功能太少用了 -- 很多人几乎一年浏览一下某个项目的历史项目, 就不错了.

#36 VimGolf - Prime Numbers (6:53)

VimGolf是一个Vim挑战网站, 从获得Prime Numbers这个例子上, 可以学习宏/正则式.

#37 How to fold (8:49)

:help fold-methods

  • zi switch folding on or off
  • za toggle current fold open/closed
  • zc close current fold
  • zR open all folds
  • zM close all folds
  • zv expand folds to reveal cursor
  • zo open current fold
  • zO recursively open current fold
  • zc close current fold
  • zC recursively close current fold
  • za toggle current fold 有用, 可以换掉zc, zo
  • zA recursively open/close current fold
  • zm reduce foldlevel by one
  • zM close all folds
  • zr increase foldlevel by one
  • zR open all folds

nnoremap <Space> za 不错, 很方便.

知识点不多, 基本都用惯了.

#38 Writing a custom fold expression (12:07)

  • foldcolumn 是说左边有几个列是放fold标记的

  • 使用foldmethod=marker 时, 可以用:

    {{{
    {{{1  这里1表示级别
    

Here’s the boilerplate fold expression that we used to begin with:

function! MarkdownFolds()
  return "0"
endfunction
setlocal foldmethod=expr
setlocal foldexpr=MarkdownFolds()

返回值:

"0" the line is not in a fold "1", "2", ... the line is in a fold with this level "=" use fold level from the previous line ">1", ">2" a fold with this level starts at this line

可以通过这个函数, 设置fold的区域显示什么:

function! MarkdownFoldText()
  return getline(v:foldstart)
endfunction
setlocal foldtext=MarkdownFoldText()

有用但是不重要

#39 Profiling Vimscript performance (8:09)

vim --cmd 'profile start vimrc.profile' --cmd 'profile! file ~/.vimrc'

会把profile结果记录在vimrc.profile 里面

, 有用技巧

#40 Long-range line duplication (6:31)

没用, 不方便, 把第9行拷贝到16行:

:9copy16

拷贝到当前行:

:9t.
set relativenumber, 显示相对行号

:-7t.

#41 Meet the arglist (4:57)

:args

. 是重复上一个编辑命令 @: 是重复上一个命令模式的命令

buffer list 包含 argument list, 比如我用 lsrecent 打开一个文件后, :args 显示:

[.recent]

并不显示当前文件.

#42 Populating the arglist (5:31)

how to set the contents of the arglist using the :args command, which can receive filepaths, globs, or even backtick expressions.

比如:

:args notes/misc/vim-ctags-vs-cscope.rst

会打开这个文件.

args 有点像用 vim *.rst 这样的命令打开多个文件的时候, 带的参数 *.rst, 可以传shell 命令给args:

args `cat a.txt`

#44 Search multiple files with :vimgrep (7:25)

vimgrep is Vim’s built-in command for searching across multiple files. It’s not so fast as external tools like ack and git-grep, but it has its uses. vimgrep uses Vim’s built-in regex engine, so you can reuse the patterns that work with Vim’s standard search command.

不如:

ack
git-grep
ag

快.

grep 一个东西:

:Ack ensureIndex
:grep ensureIndex * -r  会把svn 之类的grep出来.

在当前文件中找:
:vimgrep /ensureIndex/g %

:vimgrep /ensureIndex/g *

:vimgrep /ensureIndex/g `find . -type f`

在arglist 里面搜索
:vimgrep /ensureIndex/g ##
:vim /pattern1/ `find . -type f`
:vim /pattern2/ `find . -type f`
:vim /pattern3/ `find . -type f`

可以换成:

:args `find . -type f`
:vim /pattern1/ ##
:vim /pattern2/ ##
:vim /pattern3/ ##

vimgrep 的优势只有: 和vim使用同样的正则.

#45 Project-wide find and replace (6:25)

把quickfix 窗口里面的文件名, 放到arglist里面去, 非常有用, 但是用到这种全局替换的case不多:

command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames()
function! QuickfixFilenames()
  " Building a hash ensures we get each buffer only once
  let buffer_numbers = {}
  for quickfix_item in getqflist()
    let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr'])
  endfor
  return join(map(values(buffer_numbers), 'fnameescape(v:val)'))
endfunction

这样, 流程变为:

  1. vimgrep 找出需要替换的单词
  2. Qargs
  3. :argdo %s/xxx/xxxxx/ge
  4. :argdo w

#46 Search for the selected text (4:39)

用内置功能:

:vmap X y/<C-R>"<CR>

用插件:

visual-star-search plugin from github,

非常有用, 效果比之前用的 UtilVisualSelection 好.

某些时候可以替代ack 也不错:

" recursively vimgrep for word under cursor or selection if you hit leader-star
nnoremap <leader>* :execute 'noautocmd vimgrep /\V' . substitute(escape(expand("<cword>"), '\'), '\n', '\\n', 'g') . '/ **'<CR>
vnoremap <leader>* :<C-u>call <SID>VSetSearch()<CR>:execute 'noautocmd vimgrep /' . @/ . '/ **'<CR>

,* 这个map比 F3 也更好

@49 Enhanced abbreviations with :Abolish (3:09)

abolish插件对我应该不太有用.

Abolish's killer feature is that it handles the fight between logical names & the English language. 在替换的时候能自动处理单复数, 大小写, 前后缀:

:%s/Notes/Entries/g
:%s/Note/Entry/g
:%s/notes/entries/g

#50 An introduction to vspec (7:15)

Vspec is a library that allows you to test-drive your Vimscript code. In this tutorial, we’ll cover the basics: how to inspect the contents of a buffer, how to simulate the actions of a user, and how to invoke user-defined mappings.

可以给vim 插件写测试:

nnoremap x daw

describe 'vspec'

  before
    new
    put! = 'Welcome to Vimcasts'
  end

  after
    close!
  end

  it 'can read the contents of the buffer'                  #一个case
    Expect getline(1) == "Welcome to Vimcasts"
  end

  it 'feels just like operating Vim!'                       #一个case
    normal gg$
    normal daw
    Expect getline(1) == 'Welcome to'
    Expect getreg('"') == ' Vimcasts'
  end

  it 'can exercise user-defined mappings'                   #一个case
    normal gg$
    normal x
    Expect getline(1) == 'Welcome to'
    Expect getreg('"') == ' Vimcasts'
  end

end
  1. 把如上脚本转换为vimscrip (excommand)
  2. 用Ex模式调用vim(不会出现gui), 并执行excommand
  3. 可以用excommand normal d 模拟normal 模式下按一下 d

非常赞 .

#52 Meet the yank register (4:29)

已知, 比较简单

#53 Using Vim's named registers (3:29)

  • "ayy 是把当前行放入 寄存器a
  • "Ayy 是把当前行append 到 寄存器a

比较简单

#55 Pasting from Insert mode (4:15)

insert下/命令模式下, 按 crtl+r 0, 粘贴0号寄存器.

#56 Simple calculations with Vim's expression register (4:02)

表达式寄存器: "=

有用 : 编辑模式下: ctrl+r = 输入 3*5 , 插入结果

用下面这个map:

nnoremap Q 0yt=A<C-r>=<C-r>"<CR><Esc>
3*2 =

#57 Evaluating scripts with Vim's expression register (3:56)

system() 函数

"= 下可以用 abs(), round(), system()之类函数

:help function-list
:put = 3+3
:put =system('echo $RANDOM')

#58 Accessing the system clipboard from Vim (4:48)

"+y 粘贴, 不需要设置set paste:

"+gp
:put +

If you’d like to make it easier to interact with the system clipboard, try out this setting,

:set clipboard=unnamed,unnamedplus

有用, 但是会破坏我在 rst_bold_it 的ctrl+c, ctrl+b, 因为这里我用了默认寄存器 " , 我换成命名寄存器 n 就好了

上面这个行为想当于 在d, x, y, p 命令前都加了"*

#59 Using Vim's paste mode with the system paste command (4:25)

set paste 之后 , imap都失效了.

unimpaired 这个插件, 可以在我想要粘贴的时候, 按 yo , 此时会自动 set paste 贴完之后, 会自动 set nopaste

-对我基本没用

#60 Comparing buffers with vimdiff (4:16)

:windo diffthis 比较两个win.
:windo diffoff

ning: vim modline

比如写在文件头:

"vim: foldmethod=marker

总结

前30个非常好, 后面知识较少.

Comments