この記事は Vim 駅伝 の 2024/12/16 の記事です。 前回の記事は yuys13 さんによる、 2024/12/13 の「ソフトウェア技術者とコミュニティ活動~vim-jp radioに出演しました~」という記事でした。
次回は 2024/12/18 に投稿される予定です。
この記事はなに?
少し前に Vim script 関数を追加する Pull Request を出したので、その流れを忘れないように記録するための記事です。
VimConf 2024 の Kato さんのセッションとかぶってしまっていますが、実装の一例として見ていただくのがいいかと思います。 セッションの方がより深掘りされているので、視聴がおすすめです。
- 動画 - Hacking Vim script - YouTube
- スライド - vimconf2024-kato - 04-kat0h-hacking_vim_script.pdf
- セッション紹介 - Hacking Vim script - VimConf 2024
今回は、足し算をする関数を追加してみる。
前提
- Vim のビルド環境が整った状態からスタート
- 今回は Docker イメージ
mikoto2000/vim-devkit
を利用する
- 今回は Docker イメージ
手順概要
- 関数の実体を実装
- 関数のエントリーポイントを追加
- ドキュメントを追加
- 関数の説明を追加
- タグを追加
- 関数リストに追加
- 関数のテストを実装
実装
関数の実体を実装
evalfunc.c
:
一番下に、実装する。
diff --git a/src/evalfunc.c b/src/evalfunc.c
index b2905da2a..99527029e 100644--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -12125,3 +12125,9 @@ f_xor(typval_T *argvars, typval_T *rettv)
}-
#endif // FEAT_EVAL+
+ int
+add_num(int x, int y)
+{
+ return x + y;
+}
関数のエントリーポイントを追加
引数パターンの確認
今回追加するのは、ふたつの引数がそれぞれ「数値」、「数値」の引数を持つ関数。
Lists of functions that check the argument types of a builtin function.
と
コメントされている行から下に、引数のパターンごとに変数がつくられている。
今回追加したいパターンの引数の組み合わせは arg2_number[]
となる。
エントリーポイント関数の追加
evalfunc.c
:
今回は、さきほど実装した「関数の実体」の直後にエントリーポイントを実装し、プロトタイプ宣言も追加する。
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 99527029e..8fcdaaf60 100644--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -194,6 +194,7 @@ static void f_wildmenumode(typval_T *argvars, typval_T *rettv);
static void f_windowsversion(typval_T *argvars, typval_T *rettv);
static void f_wordcount(typval_T *argvars, typval_T *rettv);
static void f_xor(typval_T *argvars, typval_T *rettv);+static void f_add_num(typval_T *argvars, typval_T *rettv);
/*@@ -12131,3 +12131,26 @@ add_num(int x, int y)
{
return x + y;
}+
+/*
+ * "add_num(number, number)" function
+ */
+ static void
+f_add_num(typval_T *argvars, typval_T *rettv)
+{
+ // argvars[] の第一引数と第二引数の型チェック
+ if (in_vim9script()
+ && (check_for_number_arg(argvars, 0) == FAIL
+ || check_for_number_arg(argvars, 1) == FAIL))
+ return;
+
+ // argvars[] から第一引数と第二引数を取得
+ int x = tv_get_number_chk(&argvars[0], NULL);
+ int y = tv_get_number_chk(&argvars[1], NULL);
+
+ // 戻り値に計算結果を格納
+ rettv->vval.v_number = add_num(x, y);
+
+ return;
+}
+
エントリーポイント定義の追加
evalfunc.c
:
1758 行目くらいからあるエントリーポイントの定義に、今回実装したエントリーポイントの定義を追加する。
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 99527029e..d51b6ac1f 100644--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -1758,6 +1758,8 @@ static funcentry_T global_functions[] =
ret_float, f_acos},
{"add", 2, 2, FEARG_1, arg2_listblobmod_item,
ret_first_arg, f_add},+ {"add_num", 2, 2, 0, arg2_number,
+ ret_number, f_add_num},
{"and", 2, 2, FEARG_1, arg2_number,
ret_number, f_and}, {"append", 2, 2, FEARG_2, arg2_setline,
各定義は以下の通り。
- 関数名
- 最小引数数
- 最大引数数
- メソッドとして利用できる引数の位置
- 引数の組み合わせ
- 戻り値の型
- 実際に呼び出すエントリーポイント
ドキュメントを追加
関数の説明を追加
runtime/doc/builtin.txt
に関数のドキュメントを辞書順になるように追加する。
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index d0f0c7b03..7370091a0 100644--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -26,6 +26,7 @@ USAGE RESULT DESCRIPTION ~
abs({expr}) Float or Number absolute value of {expr}
acos({expr}) Float arc cosine of {expr}
add({object}, {item}) List/Blob append {item} to {object}+add_num({number}, {number}) Number add two number
and({expr}, {expr}) Number bitwise AND
append({lnum}, {text}) Number append {text} below line {lnum}
appendbufline({buf}, {lnum}, {text})@@ -833,6 +834,12 @@ add({object}, {expr}) *add()*
|Blob|
+add_num({number}, {number}) *add_num()*
+ Add two {number}.
+
+ Return type: |Number|
+
+
and({expr}, {expr}) *and()*
Bitwise AND on the two arguments. The arguments are converted to a number. A List, Dict or Float argument causes an error.
タグを追加
runtime/doc/tags
に関数のドキュメントのタグを辞書順になるように追加する。
diff --git a/runtime/doc/tags b/runtime/doc/tags
index f33988020..f92a144df 100644--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -5995,6 +5995,7 @@ ada-extra-plugins ft_ada.txt /*ada-extra-plugins*
ada-reference ft_ada.txt /*ada-reference*
ada.vim ft_ada.txt /*ada.vim*
add() builtin.txt /*add()*+add_num() builtin.txt /*add_num()*
add-filetype-plugin usr_05.txt /*add-filetype-plugin*
add-global-plugin usr_05.txt /*add-global-plugin* add-local-help usr_05.txt /*add-local-help*
関数リストに追加
runtime/doc/usr_41.tx
に関数定義を辞書順になるように追加。
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 36907d249..29e6d2ffc 100644--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -808,6 +808,7 @@ List manipulation: *list-functions*
empty() check if List is empty
insert() insert an item somewhere in a List
add() append an item to a List+ add_num() add two number
extend() append a List to a List
extendnew() make a new List and append items remove() remove one or more items from a List
関数のテストを実装
今回は、ただの関数なので src/testdir/test_functions.vim
にテスト関数を追加する。
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 8b2518f2b..9167b2952 100644--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -4206,4 +4206,9 @@ func Test_getcellpixels_gui()
endif
endfunc
+func Test_add_num()
+ let result = add_num(1, 2)
+ call assert_equal(3, result)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
make test_functions
で、このファイル内のテストのみを実行できる。
0 件のコメント:
コメントを投稿