星期三, 五月 27, 2020

VIM学习笔记 工具箱-大写锁定键(Caps)映射为Esc

今天要处理一起拆迁事件 — 把地处黄金地段的大写锁定键Caps Lock更换为Esc键。

至于,为什么地处偏僻的Esc被时常造访,而位置绝佳的Caps Lock却长期空置?根据考古发现,很可能是由于远古程序员使用了以下布局的祖传键盘:

keyboard_esc

Windows

下载并安装Microsoft PowerToys;在“Keyboard Manager”设置中,点击“Remap a key”,然后将Caps Lock映射为Esc

Caps2Esc_Win_PowerToys

如果您不需要PowerToys提供的窗口管理、批量重命名和快速应用启动等众多功能,那么可以下载Uncap;它没有任何图形界面,只需要后台运行单一的“uncap.exe”文件,即可将Caps Lock映射为Esc

如果需要在系统启动时自动完成键盘映射,那么可以在Windows注册表的以下节点中增加启动项:

Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

Caps2Esc_Win_Uncap

Linux

下载并安装GNOME Tweak tool;在“Keyboard & Mouse”设置中,点击“Additional Layout Options”;在“Caps Lock behavior”列表中选择“Caps Lock an additionnal Esc”。

Caps2Esc_Linux_GnomeTweakTool

Mac

打开“系统偏好设置”,进入“键盘”选项,点击“修饰键...”按钮,将大写锁定键的行为更改为Escape

Caps2Esc_Mac_Keyboard

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 五月 24, 2020

VIM学习笔记 4种Magic模式

根据对于特殊元字符的不同解释方式,Vim正则表达式可以分为四种模式:magic,no magic,very magic和very nomagic。

  • magic模式,使用\m前缀,其后模式的解释方式为'magic'选项。^$.*[]等字符含有特殊意义;而+?()、和{}等其它字符则按字面意义解释。magic为默认设置,表达式中的\m前缀可以省略;
  • no magic模式,使用\M前缀,其后模式的解释方式为'nomagic'选项。除了^$之外的特殊字符,都将被视为普通文本;
  • very magic模式,使用\v前缀,其后模式中除 '0'-'9','a'-'z','A'-'Z' 和 '_' 之外的字符都当作特殊字符解释;
  • very nomagic模式,使用\V前缀,其后模式中只有反斜杠(\)具有特殊意义。

不同模式之间的区别,在于哪些特殊字符需要使用反斜杠(\)进行转义。例如星号(*),在magic和very magic模式下视为特殊修饰符;而在no magic和very nomagic模式下则被视为普通字符,必须使用“\*”恢复其特殊作用。

对于简单的正则表达式,使用“\”对特殊字符进行转义,可能并不会造成困扰;但在复杂的正则表达式中,对大量特殊字符的重复转义,将使得表达式过于繁琐且难以阅读。

例如在默认的magic模式下,使用以下命令查找十六进制色彩值。其中,使用()构建捕获组;使用{}匹配6位和3位十六进制值。因为有多种特殊字符需要进行转义,造成表达式过于冗长:

/\m#\(\x\{6\}\|\x\{3\}\)

而使用very magic模式,则可以简化表达式:

/\v#(\x{6}|\x{3})

4种Magic模式的差异和用法,可以简单总结如下:

模式前缀特殊字符示例适用场景
magic\m^$.*[]匹配每行中的任意内容/^.*$默认模式
nomagic\M^$/\M^\.\*$查找字符串中包含特殊字符
very magic\v除'0-9','a-z','A-Z','_'之外匹配十六进制色彩值/\v#(\x{6}|\x{3})使用较多特殊字符的复杂正则表达式
very nomagic\V\匹配正则表达式本身/\V^.*$进行精确的完整匹配
查找字符串中包含特殊字符

以下表格,列示了常用特殊字符在不同模式下的应用。其中,黄色高亮表示为特殊字符,而不需要转义:

very magicmagicnomagicvery nomagic用途
\v\m\M\V
^^^\^匹配行首
$$$\$匹配行尾
..\.\.匹配任何字符
**\*\*匹配任意次数
~~\~\~最近替代字符串
[][]\[]\[]匹配列表范围内的字符
{}\{\}\{\}\{\}匹配重复次数
()\(\)\(\)\(\)匹配组
<>\<\>\<\>\<\>匹配词首与词尾
+\+\+\+匹配一次或多次
?\?\?\?匹配零次或一次
|\|\|\|可选分支
\a\a\a\a字母字符
其它特殊字符元素
\\\\\\\\反斜杠 (字面意义)

magic默认模式

建议始终将'magic'选项保持在缺省值。

建议在模式之前,通过使用“\v“或“\M“等前缀,来明确激活特定模式。

如果希望始终使用Very magic模式,那么请在vimrc中定义以下键盘映射,将在查找和替换时自动激活very magic模式:

nnoremap / /\v
vnoremap / /\v
cnoremap %s/ %s/\v
nnoremap :g/ :g/\v

