人们谈论常见技巧的问题很多,特别是“Vim+ctags提示和技巧”。

然而,我并没有提到Vim新手会觉得很酷的常用快捷方式。我所说的是一位经验丰富的Unix用户(无论是开发人员、管理员,还是两者都有),他们认为自己知道99%的人从未听说过或梦想过的东西。这不仅让他们的工作更容易,而且很酷,很粗糙。毕竟,Vim位于世界上最黑暗的角落丰富的操作系统中,因此它应该具有只有少数特权人士知道并想与我们分享的复杂性。


当前回答

使移动在换行模式下在当前屏幕行上操作的映射。不久前,我在Vim提示的一条评论中发现了这一点,事实证明它非常方便。

function! ScreenMovement(movement)
  if &wrap
    return "g" . a:movement
  else
    return a:movement
  endif
endfunction
onoremap <silent> <expr> j ScreenMovement("j")
onoremap <silent> <expr> k ScreenMovement("k")
onoremap <silent> <expr> 0 ScreenMovement("0")
onoremap <silent> <expr> ^ ScreenMovement("^")
onoremap <silent> <expr> $ ScreenMovement("$")
nnoremap <silent> <expr> j ScreenMovement("j")
nnoremap <silent> <expr> k ScreenMovement("k")
nnoremap <silent> <expr> 0 ScreenMovement("0")
nnoremap <silent> <expr> ^ ScreenMovement("^")
nnoremap <silent> <expr> $ ScreenMovement("$")

其他回答

HOWTO:在Bash中使用Vim时自动完成Ctag。对于其他使用Vim和Ctags的人,我已经为Bash编写了一个小型自动补全器函数。将以下内容添加到~/.bash_completion文件中(如果不存在,请创建它):

感谢stylishpants的多次修复和改进。

_vim_ctags() {
    local cur prev

    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    case "${prev}" in
        -t)
            # Avoid the complaint message when no tags file exists
            if [ ! -r ./tags ]
            then
                return
            fi

            # Escape slashes to avoid confusing awk
            cur=${cur////\\/}

            COMPREPLY=( $(compgen -W "`awk -vORS=" "  "/^${cur}/ { print \\$1 }" tags`" ) )
            ;;
        *)
            _filedir_xspec
            ;;
    esac
}

# Files matching this pattern are excluded
excludelist='*.@(o|O|so|SO|so.!(conf)|SO.!(CONF)|a|A|rpm|RPM|deb|DEB|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MP?(E)G|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)'

complete -F _vim_ctags -f -X "${excludelist}" vi vim gvim rvim view rview rgvim rgview gview

重新启动Bash会话(或创建新会话)后,可以键入:

代码:

~$ vim -t MyC<tab key>

并且它将自动完成标记,就像它对文件和目录所做的那样:

代码:

MyClass MyClassFactory
~$ vim -t MyC

我发现当我快速修复bug时,它真的很有用。

以下两项都不是真正的顽固,但我发现它非常有用。

琐碎的捆绑,但我不能没有。它在插入模式下启用hjkl风格的移动(使用ctrl键)。在正常模式下:ctrl-k/j向上/向下滚动半个屏幕,ctrl-l/h转到下一个/上一个缓冲区。µ和ù映射特别适用于AZERTY键盘,并转到下一个/上一个错误。

imap <c-j> <Down>
imap <c-k> <Up>
imap <c-h> <Left>
imap <c-l> <Right>
nmap <c-j> <c-d>
nmap <c-k> <c-u>
nmap <c-h> <c-left>
nmap <c-l> <c-right>

nmap ù :cp<RETURN>
nmap µ :cn<RETURN>

我编写了一个小函数来突出显示函数、全局、宏、结构和typedef。(对于非常大的文件可能会很慢)。每种类型都有不同的突出显示(请参阅“:help group name”了解当前颜色主题的设置)用法:使用ww(默认“\ww”)保存文件。你需要做这个。

