Learn Vimscript the Hard Way Notes
第二次阅读
14 Autocommand Groups
需要用 augroup
包裹. 对同一个组多次使用 augroup
其会叠加.
用 augroup
可能是方便组织.
如:
1 |
|
要想重写则使用 autocmd!
1 |
|
针对某种文件:
1 |
|
40 Paths
40.1 Absolute Paths
1 |
|
输出当前文件名.
1 |
|
输出当前路径。
1 |
|
指定当前目录下的一个文件名 (不管是否存在),显示他的绝对路径.
40.2 Listing Files
列出当前目录下的所有文件名.
1 |
|
其返回的是一个 string
, 每名字之间用换行符分隔. 为了提取出来,使用 split()
函数:
1 |
|
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
使用: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
setting
:setlocal
作用于当前缓冲区。
:set
设置的是全局值。
一个window就是一个buffer。
:setglobal
,设置全局值,但不改变当前buffer的变量。
2022/6/2
12 Autocommand
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
一般把BufRead
和BufNewFile
两个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后,在读文件之后触发。
Read
和Write
一般是命令中间。
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:
- Start at the cursor position
- Enter visual mode(charwise)
- …mapping keys go here…
- 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
set
和let
的区别。
这里可能要区分选项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’ ’>’
.
execute
和normal!
结合可以解决以上问题。
: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>num
num表示一个特殊的数字。
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,mkview
和 loadview
.
用viewdir
选项查看。
按照缩进foldset foldmethod=indent
foldlevel
和shiftwidth
相关。
利用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的原则就通透了:
- 每一行都有一个foldlevel。
- foldlevel为0则不会折叠。
- 相邻的行若有相同的foldlevel则折叠在一起。
- 当一个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是我随便写的数字,所以可以把
它解决了一个问题,在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