模式转换

你甚至可以在表达式当中改变模式。例如以下命令,开头使用very magic模式,之后转换为magic模式,整体表达式将匹配“foo(bar)”:

/\vfoo\(\mbar)

当然,非常不建议采用此种易引起误解的表达式写法。我们可以将其改写为very nomagic模式:

/\Vfoo(bar)

请使用以下命令,查看更多帮助信息:

:help /magic

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期六, 五月 16, 2020

VIM学习笔记 正则表达式(Regex-VeryMagic)

假设希望在以下CSS代码中,查找所有颜色代码:

body { color: #3c3c3c; }
strong { color: #000; }

在默认的Magic模式下,使用以下命令可以匹配以“#”开头的十六进制色彩值:

/#\([0-9a-fA-F]\{6}\|[0-9a-fA-F]\{3}\)

在以上正则表达式中,[]用于指定可选字符范围,但不需要转义;()用于构建捕获组(Groups),需要使用\进行转义;{}用于指定重复次数,但只需要对开括号进行转义,与之对应的闭括号可以不用转义。由此可见,在Magic模式下,需要对很多特殊符号进行转义,而且转义的方式也欠缺一致性。在编写较复杂的正则表达式时,显得琐碎且难以阅读。

使用\v激活Very Magic模式,则可简化为更加友好的正则表达式:

/\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})