nmap <Leader>ww :call SaveCtagsHighlight()<CR>

"Based on: http://stackoverflow.com/questions/736701/class-function-names-highlighting-in-vim
function SaveCtagsHighlight()
    write

    let extension = expand("%:e")
    if extension!="c" && extension!="cpp" && extension!="h" && extension!="hpp"
        return
    endif

    silent !ctags --fields=+KS *
    redraw!

    let list = taglist('.*')
    for item in list
        let kind = item.kind

        if     kind == 'member'
            let kw = 'Identifier'
        elseif kind == 'function'
            let kw = 'Function'
        elseif kind == 'macro'
            let kw = 'Macro'
        elseif kind == 'struct'
            let kw = 'Structure'
        elseif kind == 'typedef'
            let kw = 'Typedef'
        else
            continue
        endif

        let name = item.name
        if name != 'operator=' && name != 'operator ='
            exec 'syntax keyword '.kw.' '.name
        endif
    endfor
    echo expand("%")." written, tags updated"
endfunction

我有编写大量代码和函数的习惯,我不喜欢为它们编写原型。所以我做了一些函数,在C样式源文件中生成原型列表。它有两种风格:一种是删除形式参数的名称,另一种是保留它。每次需要更新原型时,我都会刷新整个列表。它避免了原型和函数定义不同步。还需要ctags。

"Usage: in normal mode, where you want the prototypes to be pasted:
":call GenerateProptotypes()
function GeneratePrototypes()
    execute "silent !ctags --fields=+KS ".expand("%")
    redraw!
    let list = taglist('.*')
    let line = line(".")
    for item in list
        if item.kind == "function"  &&  item.name != "main"
            let name = item.name
            let retType = item.cmd
            let retType = substitute( retType, '^/\^\s*','','' )
            let retType = substitute( retType, '\s*'.name.'.*', '', '' ) 

            if has_key( item, 'signature' )
                let sig = item.signature
                let sig = substitute( sig, '\s*\w\+\s*,',        ',',   'g')
                let sig = substitute( sig, '\s*\w\+\(\s)\)', '\1', '' )
            else
                let sig = '()'
            endif
            let proto = retType . "\t" . name . sig . ';'
            call append( line, proto )
            let line = line + 1
        endif
    endfor
endfunction


function GeneratePrototypesFullSignature()
    "execute "silent !ctags --fields=+KS ".expand("%")
    let dir = expand("%:p:h");
    execute "silent !ctags --fields=+KSi --extra=+q".dir."/* "
    redraw!
    let list = taglist('.*')
    let line = line(".")
    for item in list
        if item.kind == "function"  &&  item.name != "main"
            let name = item.name
            let retType = item.cmd
            let retType = substitute( retType, '^/\^\s*','','' )
            let retType = substitute( retType, '\s*'.name.'.*', '', '' ) 

            if has_key( item, 'signature' )
                let sig = item.signature
            else
                let sig = '(void)'
            endif
            let proto = retType . "\t" . name . sig . ';'
            call append( line, proto )
            let line = line + 1
        endif
    endfor
endfunction

这些是我多年来收集的。

" Pasting in normal mode should append to the right of cursor
nmap <C-V>      a<C-V><ESC>
" Saving
imap <C-S>      <C-o>:up<CR>
nmap <C-S>      :up<CR>
" Insert mode control delete
imap <C-Backspace> <C-W>
imap <C-Delete> <C-O>dw
nmap    <Leader>o       o<ESC>k
nmap    <Leader>O       O<ESC>j
" tired of my typo
nmap :W     :w

宏可以调用其他宏,也可以调用自身。

eg:

qq0dwj@qq@q

…将删除每行中的第一个单词,直到文件结束。

这是一个非常简单的示例,但它展示了vim的一个非常强大的功能

全部替换

  :%s/oldtext/newtext/igc

给出一个替换所有:)