Learn Vimscript the Hard Way Notes

learn vimscrip the hard way


第二次阅读

14 Autocommand Groups

需要用 augroup 包裹. 对同一个组多次使用 augroup 其会叠加.

augroup 可能是方便组织.
如:

1
2
3
4
5
6
7
augroup testgroup
autocmd BufWrite * :echom "cat"
augroup END

augroup testgroup
autocmd BufWrite * :echom "dog"
augroup END

要想重写则使用 autocmd!

1
2
3
4
augroup testgroup
autocmd!
autocmd BufWrite * :echom "dog"
augroup END

针对某种文件:

1
2
3
augroup filetype_html
autocmd!
autocmd FileType html nnoremap <buffer> <localleader>f Vatzf

40 Paths

40.1 Absolute Paths

1
:echo expand('%')

输出当前文件名.

1
:echo expand('%:p')

输出当前路径。

1
:echo fnamemodify('foo.txt', ':p')

指定当前目录下的一个文件名 (不管是否存在),显示他的绝对路径.

40.2 Listing Files

列出当前目录下的所有文件名.

1
:echo globpath('.', '*')

其返回的是一个 string, 每名字之间用换行符分隔. 为了提取出来,使用 split() 函数:

1
:echo split(globpath('.', '*'), '\n')

split() 函数接受两个参数,第一个是一个 string, 第二个是分隔符.

第一次阅读

1 Echoing Messages

:echo:echom的区别,后者的信息能被:message保存.

2 Setting Options

?可用来检查状态,如:

:set number?
#若没有设置行号,则显示
nonumber

5 Strict Mapping

<cr>表示回车键。
:nunmap /取消/的map。

Norecursive Mapping
就是不会递归替换。
:*noremap.

6.2 Leader

前缀prefix在这里常叫leader
改变leader:

:let mapleader = “-”
#然后执行
:nnoremap <leader>d dd
#此时-d代表dd 

感觉这像是一种约定俗成,而且便于修改你方便的前缀。

另一个可以用在特定文件的leader叫“local leader”,设置如下:

:let maplocalleader = “\\”

2022/5/31

8 Abbreviations

The abbreviation will be expanded when you type anything that’s not a letter, number, or underscore.

使用:set iskeyword?查看哪些是keyword,也就是不会被缩写abbreviation展开的字符。

Abbreviation 可以用来correcting typos。

Abbreviation 和 mapping的区别

mapping会立即扩展,而abbreviation需要后面跟一个空格才会扩展。

9 More Mapping

按下viw可以在可视模式下选中一个单词。

普通模式下w是光标移动到一个单词的末尾,b是移动到一个单词的开头。

2022/6/1

11 Buffer-Local Options

<buffer>, 告诉vim在当前缓冲区内使用次此命令。

:nnoremap <buffer> <leader>x dd

Local Leader

When you create mapping that only applies to specific buffers you should use instead of .

setting

:setlocal 作用于当前缓冲区。

:set设置的是全局值。

一个window就是一个buffer。

:setglobal,设置全局值,但不改变当前buffer的变量。

2022/6/2

12 Autocommand


参考1


autocmd即自动命令,是在指定事件发生时自动执行的命令。

格式大概是:

:autocmd event filter command
如
:autocmd BufNewFile * :write

:w:write的缩写,意为将当前缓冲区的内容写入文件。

:normal gg=G

会告诉Vim to reindent the current file

The event type BufWritePre means the event will be checked just before you write any file.

所以说,event可能就是,检查的时机,后面的filter就是检查的对象。

查看有哪些autocmd的events

:help autocmd-events

Multiple Events

:autocmd BufWritePre,BufRead *.html :normal gg=G

一般把BufReadBufNewFile两个events添加到一起。逗号连接时不能有空格。

:autocmd BufNewFile, BufRead *.html setlocal nowrap

FileType Events
最常用的就是FileType这个events。

:autocmd FileType JavaScript nnoremap <buffer> <localleader>c I//<esc>

将autocommand和buffer local mapping结合,可以创建特定的键位。

自动折行

:set wrap

就是把长的一行用多行显示。

:set textwidth=n

每行超过n各字符时自动换行。

13 Buffer-local Abbreviations

:iabbrev中使用<buffer>.

<left>即向左移动一个字符。

autocmd-events 的几个前缀和后缀

Buf都作为前缀,是与buffer相关的,如BufNewFile,就是在打开一个不存在的文件时触发。