body { color: #3c3c3c; }
strong { color: #000; }

Very magic

在模式开头使用\v激活very magic模式,其后除下划线(_)、大小写字母以及数字之外的所有字符都具有特殊含义。这样可以避免重复输入大量的转义符(\),也使得正则表达式更加清晰易读。

假设在以下文本中,希望搜索单引号包围的内容:

you have mocking some 'bird of the year'.
you have mocking some 'the year's bird'.

在默认的magic模式下,使用以下模式来处理单词中的单引号:

/'\('\w\|[^']\)\+'

you have mocking some 'bird of the year'.
you have mocking some 'the year's bird'.

如果使用VeryMagic模式,命令则可以简化为:

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

假设在以下文本中,希望仅保留英文字母:

12345aaa678
12345bbb678
12345ccc678

使用以下替换命令,可以删除其中的数字部分:

:%s/\d\{5\}\(\D\+\)\d\{3\}/\1/

aaa
bbb
ccc

如果使用VeryMagic模式,命令则可以简化为:

:%s/\v\d{5}(\D+)\d{3}/\1/

由此可见,Very magic模式为使用正则表达式提供了极大的便利。但很不幸,我们并无法将Very magic模式设置为默认选项。潜在的替代方案是,定义以下键盘映射,在查找时自动激活very magic模式:

:noremap / /\v

使用以下命令,可以查看更多帮助信息:

:help /\v

Very No Magic

在模式开头使用\V指定Very No Magic模式,将使得其后模式中只有反斜杠(\)具有特殊意义,而()[]|.*?等等元字符都将被视为普通文本。

如果您需要精确的完整匹配,并且查找字符串中包含特殊字符时,那么可以使用Very nomagic模式。

例如以下命令,将查找字符串“Fun.test(*args)” 。也就是说,其中的“*”和“.”都被视为普通字符,而不需要进行转义:

/\VFun.test(*args)

假设需要在以下文本中查找“a.k.a”:

The N key searches backward
the \v pattern switch (a.k.a. very magic)

因为“.”在正则表达式中具有特殊含义,它将会匹配任意字符,所以使用以下命令,将会同时匹配单词“backward”中的部分字符:

/a.k.a

The N key searches backward
the \v pattern switch (a.k.a. very magic)

当然,可以使用转义符来消除“.”的特殊含义:

/a\.k\.a\.

而更简单的方法是,在命令中使用\V激活very nomagic模式:

/\Va.k.a.

此时,将只会按字面匹配到单词“a.k.a”:

The N key searches backward
the \v pattern switch (a.k.a. very magic)

使用以下命令,可以查看更多帮助信息:

:help /\V

小结

我们可以将 very magic 和 very nomagic 模式,理解为对于正则表达式的两种极端处理方式。需要构建较复杂正则表达式时,推荐使用very magic模式;需要按字面意义查找文本时,则推荐使用very nomagic 模式。

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期一, 五月 11, 2020

VIM学习笔记 编译源码(Compile Code)-Python

Python作为一种解释型编程语言,需要解释器来编译并执行Python代码。

测试Python

对于Linux和Mac操作系统,均已预装Python。而在Windows下,可以使用安装包或者直接解压版zip文件。

使用以下命令,可以查看当前Python版本:

$ python --version

python-version

设置动态调用库

新版本的Vim已经默认支持Python。可以使用:version命令,确认是否包含“+python/dyn”和“+python3/dyn”特性。

version_python3

其中dyn,即dynamic,表示可以通过'pythondll'和'pythonthreedll'选项动态调用Python库。

使用set pythonthreedll?命令,可以查看当前动态调用的Python库。以下为Fedora31下的默认设置:

set pythonthreedll=libpython3.7m.so.1.0

如果您的Vim不支持动态调用Python库,那么以上命令将会报错。

如果您仅是下载并解压程序包(而不是进行安装),那么同时需要设置pythonthreehome选项。例如以下命令,在Windows下设置Python3环境:

set pythonthreehome=C:\tools\Python3
set pythonthreedll=C:\tools\Python3\python38.dll

以下命令,可以在Mac下设置Python环境:

" for python 3.X
set pythonthreehome=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7
set pythonthreedll=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/libpython3.7m.dylib
" for python 2.X
set pythonhome=/System/Library/Frameworks/Python.framework/Versions/2.7
set pythondll=/System/Library/Frameworks/Python.framework/Versions/2.7/Python

请注意,在您的环境中Python所处的路径可能会不同。请在操作系统中使用以下命令,查看Python系统路径:

$ python -c "import sys; print(sys.path)"

python_sys_path

请使用以下命令,查看更多帮助信息:

:help python-dynamic
:help 'pythonhome'
:help 'pythonthreehome'

设置编译器

使用以下命令,设置'makeprg'选项为python3命令:

set makeprg=python3\ %

通过在vimrc文件中增加以下自动命令,可以为Python源码文件设置编译快捷键:

augroup make_python
 au!
 au FileType python set makeprg=python3\ %
 au FileType python map <buffer> <leader><space> :w<cr>:make<cr>
augroup end

编译Python代码

使用以下命令,将根据'makeprg'选项编译并执行Python文件:

:make

如果编译出现错误,将在QuickFix中显示错误列表,并自动跳转到第一个错误处:

python_error_quicklist_multiple

启用以下内置的编译器,再执行:make编译命令,报错信息将被整合为一行:

:compiler pyunit

python_error_quicklist_single

如果希望在编译时保持当前光标位置不变,那么可以使用以下命令:

:make!

使用:cw命令,将打开quickfix窗口。使用:cp命令,跳转到上一个错误;使用:cn命令,跳转到下一个错误。关于QuickFix操作的更多信息,请参阅QuickFix章节。

在修复错误并成功编译之后,将显示命令输出:

python_success_output

使用以下命令,将解释执行当前文件:

:!python3 %

如果执行不带任何参数的python3命令,那么将进入交换模式的python shell,您可以在其中直接执行python命令:

:!python3

Python3_i

使用以下命令,可以退出交换模式的python shell:

import sys; sys.exit()

您也可以直接使用Vim内置的:python3命令来执行代码:

:py3 print('hello world')

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 五月 03, 2020

VIM学习笔记 替换字符串中的submatch()

submatch({nr})函数,只用于 :substitute 命令或 substitute() 函数中。它将返回匹配文本的第{nr}个子匹配。如果{nr}为0,则返回整个匹配文本。

将submatch()和其它函数相结合,可以对替换文本进行更丰富的操作。使用:help submatch()命令,可以查看更多帮助信息。

更新列表序号

如果希望在第1条之后插入一个新的条目,那么就意味着需要调整后续各个条目的序号:

Article 1: 3 Steps To Enable Thesaurus Option
Article 2: Steps to Add Custom Header
Article 3: Automatic Word Completion
Article 4: How To Record and Play Macro
Article 5: Make Vim as Your C IDE

使用以下命令,将第2行及之后各行中的序号分别加1:

:2,$s/\d\+/\=submatch(0) + 1/

Article 1: 3 Steps To Enable Thesaurus Option
Article 3: Steps to Add Custom Header
Article 4: Automatic Word Completion
Article 5: How To Record and Play Macro
Article 6: Make Vim as Your C ID

请注意,替换命令中并没有使用/g标志,因此将仅仅替换第一个匹配字符,以避免条目文本中的数字也被更改。

转换单词大小写

假设需要在以下条目中,将首个单词的首个字母转换为大写:

The following activities can be done using vim:
a. source code walk through,
b. record and play command executions,
c. making the vim editor as ide

使用以下命令,将匹配“.”及空格之后的单词字符(0-9A-Za-z),并替换为大写:

:%s/\.\s*\w/\=toupper(submatch(0))/g

The following activities can be done using vim:
a. Source code walk through,
b. Record and play command executions,
c. Making the vim editor as ide

替换文件路径

将当前光标下的相对路径名,替换为完整的绝对路径名:

:s/\f*\%#\f*/\=fnamemodify(submatch(0), ':p')/

其中,\= 表示使用表达式作为替换字符串(请参考帮助信息:help sub-replace-expression);\f*\%#\f* 将匹配文件名(请参考帮助信息:help /\f) 。

如果希望将可视化模式下选中的文件名,替换为完整的绝对路径名,那么在命令中使用\%V参数:

:s/\%V.*\%V/\=fnamemodify(submatch(0), ':p')/

数据补零

将每行数据中不满8位的字符串,向右对齐并在前部以0补足8位:

:%s/.*/\=printf('%08s',submatch(0))/g

submatch_08s

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>