NOTICE: 本プラグインはまだ開発段階であり、事前告知なくインターフェースが変更となることがあります。
2022/02/20 に v0.3.0 がリリースされ、既存のインターフェースとの互換性がなくなりました。 以前のバージョン向けの設定を行っていた方は、TROUBLESHOOTING.md を参考に再設定を行ってください。
Neovim の数値増減機能を拡張する Lua 製プラグイン。
既存の <C-a>
や <C-x>
コマンドを拡張し、数値以外も増減・トグルできるようにします。
- 数値をはじめとする様々なものの増減
- n 進数 (
2 <= n <= 36
) の整数 - 日付・時刻
- キーワードや演算子など、所定文字列のトグル
true
⇄false
&&
⇄||
a
⇄b
⇄ ... ⇄z
日
⇄月
⇄ ... ⇄土
⇄日
⇄ ...
- Hex color
- SemVer
- n 進数 (
- VISUAL mode での
<C-a>
/<C-x>
/g<C-a>
/g<C-x>
に対応 - 増減対象の柔軟な設定
- 特定のファイルタイプでのみ有効なルールの設定
- VISUAL モードでのみ有効なルールの設定
- カウンタに対応
- ドットリピートに対応
本プラグインには Neovim 0.5.0 以上が必要です(Neovim 0.6.1 以降を推奨)。
好きなパッケージマネージャの指示に従うことでインストールできます。
本プラグインはデフォルトではキーマッピングを設定/上書きしません。 本プラグインを有効にするには、いずれかのキーに以下のような割り当てを行う必要があります。
nmap <C-a> <Plug>(dial-increment)
nmap <C-x> <Plug>(dial-decrement)
nmap g<C-a> g<Plug>(dial-increment)
nmap g<C-x> g<Plug>(dial-decrement)
vmap <C-a> <Plug>(dial-increment)
vmap <C-x> <Plug>(dial-decrement)
vmap g<C-a> g<Plug>(dial-increment)
vmap g<C-x> g<Plug>(dial-decrement)
注意: g<Plug>(dial-increment)
や g<Plug>(dial-decrement)
を右辺で用いる場合は remap を有効にする必要があります。
または Lua 上で以下のように設定することもできます。
vim.keymap.set("n", "<C-a>", function()
require("dial.map").manipulate("increment", "normal")
end)
vim.keymap.set("n", "<C-x>", function()
require("dial.map").manipulate("decrement", "normal")
end)
vim.keymap.set("n", "g<C-a>", function()
require("dial.map").manipulate("increment", "gnormal")
end)
vim.keymap.set("n", "g<C-x>", function()
require("dial.map").manipulate("decrement", "gnormal")
end)
vim.keymap.set("v", "<C-a>", function()
require("dial.map").manipulate("increment", "visual")
end)
vim.keymap.set("v", "<C-x>", function()
require("dial.map").manipulate("decrement", "visual")
end)
vim.keymap.set("v", "g<C-a>", function()
require("dial.map").manipulate("increment", "gvisual")
end)
vim.keymap.set("v", "g<C-x>", function()
require("dial.map").manipulate("decrement", "gvisual")
end)
dial.nvim では操作対象を表す被加数 (augend) と、複数の被加数をまとめたグループを用いることで、増減させるルールを自由に設定することができます。
local augend = require("dial.augend")
require("dial.config").augends:register_group{
-- グループ名を指定しない場合に用いられる被加数
default = {
augend.integer.alias.decimal, -- nonnegative decimal number (0, 1, 2, 3, ...)
augend.integer.alias.hex, -- nonnegative hex number (0x01, 0x1a1f, etc.)
augend.date.alias["%Y/%m/%d"], -- date (2022/02/19, etc.)
},
-- `mygroup` というグループ名を使用した際に用いられる被加数
mygroup = {
augend.integer.alias.decimal,
augend.constant.alias.bool, -- boolean value (true <-> false)
augend.date.alias["%m/%d/%Y"], -- date (02/19/2022, etc.)
}
}
-
"dial.config"
モジュールに存在するaugends:register_group
関数を用いてグループを定義することができます。 関数の引数には、グループ名をキー、被加数のリストを値とする辞書を指定します。 -
上の例で
augend
という名前のローカル変数に代入されている"dial.augend"
モジュールでは、さまざまな被加数が定義されています。
以下のように expression register (:h @=
) を用いると、増減対象のグループを指定できます。
"=mygroup<CR><C-a>
増減のたびに expression register を指定するのが面倒であれば、以下のようにマッピングすることも可能です。
nmap <Leader>a "=mygroup<CR><Plug>(dial-increment)
また、 Lua 上で以下のように記述すれば expression register を使わずにマッピングを設定できます。
vim.keymap.set("n", "<Leader>a", require("dial.map").inc_normal("mygroup"), {noremap = true})
expression register などでグループ名を指定しなかった場合、default
グループにある被加数がかわりに用いられます。
lua << EOF
local augend = require("dial.augend")
require("dial.config").augends:register_group{
default = {
augend.integer.alias.decimal,
augend.integer.alias.hex,
augend.date.alias["%Y/%m/%d"],
},
typescript = {
augend.integer.alias.decimal,
augend.integer.alias.hex,
augend.constant.new{ elements = {"let", "const"} },
},
visual = {
augend.integer.alias.decimal,
augend.integer.alias.hex,
augend.date.alias["%Y/%m/%d"],
augend.constant.alias.alpha,
augend.constant.alias.Alpha,
},
}
-- VISUAL モードでの被加数を変更する
vim.keymap.set("v", "<C-a>", require("dial.map").inc_visual("visual"), {noremap = true})
vim.keymap.set("v", "<C-x>", require("dial.map").dec_visual("visual"), {noremap = true})
EOF
" 特定のファイルタイプでのみ有効にする
autocmd FileType typescript lua vim.api.nvim_buf_set_keymap(0, "n", "<C-a>", require("dial.map").inc_normal("typescript"), {noremap = true})
autocmd FileType typescript lua vim.api.nvim_buf_set_keymap(0, "n", "<C-x>", require("dial.map").dec_normal("typescript"), {noremap = true})
以下簡単のため、 augend
という変数は以下のように定義されているものとします。
local augend = require("dial.augend")
n 進数の整数 (2 <= n <= 36
) を表します。 augend.integer.new{ ...opts }
で使用できます。
require("dial.config").augends:register_group{
default = {
-- uppercase hex number (0x1A1A, 0xEEFE, etc.)
augend.integer.new{
radix = 16,
prefix = "0x",
natural = true,
case = "upper",
},
},
}
日付や時刻を表します。
require("dial.config").augends:register_group{
default = {
-- date with format `yyyy/mm/dd`
augend.date.new{
pattern = "%Y/%m/%d",
default_kind = "day",
-- if true, it does not match dates which does not exist, such as 2022/05/32
only_valid = true,
-- if true, it only matches dates with word boundary
word = false,
},
},
}
pattern
で指定する文字列には、以下のエスケープシーケンスを使用できます。
文字列 | 意味 |
---|---|
%Y |
4桁の西暦。 (e.g. 2022 ) |
%y |
西暦の下2桁。上2桁は 20 として解釈されます。 (e.g. 22 ) |
%m |
2桁の月。 (e.g. 09 ) |
%d |
2桁の日。 (e.g. 28 ) |
%H |
24時間で表示した2桁の時間。 (e.g. 15 ) |
%I |
12時間で表示した2桁の時間。 (e.g. 03 ) |
%M |
2桁の分。 (e.g. 05 ) |
%S |
2桁の秒。 (e.g. 08 ) |
%-y |
西暦の下2桁を1–2桁で表したもの。(e.g. 9 で 2009 年を表す) |
%-m |
1–2桁の月。 (e.g. 9 ) |
%-d |
1–2桁の日。 (e.g. 28 ) |
%-H |
24時間で表示した1–2桁の時間。 (e.g. 15 ) |
%-I |
12時間で表示した1–2桁の時間。 (e.g. 3 ) |
%-M |
1–2桁の分。 (e.g. 5 ) |
%-S |
1–2桁の秒。 (e.g. 8 ) |
%a |
英語表記の短い曜日。 (Sun , Mon , ..., Sat ) |
%A |
英語表記の曜日。 (Sunday , Monday , ..., Saturday ) |
%b |
英語表記の短い月名。 (Jan , ..., Dec ) |
%B |
英語表記の月名。 (January , ..., December ) |
%p |
AM または PM 。 |
%J |
日本語表記の曜日。 (日 , 月 , ..., 土 ) |
キーワードなどの決められた文字列をトグルします。 augend.constant.new{ ...opts }
で使用できます。
require("dial.config").augends:register_group{
default = {
-- uppercase hex number (0x1A1A, 0xEEFE, etc.)
augend.constant.new{
elements = {"and", "or"},
word = true, -- if false, "sand" is incremented into "sor", "doctor" into "doctand", etc.
cyclic = true, -- "or" is incremented into "and".
},
augend.constant.new{
elements = {"&&", "||"},
word = false,
cyclic = true,
},
},
}
#000000
や #ffffff
といった形式の RGB カラーコードを増減します。 augend.hexcolor.new{ ...opts }
で使用できます。
require("dial.config").augends:register_group{
default = {
-- uppercase hex number (0x1A1A, 0xEEFE, etc.)
augend.hexcolor.new{
case = "lower",
},
},
}
Semantic version を増減します。後述のエイリアスを用います。 単なる非負整数のインクリメントとは以下の点で異なります。
- semver 文字列よりもカーソルが手前にあるときは、パッチバージョンが優先してインクリメントされます。
- マイナーバージョンの値が増加したとき、パッチバージョンの値は0にリセットされます。
- メジャーバージョンの値が増加したとき、マイナー・パッチバージョンの値は0にリセットされます。
ユーザ自身が増減ルールを定義したい場合には augend.user.new{ ...opts }
を使用できます。
require("dial.config").augends:register_group{
default = {
-- uppercase hex number (0x1A1A, 0xEEFE, etc.)
augend.user.new{
find = require("dial.augend.common").find_pattern("%d+"),
add = function(text, addend, cursor)
local n = tonumber(text)
n = math.floor(n * (2 ^ addend))
text = tostring(n)
cursor = #text
return {text = text, cursor = cursor}
end
},
},
}
エイリアスはライブラリで予め定義された被加数です。 new
関数を用いることなく、そのまま使用できます。
require("dial.config").augends:register_group{
default = {
augend.integer.alias.decimal,
augend.integer.alias.hex,
augend.date.alias["%Y/%m/%d"],
},
}
エイリアスとして提供されている被加数は以下の通りです。
Alias Name | Explanation | Examples |
---|---|---|
augend.integer.alias.decimal |
decimal natural number | 0 , 1 , ..., 9 , 10 , 11 , ... |
augend.integer.alias.decimal_int |
decimal integer (including negative number) | 0 , 314 , -1592 , ... |
augend.integer.alias.hex |
hex natural number | 0x00 , 0x3f3f , ... |
augend.integer.alias.octal |
octal natural number | 0o00 , 0o11 , 0o24 , ... |
augend.integer.alias.binary |
binary natural number | 0b0101 , 0b11001111 , ... |
augend.date.alias["%Y/%m/%d"] |
Date in the format %Y/%m/%d (0 padding) |
2021/01/23 , ... |
augend.date.alias["%m/%d/%Y"] |
Date in the format %m/%d/%Y (0 padding) |
23/01/2021 , ... |
augend.date.alias["%d/%m/%Y"] |
Date in the format %d/%m/%Y (0 padding) |
01/23/2021 , ... |
augend.date.alias["%m/%d/%y"] |
Date in the format %m/%d/%y (0 padding) |
01/23/21 , ... |
augend.date.alias["%d/%m/%y"] |
Date in the format %d/%m/%y (0 padding) |
23/01/21 , ... |
augend.date.alias["%m/%d"] |
Date in the format %m/%d (0 padding) |
01/04 , 02/28 , 12/25 , ... |
augend.date.alias["%-m/%-d"] |
Date in the format %-m/%-d (no paddings) |
1/4 , 2/28 , 12/25 , ... |
augend.date.alias["%Y-%m-%d"] |
Date in the format %Y-%m-%d (0 padding) |
2021-01-04 , ... |
augend.date.alias["%Y年%-m月%-d日"] |
Date in the format %Y年%-m月%-d日 (no paddings) |
2021年1月4日 , ... |
augend.date.alias["%Y年%-m月%-d日(%ja)"] |
Date in the format %Y年%-m月%-d日(%ja) |
2021年1月4日(月) , ... |
augend.date.alias["%H:%M:%S"] |
Time in the format %H:%M:%S |
14:30:00 , ... |
augend.date.alias["%H:%M"] |
Time in the format %H:%M |
14:30 , ... |
augend.constant.alias.ja_weekday |
Japanese weekday | 月 , 火 , ..., 土 , 日 |
augend.constant.alias.ja_weekday_full |
Japanese full weekday | 月曜日 , 火曜日 , ..., 日曜日 |
augend.constant.alias.bool |
elements in boolean algebra (true and false ) |
true , false |
augend.constant.alias.alpha |
Lowercase alphabet letter (word) | a , b , c , ..., z |
augend.constant.alias.Alpha |
Uppercase alphabet letter (word) | A , B , C , ..., Z |
augend.semver.alias.semver |
Semantic version | 0.3.0 , 1.22.1 , 3.9.1 , ... |
何も設定しなかった場合は以下の被加数が default
グループの値としてセットされます。
augend.integer.alias.decimal
augend.integer.alias.hex
augend.date.alias["%Y/%m/%d"]
augend.date.alias["%Y-%m-%d"]
augend.date.alias["%m/%d"]
augend.date.alias["%H:%M"]
augend.constant.alias.ja_weekday_full
HISTORY を参照。
plenary.nvim
の PlenaryBustedDirectory
を用いています。