Pre都作为后缀, 意为在什么之前,如BufReadPre,就是在打开一个buffer后,在读文件之前触发。

Post都作为后缀,意为在什么之后,如BufReadPost,就是在打开一个buffer后,在读文件之后触发。

ReadWrite一般是命令中间。

File,与文件相关,如FileType

Filter与filter命令相关,如FilterReadPre

过滤器filter


参考


14 Autocommand Groups

作用,防止重复定义。

autocmd!

能够clear前面相同的定义。

Read :help autocmd-groups

15 Operator-Pending Mappings

:onoremap p i(

这里的第一个o就是operator的意思。
此时用dp结果就是删除括号里面的。
用在等待一个动作时。

think way:

  1. Start at the cursor position
  2. Enter visual mode(charwise)
  3. …mapping keys go here…
  4. Alll the text you want to include in the movement should now be selected.

Read :help omap-info

16 More Operator-Pending Mappings

normal命令

:normal

命令。

:normal gg

就是跳转到开头,所以,normal命令就是指在:normal模式下运行命令。

execute命令

:execute “write”

就是执行一段Vimscript命令。

g_

移动到the last non-blank character in the line.


Read :help pattern-overview
Read :help normal
Read :help execute
Read :help expr-quote

17 Status Lines

就是页面最下面那一行,可以改变输出的内容。

:set statusline=%f

Things that start with % are expanded to different text depending on what comes after them.

空白字符需转义。

:set statusline=%f\ -\ FileType:\ %y

在当前的statusline后面添加:

:set statusline+=FileType

查阅

:help statusline

18 Responsible Coding

在normal模式下Fold you code by

za    

fold everything automatically

:help foldlevelstart

设置foldlevel的值来决定fold。

一般情况:

set foldlevel=

放在autocmd前面,以便修改不同类型文件的foldlevel。

19 Variables

setlet的区别。


参考


这里可能要区分选项options和变量variables。

set只能用与设置选项,且不能进行运算,如

:set textwidth=100+1

会报错。

let可以用于变量和选项,只不过修改选项时要加上&,如

:let &textwidth=100+1

修改变量时用&就会报错。

set还能查看选项的值,如

set textwidth?

以上设置的都是全局的变量和选项。

Local Options

:let &1:number = 1

报错了。

Registers as Variables

Read and set registers as variables.

:let @a = “hello!”

把寄存器a的值设置为“hello!”,可以在normal中引用寄存器的值

“ap

粘贴a的值。

寄存器,保存上一次复制粘贴的值,如

echo @“

/寄存器,保存上一次查找的值,如

echo @/

You should never use let if set will suffice.

Read :help registers.

Variable Scoping

Like

:let b:hello = “world”

b: is a scope for variables, 表示设置为局部值。

浏览scopes表:help internal-variables

21 Conditionals

Multiple-Line Statements

Use | to separate each line

:echom “foo” | echom “bar”

Basic if

:if 1
:   echom “ZERO”
:endif

Vimscript中的字符串的值要根据上下文判断。如

if “10” #这里表示数字
if “10num” #这里也表示数字
if “num10” #这里不是数字了
“hello” + 10 #值为10

else 和 elseif

if  0
    echom “if”
elseif “nope!”
    echom “elseif”
else 
    echom “finally”
endif

22 Comparisons

if 10 > 1
    echom “foo”
endif

Case Sensitivity

:set noignorecase
:set ignorecase

设置大小写敏感。

Code Defensively

A bare “==” should never appear in your plugins’ code.

==? case-insensitive no matter what the user has set.

==# case-sensitive no matter what the user has set.

在数字做比较是也多用上面两个operator。

Read :help ignorecase
Read :help expr4

23 Functions

Define the function

function Meow()
    echom “Meow!”
endfunction

Running the function

call Meow()

Returning a value

function GetMeow()
    return “Meow String!”
endfunction

Implicit Returning

没有明确的写return的话,会有implicit returning.

Read :help call

Read :help E124 看那些可以当作函数名。 must start with a capital or “s:”

Read :help return

24 Function Arguments

对scope的理解

可能是和名称空间差不多的玩意。

a:name这里的:a表示variable scope。

所有的变量调用时都要加上a:

Global variable need to be accessed with :g.


Varargs

function Varg(...)
    echom a:0
    echom a:1
    echom a:000
endfunction

a:0表示extra variable的数量。

a:1表示第一个extra variable的值。

a:000表示所有extra variable的列表。

Assignment

function AssignGood(foo)
    let a:foo_tmp = a:foo
endfunction

Read :help function-argument
Read :help local-variables

25 Numbers

Two types:

  • Numbers, 32 bit signed
  • Floats

0开头的数字表示octal number,以0x开头的数字表示hex。

echo 5e4

会报错。

Coercion

echo 2 * 2.0

结果为浮点数。

division

echo 3 / 2 

结果为1.

echo 3 / 2.0

结果为1.5.

Read :help Float
Read :help float-point-precision

Strings

Concatenation

echom “Hello,” + “world”

输出0,vim的+只用于numbers。

vim不会coerce string to float

echom 10 + “10.10”

输出20.

. is the concatenate strings operator.

echom “Hello, ” . “world”

将两个string连接起来。

echom 10.1 . “foo”

会报错。

Don’t rely on Vim’s coercion.

Special Characters

\转义。

foo^@bar中的^@ is Vim’s way of saying “newline character”.

Literal Strings

使用单引号’ ’

里面没有转义字符。

echom ‘\n\\’

显示\n\\.

Truthiness


Read :help express-quote
Read :help i_CTRL-V
Read :help literal-string


27 String Functions

Length

echom strlen(“foo”)

Splitting

echo split(“one two three”)

输出[‘one’, ‘two’, ‘three’].

将字符串分解为list。

echo split(“one, two, three”, “,”)

输出[‘one’, ‘two’, ‘three’],此时是以,作为分隔,若不指定则默认为空白字符。

Joining

echo join([“foo”, “bar”], “...”)

输出foo...bar,就是用后面指定的符号连接列表中的各元素。

和split配合使用

echo join(split(“foo bar”), “;”)

输出foo;bar.

Lower and Upper Case

echom tolower(“Foo”)
echom toupper(“Foo”)

Read :help split()
Read :help join()
Read :help functions


28 Execute

判断一个字符串是否是Vimscript的命令。

Basic Excution

execute “echom ‘Hello, world!’”

输出’Hello world!’

Can not be followed by a comment.


Read :help execute

Read :help leftabove, :help rightbelow,:help split,:help vsplit.


29 Normal

normal G

移动到文件底部。

Avoiding Mapping

使用normal!相当于norecuision的作用,在写Vimscript的时候要用normal!

Special Characters

normal!不能识别特殊字符如<cr>它会将其视为‘<’ ‘c’ ’r’ ’>’.

executenormal!结合可以解决以上问题。

:execute “normal! gg/foo\<cr>dd”

此处要使用转义\


Read :help normal


Extra Credit

Skip 掉了

30 Execute Normal!

Read :help express-quote

31 Basic Regular Expressions

Use ? to search backward instead of forward.

execute “normal! G?print\<cr>”

也就是说/是以forward的方式查找,?是以backward的方式查找。

Magic

magic选项就是存在\n这类普通字符前面加一个\就有了特殊含义,以及\.将原本有特殊含义的词变为普通的字符。

execute “normal! gg/for .\\+ in .\\+:\<cr>”

此处的正则表达式中的+需写成\+才能发挥作用,所以\\是为了转义一个\.

在Vim中,单引号阔起来的都表示单个字符如a\nb,表示四个字符。

:execute “normal! gg” . ‘/for .\+ in .\+:’ . “\<cr>”

Very Magic

Very magic就是:所有的ASCII字符除了 ‘0’-‘9’, ‘a’-‘z’,‘A’-‘Z’和‘_’外的字符都有特殊含义。

Vim 有四种parse regex的方法,添加\v能够让这种regex语法最接近其他语言中的正则表达式, \v是”very magic“模式。

‘/\vfor .+ in .+:’

Read :help magic
Read :help pattern-overview
Read :help match
Read :help nohlsearch


32 Case Study: Grep Operator, Part One


Read :help grep
Read :help make
Read :help quickfix-window


Escaping Shell Command Arguments

<cword>用在命令中,Vim会在命令被执行前把它替换为光标下的单词。

<cWORD>会替换为整个单词。

两个的区别在如foo-bar, 前者会替换为foo,后者会替换为foo-bar.

Vim会在如<cword>扩展之前就运行shellescape(),因此要使用expand(), 让<cword>在shellescape()执行之前展开。

:nnoremap <leader>g :execute “grep! -R ” . shellescape(expand(“<cWORD>”)) . “ .”<cr>:copen<cr>

grep!防止跳转至第一条。

copen的作用是打开quickfix,可调整高度。

cnext是切换到下一个error的位置。

cprevious是切换到前一个。


Read :help :grep
Read :help cword
Read :help cnext
Read :help cprevious
Read :help expand
Read :help copen
Read :help silent


33 Case Study: Grep Operator, Part Two

~/vim/plugin目录,操作其中的文件时可以用:source %加载。


Visual Mode

<c-u>的作用,避免出现:’<,’>.

visualmode()返回visualmode的模式。

变量由@开头的都是寄存器。

@@是未命名的寄存器,存放复制和删除的text(未指定寄存器的)。

function!前面的!表示重写一个function。


Read :help visulmode
Read :help c_ctrl-u
Read :help operatorfunc
Read :help map-operator


operatorfunc是个选项,如

:set operatorfunc=GrepOperator

这样,就可以用g@来调用GrepOperator这个函数。

‘`[‘放在定义为motion的text前面.


34 Case Study: Grep Operator, Part Three


Namespacing

, 会被扩展为<SNR>numnum表示一个特殊的数字。

s:添加到函数前,使之处于当前的名称空间。


Read :help <SID>


35 Lists

indexing

0表示第一个元素。

-1表示倒数第一个元素,-2表示倒数第二个元素。


slicing

分割。

:echo [‘a’, ‘b’, ‘c’, ‘d’, ‘e’][0:2]

显示[’a’, ‘b’ , ‘c’]


Concatenation

:echo [‘a’, ’b’] + [‘c’]

List Function

Read :help List
Read :help add()
Read :help len()
Read :help get()
Read :help index()
Read :help join()
Read :help reverse()
Read :help functions


36 Looping

For Loops

:let c = 0
:for i in [1, ,2 ,3, 4]
:  let c += i
:endfor

:echo c

While Loops

:let c = 1
:let total = 0

:while c <= 4
:  let total += c
:  let c += 1
:endwhile

:echom total

Read :help for
Read :help while


Dictionaries

:echo {‘a’: 1, 100: ‘foo’}

:echo {‘a’: 1, 100: ‘foo’,}

Indexing

:echo {‘a’: 1, 100: ‘foo’,}[‘a’]

:echo {‘a’: 1, 100: ‘foo’,}.a

Assigning and Adding

:let foo = {‘a’: 1}
:let foo.a = 100
:let foo.b = 200
:echo foo

Removing Entries

:let test = remove(foo, ‘a’)
:unlet foo.b
:echo foo
:echo test

多数使用remove()


Dictionary Function

Read :help Dictionary
Read :help get()
Read :help has_key()
Read :help items()
Read :help keys()
Read :help values()


38 Toggling

Restoring Windows/Buffers

每一个window都有一个号。


Read :help foldcolumn
Read :help winnr()
Read :help ctrl-w_w
Read :help wincmd


execute a:number . “wincmd operator”

Functional Programming


Functions as Variables

可以用变量存储函数,这时变量要以大写字母开头

:let Myfunc = function(“Append”)
:echo Myfunc([1, 2], 3)

Higher-Order Function

就是通过调用其他函数完成任务的函数。

Read :help map
Read :help sort()
Read :help reverse()
Read :help copy()
Read :help deepcopy()
Read :help function()
Read :help type()


40 Paths

% 表示当前文件。

%:p表示绝对路径。

Read :help expand()
Read :help fnamemodify()
Read :help filename-modifiers
Read :help simplify
Read :help resolve()
Read :help globpath()
Read :help wildcards


41 Creating a Full Plugin


42 Plugin Layout in the Dark Ages


43 A New Hope: Plugin Layout with Pathogen


45 Basic Syntax Highlighting

注意防止重复加载的判断,和防止多次加载头文件一样。


Read :help syn-keyword
Read :help iskeyword
Read :help group-name


syn-keyword中的option, 就是可以用简写。

把你自己的group link 到其他的group,就可以有一样的highlighting。大小写不敏感。


46 Advanced Syntax Highlighting

syntax keyword的作用大概是自己定义一个keyword group。

syntax match同样要自己定义一个group,只不过后面跟的是正则表达式。其不允许一行多个group。

后定义的group有更高的优先级。

Keyword的优先级高于Match和Region.

如:

syntax match potionComment “\v#.*$”

Read :help syn-match
Read :help syn-priority


47 Even More Advanced Syntax Highlighting

Read :help syntax


Highlighting Strings

syntax region, 注意start,skip,end

Read :help syn-region


48 Basic Folding

Read :help usr_28


所有的fold操作以z开头。

保存fold,mkviewloadview.

viewdir 选项查看。

按照缩进foldset foldmethod=indent

foldlevelshiftwidth相关。

利用foldmethod选择折叠方式。


Vim中local和全局的作用。

设置了local之后,会更加specific,因此优先级会更高。


Read :help foldmethod
Read :help fold-manual
Read :help fold-marker
Read :help help foldmarkr
Read :help fold-indent
Read :help fdl
Read :help foldlevelstart
Read :help foldminlines
Read :help foldignore


49 Advanced Folding

Folding Theory

每一行代码都有一个foldlevel.

当前自己的理解,一个tab键的缩进就是让foldlevel加1,fold indent是按照每一行的foldlevel折叠的,相邻的折在一起,但相邻的foldlevel不一定相等。


Getting Started

每当:set filetype=potion时,都会加载ftplugin/potion.


Expr Folding

foldignore只对foldmethod为indent时有效。

字符’-1’表示这一行的foldlevel是undefined, 这一行的foldlevel会和the line above or below哪一个的foldlevel小,就等于哪一个。


Read :help foldexpr
Read :help fold-expr
Read :help getline
Read :help indent()
Read :help line()


An Indentation Level Helper

shiftwidth的值就是一个tab键的长度。tabstop的值也是tab的空格数。

indent()返回某一行的前面的space数。

=~?的意思是后面为正则表达式且大小写不敏感。

>表示另一个Vim中的特殊foldlevel, 如>1告诉Vim以1从这个foldlevel打开当前行。记忆方法,从左到右可以进去,所以是从这里开始打开。


对fold的理解
这个玩意就是靠foldlevel来fold,比如的foldmethod=indent时,此时的foldlevel取决于indent数量。

foldmethod=expr时,此时的foldlevel取决于后面表达式的值,后面的返回值也是数字,来表示foldlevel,这个foldexpr=后面一个东西会对每一行计算,最终会算出每一行的foldlevel。所以当我之前设置:set foldexpr=1的时候会全部折叠,其实不管我后面写多少都会全部折叠,因为这样写相当于我把每一行的foldlevel都设置为了1.

这下子fold的原则就通透了:

  1. 每一行都有一个foldlevel。
  2. foldlevel为0则不会折叠。
  3. 相邻的行若有相同的foldlevel则折叠在一起。
  4. 当一个foldlevel如1折叠时,随后的行中若foldlevel高于1也会折叠,直到一个低于1的。

foldexpr的理解
foldexpr得到一个值,进而判断这一行是否为fold。


50 Section Movement Theory

Read :help section


Nroff

nroff和troff都起源于roff,是一种类似于LaTex和Markdown的语言,用于UNIX和UNIX-like操作系统,是man page的排版格式。

.SH是section heading.


[[]]用于找{.

[]][用于找}.


51 Potion Section Movement

Read :help line-continuation


首先,<SID>在脚本运行时会被扩展为<SNR>12_,12是我随便写的数字,所以可以把视为下面的简写形式,这个数字是用于标记当前脚本的unique number。

它解决了一个问题,在Vim中,你调用了一个函数,它不知道其在哪里定义的,能让Vim找到它的定义。


Base Movement

%^ a special Vim regent atom that means “beginning of file”

Read :help search()
Read :help ordinary-atom


52 External Commands

silent理解
就是屏蔽掉输出的报告信息,就是回到命令行界面,然后说press enter to return的那种。


system()

The system() function takes a command string as a parameter and returns the output of that command as a String.

Read :help bufname
Read :help bufbyte
Read :help append()
Read :help split()
Read :help :!
Read :help read
Read :help read!
Read :help system()
Read :help design-not
Read :help bufwinnr()


53 Autoloading

如:

call somefile#Hello()

则Vim会寻找~/.vim/autoload/somefile.vim文件

Read :help autoload
Read :help silent!


54 Documentation

通过filetype可以做很多事,比如:set filetype=help能够使用help文档的高亮。

Read :help help-writing
Read :help :left
Read :help :right
Read :help :center


55 Distribution


56 What Now?

Read :help highlight
Read :help user-commands
Read :help runtimepath
Read :help ins-completion
Read :help omnifunc
Read :help come-omni
Read :help quickfix.txt
Read :help perl-using


Learn Vimscript the Hard Way Notes
http://example.com/2022/08/25/Learn Vimscript the Hard Way Notes/
作者
Jie
发布于
2022年8月25日
许可协议