最後更新: 2022-12-16
介紹
在 Debian 5 內的 vim 是 vim-tiny 來, 它比原本的 vim 輕巧, 不過少了許多功能 ...
最少沒有了"語法高亮"及"用上下左右鍵移位"
我們可以用以下指令安裝回原全版的 vim
apt-get install vim
目錄
- 設定檔
- 'modeline' option
- Space & Tab
- 箭嘴外的 "上下左右"
- 多窗分割
- 多檔案編輯
- 快速移動
- Undo & Redo
- 區塊複製
- 在 shell 上執行指令
- 字串取代
- 範圍操作
- 設定功能
- Macro
- Bookmark
- 實用 hotkey
- 編碼
- ^M
- Format Options
- vim save file 過程
- save 多了 1 byte
- 設定 hotkey(shortcut) - noremap
- File Type Detection
- Syntax Highlight
- syntax/modsecurity.vim
- Other
設定檔
vim 共有兩個設定檔, 分別是 global 檔 及 personal 檔
它們是 /etc/vim/vimrc 及 ~/.vimrc
vimrc 的 config file 係相當有趣的, 它可以 include 東西入去, 如
source /path/to/external/file
以下是我的 .vimrc 設定
set nocompatible
" 可以用返上下左右鍵
set nu
" 顯示行數
set incsearch
" Live Search
set autoindent
set tabstop=4
" 自動縮排, 且 tab 會看成 4 個 space 寬
syntax enable
set syntax=automatic
" 啟用自動 highlight (syntax=???)
source ~/.my-vim-key
" 載入另一檔案
~/.my-vim-key
" view next buffer map <Esc>OC <C-right> map <C-right> <Esc>:bn<CR> " view before buffer map <Esc>OD <C-left> map <C-left> <Esc>:bn<CR> “Hot key to switch between Big5 and UTF-8 set <C-u>=^U set <C-b>=^B map <C-u> :set fileencoding=utf-8<CR> map <C-b> :set fileencoding=big5<CR>
從以上檔案好易看出, " 是代表 comments
map 是綁 keyboard 鍵的功能
在 .my-vim-key上, 我用了雙重 keyboard 綁定 @@"
這是因為經 putty 後, vi-tiny 的方向鍵會失效 .....
詳細請看 Escape character
首先我把 putty 輸出的 "Ctrl+右" map 成 terminal 的 "Ctrl+右" 先
之後再綁定 vi 的 "Ctrl+右" 的功能
'modeline' option
將 vim 的設定寫在被修改的檔案首尾N行, 打開它時自動套用.
Help
:help 'modeline'
Enabling modeline
~/.vimrc
set modeline
Remark
1. Debian-based distros disables modeline by default
/usr/share/vim/vim*/debian.vim
2. modeline 預設 detect 頭尾 5 行
set modelines=5
Checking
:set modeline? modelines?
modeline modelines=3
:verbose set modeline?
modeline
Last set from ~/.vimrc
Usage
# vim: sts=4:ts=4:sw=4:paste:et
"et" 要放在最尾, 否則會唔 work
Space & Tab
Tab 與 Space 的 ASCII
hexdump -C test.txt
20 = 空格, 0a = 新行, 09 = tab
00000000 20 20 20 20 0a 09 0a | ...|
Setting
- et (expandtab)
- ts (tabstop)
- sw (shiftwidth)
- sts (softtabstop)
- sta (smarttab)
show current setting
* default setting 係不會 display 出來的
:set
:set ts sw sts
expandtab (et)
# 按 "tab" 時, 會用 "ts" 數量的空格取代 tab
# real tab character use Ctrl-V<Tab>
# 建議 et 前 settings
# set 'shiftwidth' and 'softtabstop' to the same value, while leaving 'tabstop' at its default value
:set et
tabstop (ts) # default 8
在 et 情況
設定每次按 TAB 相當多小個空格
在 noet 情況
設定一個 tab 顯示成多少個空格 (沒有 et 情況下)
shiftwidth (sw) # default 8
1. Number of spaces to use for each step of autoindent.
2. shiftwidth governs indentation via ">>" (:help shift-left-right)
set shiftwidth=8 makes it so that each >> you do will
indent a line 8 character blocks more to the right.
* 建議 shiftwidth=0 => 令它與 tabstop 保持一致
:set sw=0
softtabstop (sts) # Default 0 => tabs are always 'tabstop' positions
Number of spaces that a <Tab> counts for while performing editing operations
* It affects what happens when you press the <TAB> or <BS> keys.
> 空格轉換成TAB
> makes spaces feel like tabs ( i.e. Deleting 時, 將 N 個 space 當做 1 個 tab 去 Delete )
* "x"(DEL) still work on the actual characters.
noet
If softtabstop is less than tabstop
=> vim will use a combination of tabs and spaces to make up the desired spacing.
If softtabstop equals tabstop
=> vim will always use tabs.
et
vim will always use the appropriate number of spaces.
Example
:set ts=8 sts=4 noet
第一次按 Tab 鍵時, vim 會插入 4 個空格, 而不是插入一個 "tab"
(由於 ts=8 及 noet, 所以它會看成 8 空格寬)
開新行(ENTER), 按 Tab 鍵(插入 4 個空格),
再按 Tab 鍵時, vim 會刪除前面的 4 個空格, 然後插入一個 tab 字符.
Remark
1. Backspace
在插入模式下手動輸入 4 個空格, 此時按 Backspace 鍵只能刪除一個空格.
退出插入模式, 再進入插入模式, 就能用 Backspace 鍵一次性刪除這 4 個空格.
smarttab (sta)
on: A "Tab" in front of a line inserts blanks according to'shiftwidth'
off: A "Tab" always inserts blanks according to 'tabstop' or 'softtabstop'
What gets inserted (a <Tab> or spaces) depends on the 'expandtab' option.
將 file 內所有 tab 換成"空格"
# Change all the existing tab characters to match the current tab settings
# After the 'expandtab' option is set
:retab
OR
:%s/\t/ /g
某類 file 用特定的 type
~/.vimrc
autocmd FileType python setlocal shiftwidth=4 tabstop=4 expandtab autoindent softtabstop=4
Compatible mode in Vim
# When you :set compatible, all the enhancements and improvements of Vi Improved are turned off.
a "vi" command that is implemented with "vim" in compatible mode
:set nocp
highlight search
# enable
:set hlsearch
# disable
:nohlsearch
# To turn off highlighting until the next search
:noh
箭嘴外的 "上下左右"
在這裡不能不提的是, 在 tiny-vim 裡,
上下左加只能用 k, j, h, l 這一行鍵操控. 原因=不詳 = , =??
圖示:
k
h l
j
多檔案編輯
多檔案編輯是指用同一個 vi 打開多個檔案, 如
vi /etc/passwd /etc/group
查看開了什麼檔案
:ls
1 %a "/etc/resolv.conf" line 1 2 "/etc/passwd" line 0
我們可以用以下指令在它們之間切換
:n 編輯下一個檔案
:N 編輯上一個檔案
:files 列出正在在開啟的檔案
不過, 在 vi 內用 :e [file] 打開的檔案就叫作 buffer
它們不能用 :n, :N 切換 @@" 何苦呢 ??
因此要用以下 buffer 指令
:bn 編輯下一個檔案
:bp 編輯上一個檔案
:buffers 列出正在開啟的檔案 (如同 :files)
:buffer n 跳到開啟的 檔案n
多窗分割
:sp [filename] 啟用多窗模式
ctrl+w k 移到上面的視窗。
ctrl+w j 移到下方的視窗。
ctrl+w q 結束當前視窗 ( :q )
快速移動
e – jump to the end of the current word
b – jump to the beginning of the current word
w - jump to the beginning of next word
B – jump to the beginning of previous word
0 行頭
$ 行尾
% 移到相對應的 (){}[]
n| 移到第 n column
{ – move the cursor to the start of the current paragraph
} – move the cursor to the end of the paragraph.
Undo & Redo
u Undo
. Redo
:e [file] 除消所有修改(重開 file)
=======================================
區塊複製:
- v 單字選擇 ("-- VISUAL --")
- V 整行選擇 (可連續多行 "-- VISUAL LINE --")
- ctrl+v 區塊選擇 ("-- VISUAL BLOCK --")
- y 複製選擇了的地方
- d 刪除選擇了的地方
In visual block mode, you can press I to insert text at the same position in multiple lines
Ctrl-V-> select the block -> press I -> type # -> Esc
* I 一定要大寫
help:
:h v_b_I
Visual-block Insert *v_b_I*
* 要 vim 才有完整支援
=======================================
在 shell 上執行指令:
:! command
如 :!ls
=======================================
字串取代:
:n1,n2s/word1/word2/
// 一次取代
它是指在 n1 與 n2 行之後, 把 word1 取代成 word2
k //重複以上取代指令
:n1,n2s/word1/word2/g
// 執行取代直到文尾
:1,$s/word1/word2/gc
// 使用者確認 (conform) 是否要取代當前一字
相當於
:%s/OLD/NEW/g
=======================================
範圍操作:
在 vim 上, 單一個數字即代表重複做之後動作幾次, 如
3d
代表刪除 3 行, 相等於 dd, dd, dd, 又如
3dw
代表刪除 3 個字, 相等於 ctrl+w, ctrl+w, ctrl+w
另一方面, 有 , 豆號的代表一個範圍, 如
4,7d
這個刪除 第 4 行 至 第 7 行 的內容 ~
Remark
dd 刪除一行
dw 刪除一個字
D 刪至行尾
d0 刪至行首
設定功能
顯示行號:
:set nu
自動縮排: autoindent(ai) 與 smartindent(si)
autoindent
...
smartindent
Normally 'autoindent' should also be on when using 'smartindent'.
* When typing '#' as the first character in a new line, the indent for that line is removed
自動儲存備份檔
:set backup
// 在編輯的檔案會 backup 成 filename~
語法顏色(syntax)
# Enable(on) / Disable(off) syntax highlight
:syntax on
# 設定用什麼 highlight
# set filetype
:set ft=dosini
# set syntax
:set syntax=dosini
# 查看此 syntax highlight 了什麼
:syntax list
No Syntax items defined for this buffer
OR
--- Syntax items --- dosiniNumber xxx match /\<\d\+\>/ match /\<\d*\.\d\+\>/ match /\<\d\+e[+-]\=\d\+\>/ links to Number dosiniLabel xxx match /^.\{-}=/ links to Type dosiniHeader xxx start=/^\s*\[/ end=/\]/ links to Special dosiniComment xxx match /^[#;].*$/ links to Comment
自定 Syntax - nginx
套用別人寫好的 Syntax
ls /usr/src/nginx/nginx-1.16.0/contrib/vim
ftdetect ftplugin indent syntax
cp -a /usr/src/nginx/nginx-1.16.0/contrib/vim ~/.vim
設定
用 filepath 設定 filetype
~/.vim/ftdetect/nginx.vim
au BufRead,BufNewFile *.nginx set ft=nginx au BufRead,BufNewFile */etc/nginx/* set ft=nginx au BufRead,BufNewFile */usr/local/nginx/conf/* set ft=nginx au BufRead,BufNewFile nginx.conf set ft=nginx
Notes: au
:au[tocmd] [group] {event} {pat} [nested] {cmd}
Add {cmd} to the list of commands that Vim will execute automatically on {event} for a file matching {pat}.
~/.vim/syntax/nginx.vim
" Vim syntax file " Language: nginx.conf if exists("b:current_syntax") finish end " general syntax ...
Macro
q mymacro 最之後的操作建立為 mymacro
q 中止記錄
@mymacro 執行 mymacro
Bookmark
建立
mc // 將當前一行 bookmark 為 c
它支援 characters 有 a-z 不過只能用單字母
a-z 只用於當前檔案, 離開後就消失
0-9 留了給 "最近開過的檔案"月1
A-Z 係擁有永久保存能力的 bookmark 來, 而且可以跨
此外, 我們可以用 :marks 查看 bookmark 了什麼
跳到
'c // 返回 bookmark c
刪除
:delmarks [markid] ... // 刪除數個指定的 bookmark
:delmarks! // 刪除所有 bookmark
實用 hotkey
ZZ 保存並且離開 (相等於 :x)
ZQ 離開 (相等於 :q!)
它們只會在瀏覽模式下生效
":wq" vs ":x"
它們都是寫入檔案並退出, 分別在於
:wq 即使檔案沒有被修改也寫入(更新檔案的修改時間)
:x 僅當檔案被修改時才寫入
編碼
- set encoding=utf8
- set fileencoding=utf-8
set encoding=utf8
# 指定 Vim 內部對於文字編碼方式
# The encoding written to file.
set fileencoding=utf-8
# This is a list of character encodings considered when starting to edit an existing file.
# Vim tries to use the first mentioned character encoding. If an error is detected, the next one in the list is tried
# If all fail, 'fileencoding' is set to an empty string, which means the value of 'encoding' is used.
# (The encoding written to file.)
Disable automatic comment insertion
[方案1]
# turn off smartindenting and autoindenting
:set nosi noai
[方案2]
# turn on paste before pasting
:set paste
paste
:set nopaste
[方案2]
# 有時縮是 filetype 負責的
:filetype plugin indent off
^M
^M is a carriage return, and is commonly seen when files are copied from Windows (Control+M or ^M)
Line Feed(LF) – \n # a move to the next line
Carriage Return(CR) – \r # to move the position of the cursor to the first position on the same line
* Windows should be "CR+LF" whereas on Unix, it's just "LF"
<CRLF> # \r\n
Unix uses 0xA for a newline character. Windows uses a combination of two characters: 0xD 0xA.
You can remove all the ^M characters by entering the following:
:%s/CTRL-V+CTRL-M/\r/g
Format Options
# check your format options:
:set formatoptions?
P.S.
縮寫 formatoptions => fo
Default:
formatoptions=tcq
# 設定
(-=)
(+=)
# formatoptions=croql
:set formatoptions-=r
# stop Vim from auto-creating comments
To disable it while hitting ENTER in insert mode
set formatoptions-=r
To disable it while hitting o or O in normal mode
set formatoptions-=o
# Help
:help fo-table
:help 'formatoptions'
vim save file 過程
mySecRules.conf -> mySecRules.conf~
.mySecRules.conf.swp -> mySecRules.conf
delete mySecRules.conf~
多了 1 byte
vim test.txt
i A <Esc> ZZ # 插入一個字 A (0x41)
"test.txt" [New] 1L, 2C written
即使只鍵入一個字, test.txt 也會多了 0a (Line Feed - \n)
hexdump -C test.txt
00000000 31 0a |1.| 00000002
設定 hotkey(shortcut) - noremap
echo "noremap ww :w<CR>" >> ~/.vimrc
noremap = Normal-Mode "Remap"
Color Scheme
ls -1 /usr/share/vim/vim*/colors/
... default.vim
查看用緊那 scheme
:colorscheme
default
設定
:colorscheme delek
highlight
查看當前 colorscheme 的顏色
:highlight
highlight clear # to reset everything to the defaults
background
set background={light or dark}
File Type Detection
vim 一共有兩個 detection 方式, 分別:
- filename
- inspecting the contents of the file for specific text.
查看現在的 filetype
:filetype
filetype detection:ON plugin:ON indent:OFF
它們的 ON/OFF
- :filetype on
- :filetype plugin on # enable loading the plugin files for specific file types
- :filetype indent on
:verbose set ft ?
filetype=nginx Last set from ~/.vim/ftdetect/nginx.vim
設定 syntax
:set syntax=modsecurity
ftplugin (filetype plugin)
This lets us execute arbitrary Vimscript or set other settings whenever the file is sourced.
檔案: modsecurity.vim
" ftplugin/modsecurity.vim setlocal commentstring=#\ %s setlocal tabstop=2 setlocal softtabstop=2 setlocal shiftwidth=2 setlocal expandtab setlocal syntax=modsecurity
commentstring
A template for a comment.
Currently only used to add markers for folding.
The "%s" in the value is replaced with the comment text.
所以 comment 的 color 不是由它設定
設定自定的 filetype
~/.vim/ftdetect/12-modsecurity.vim
augroup filetype au! au BufRead,BufNewFile /etc/nginx/modsec/*.rules set ft=modsecurity au BufRead,BufNewFile /etc/nginx/modsec/*.conf set ft=modsecurity augroup END
# 加 "12-" 的原因
ls -1 ~/.vim/ftdetect
11-nginx.vim 12-modsecurity.vim
:au[tocmd] [group] {event} {pat} [nested] {cmd}
When the [group] argument is not given, Vim uses the current group (as defined with ":augroup");
otherwise, Vim uses the group defined with [group].
Syntax Highlight
Vim stores the name of the syntax that has been loaded in the "b:current_syntax" variable.
The order in which syntax scripts are sourced
應用1: 查看當前的 syntax
:echo b:current_syntax
python
Notes
:setlocal syntax?
syntax=nginx
應用2: stop vim reading default syntax
* prevents it from being loaded if syntax highlighting has already been enabled for this buffer.
if exists("b:current_syntax") finish end let b:current_syntax = "modsecurity" ...
The order in which syntax scripts are sourced
:scriptnames
1: /etc/vimrc 2: /usr/share/vim/vim74/syntax/syntax.vim 3: /usr/share/vim/vim74/syntax/synload.vim 4: /usr/share/vim/vim74/syntax/syncolor.vim 5: /usr/share/vim/vim74/filetype.vim ...
查看 syntax cmd
:syntax list
自定 Syntax
" Vim syntax file " Language: modsecurity if exists("b:current_syntax") finish end syn match modsecComment '\v#.*' hi def link modsecComment Comment syn keyword modsecKeyword SecRule hi def link modsecKeyword Keyword syn keyword modsecVariable REQUEST_URI REQUEST_FILENAME QUERY_STRING hi def link modsecVariable Identifier syn keyword modsecVariable REQUEST_HEADERS nextgroup=reqHeader syn match reqHeader '\v:\w+' contained hi def link reqHeader PreProc syn region Oper start=/\v\s"\S/ skip=/\v\\./ end=/\v\S"\s/ hi def link Oper Operator syn region Action start=/\v\s"id=/ skip=/\v\\./ end=/\v\S"\n/ skipwhite skipnl hi def link Action String let b:current_syntax = "modsecurity"
File Header
" Vim syntax file " Language: modsecurity
Start with a header that explains what the syntax file is for
防止 syntax file double load
if exists("b:current_syntax") finish end let b:current_syntax = "modsecurity"
syntax
syntax 的設定一共有 3 種方式, 分別係 Keywords, Match, Region
keyword
syn keyword modsecKeyword SecRule syn keyword modsecVariable REQUEST_URI REQUEST_FILENAME
match
syn match FooKey /REQUEST_HEADERS:\w/
Magic (\X)
\v # "^$.*+()|" 等直接係有 regex 的功效, 不用加 \ 在前 (e.g. \* \.)
- \d+ match one or more digits
- \s whitespace character
- \S non-whitespace character; opposite of \s
- \w word character: [0-9A-Za-z_]
- \W non-word character: [^0-9A-Za-z_]
nextgroup
nextgroup={groupname}
i.e.
syn keyword MyKey1 MyKey2 nextgroup=myNumber skipwhite syn match myNumber '\d\+'
會中 "MyKey1 1234", "MyKey2 5678"
skipX(skipwhite skipnl skipempty)
skipnl (:help syn-skipnl)
When "skipnl" is present, the match with nextgroup may be found in the next line.
skipwhite
The match must begin exactly after the end of the current group.
If you need to include the leading whitespace in the id group match: \s\+, or add skipwhite.
"contains" 與 "containedin"
"contains=GRUOP"
To configure other syntax highlighting groups to be contained within an "outer group".
syn keyword myKeyword int syn region BraceBlock start='{' end='}' contains=myKeyword
* The "contains=" argument is also inherited from the item it is contained in
To avoid that unwanted items are contained, use "contains=NONE"
* "contains=CONTAINED" If the first item in the contains list is "CONTAINED",
then all groups will be accepted that have the "contained" argument.
* "contains=CONTAINED,{group-name},..
Like "CONTAINED", but excluding the groups that are listed.
"containedin=GRUOP"
syn region BraceBlock start='{' end='}' syn keyword myKeyword int containedin=BraceBlock
"contained"
When the "contained" argument is given, this item will not be recognized at the top level,
but only when it is mentioned in the "contains" field of another match.
=> To avoid that the group matches anywhere else, just add contained.
syn region BraceBlock start='{' end='}' contains=CONTAINED syn keyword myKeyword int contained
region
syntax region msOper start=/\v\s"\S/ skip=/\v\\./ end=/\v\S"(:?\n|\s)/ contained
"skip"
skip=/\v\\./
To ignore anything that matches skip, even if it would normally be considered the end of the region
i.e.
"She said: \"Vimscript is tricky, but useful\"!".
Cluster
A list of syntax groups together under a single name.
syntax keyword myKeyword int
syntax region BraceBlock start='{' end='}' contains=@myCluster
syntax cluster myCluster contains=myKeyword
syntax keyword myConditional if else
syntax cluster myCluster add=myConditional
Usage
調用 cluster: @ClusterGroup
contains={group-name}
The cluster is set to the specified list of groups.
add={group-name}
The specified groups are added to the cluster.
remove={group-name}
The specified groups are removed from the cluster.
highlight
highlighting group = color scheme
List highlighting group
:highlight # 看每個 Group 的顏色
:help group-name # Color Group 的名稱
設定顏色的方法
- To set a link
- 設定 Group 的顏色
To set a link:
:hi[ghlight][!] [default] link {from-group} {to-group}
The [default] argument is used for setting the default highlighting for a group.
If highlighting has already been specified for the group the command will be ignored.
i.e.
highlight link modsecKeyword Keyword
"link" keyword group(i.e. modsecKeyword) to a highlighting group( i.e. Keyword)
To remove a link:
:hi[ghlight][!] [default] link {from-group} NONE
設定 Group 的顏色
highlight GROUP ctermfg=COLOR
ctermfg # 字
cterm # 背景
guifg # 字
guibg # 背景
i.e.
ctermfg=Yellow
Color Name
# "NR-16" is used for 16-color terminals
:h cterm-colors
NR-16 COLOR NAME 0 Black 1 DarkBlue 2 DarkGreen 3 DarkCyan 4 DarkRed 5 DarkMagenta 6 Brown, DarkYellow 7 LightGray, LightGrey, Gray, Grey 8 DarkGray, DarkGrey 9 Blue, LightBlue 10 Green, LightGreen 11 Cyan, LightCyan 12 Red, LightRed 13 Magenta, LightMagenta 14 Yellow, LightYellow 15 White
Other
輸入特別字元
在 insert mode 內, 我們可以鍵入 ctrl+v 之後,
輸入特別字元的 ascii 碼, 那就可輸入它們
如 ctrl+v 48 是 0