ラベル Vim の投稿を表示しています。 すべての投稿を表示
ラベル Vim の投稿を表示しています。 すべての投稿を表示

2025年8月25日月曜日

Vim のマクロで気持ち良くなった話 - Java フィールドから SQL の SELECT 定義を作成編

Java Bean でエンティティ的なものを作って、そのフィールド値を(ほぼ)全部 SELECT で撮ってきたいと思う場面は多いと思います。

ざっくりやってみたら意外とうまくいったので記録。

User.java

public class User {
  /**
   * 氏名
   */
  private String name;
  /**
   * グループ ID
   */
  private Integer groupId;
  /**
   * Role ID
   */
  private Long roleId;
  /**
   * 住所
   */
  private String address;
  /**
   * 電話番号
   */
  private String phoneNumber;
}

最初のコメントの始まりにカーソルを合わせ、以下キーストロークをうつと、フィールド名だけを抽出できる。

これを q に保存して @q で全部フィールド名だけを抽出する。

VjjdvWWhx$r,j

すると、こうなる。

public class User {
  name,
  groupId,
  roleId,
  address,
  phoneNumber,
}

後は lower snake case にすればいいので、対象のフィールドの行で以下キーストロークを実行。

^ve:s/\C\([A-Z]\)/_\1/g<Enter>veuj

これも q に記録して、対象行で @q していく。

すると以下のようになる。

public class User {
  name,
  group_id,
  role_Id,
  address,
  phone_number,
}

後は先頭と末尾を SELECT 文ににしてケツカンマを削除。

select
  name,
  group_id,
  role_Id,
  address,
  phone_number
from
  "user";

OK, 以上。

以下、似たようなことをやっている動画です。

2025年8月22日金曜日

Vim のマクロで気持ち良くなった話 - Java のフィールド定義編

エクセルのインタフェース仕様書とかに、こんな形で入力や出力のパラメーター情報が書かれていたりする。

これをいちいち手作業で Java のフィールドとして記載していくのは骨が折れるため、 Vim のマクロで何とかした。

論理名 物理名 データ型 …(略)
氏名 name String
住所 address String
電話番号 phoneNumber String

論理名からデータ型までの列をコピーして Vim に張り付けると、以下のようなテキストになる。

氏名  name    String
住所  address String
電話番号    phoneNumber String

氏名の行の先頭にカーソルを置き、以下のように入力していく。

i/**<Enter><BS> * <ESC>Ea<Enter>*/<Enter>private <ESC>Elvx<ESC>vexbPa <ESC>A;<ESC>j0

すると、氏名の行が以下のようになる。

/**
 * 氏名
 */
private String name;

このストロークを qq で記録しておき、 @q を 2 回実行すれば他の行も以下のようになる。

/**
 * 住所
 */
private String address;
/**
 * 電話番号
 */
private String phoneNumber;

うーん、便利。

以下、似たようなことをやっている動画です。

2025年4月7日月曜日

devcontainer.vim で Claude Code を使う

AI コーディングというやつをやってみたかったのです。

前提

  • OS: Windows 11 Pro 23H2 ビルド 22631.5039
  • Docker Desktop: Version 4.37.1 (178610)
  • WSL2 の Ubuntu 24.04 から WSL Integration で Docker Desktop を利用
  • Java プロジェクトを作って、 Hello,World! するのが目標
  • Claude Code のアカウントを作って $5 入金済み

devcontainer 用のファイル作成

.devcontainer/devcontainer.json

  • Maven の Java プロジェクトを作りたいので、 devcontainer の features を利用してインストール
  • Claude Code に Node が必要なので、 devcontainer の features を利用してインストール
{
  "name": "app",
  "image": "mcr.microsoft.com/devcontainers/base",
  "features": {
    "ghcr.io/devcontainers/features/node:1": {},
    "ghcr.io/devcontainers/features/java:1": {
      "version": "21",
      "installGradle": "false",
      "installMaven": "true"
    }
  }
}

.devcontainer/devcontainer.vim.json

  • devcontainer.vim config -g > .devcontainer/devcontainer.vim.json で生成したものそのまま使う
{
  "remoteEnv": {
    "EDITOR": "~/squashfs-root/AppRun",
    "PAGER": "sed -r 's/\\x1B\\[[0-9;]*[mGKH]//g' | ~/squashfs-root/AppRun -R -",
    "LESSCHARSET": "utf-8",
    "SHELL": "bash",
    "TERM": "xterm-256color",
    "HISTCONTROL": "erasedups",
    // If use WSLG
    // "DISPLAY": "${localEnv:DISPLAY}",
    // "WAYLAND_DISPLAY": "${localEnv:WAYLAND_DISPLAY}",
    // "XDG_RUNTIME_DIR": "${localEnv:XDG_RUNTIME_DIR}",
    // "PULSE_SERVER": "${localEnv:PULSE_SERVER}",
  },
  // devcontainer/cli はまだ forwardPorts に対応していないため、
  // 必要に応じて forwardPorts の定義を appPort に転記する。
  // ※ コンテナ側で Listen する際は、 `127.0.0.1` **ではなく** `0.0.0.0` で Listen すること。
  // "appPort": [
  // ],
  // Linux で実行する場合には、 runArgs をコメントアウトし、コンテナからホストへの接続ができるようにしてください
  //"runArgs": [
  //  "--add-host=host.docker.internal:host-gateway"
  //],
  "mounts": [
    {
      "type": "bind",
      "source": "${localEnv:HOME}/.vim",
      "target": "/home/vscode/.vim"
    },
    {
      "type": "bind",
      "source": "${localEnv:HOME}/.gitconfig",
      "target": "/home/vscode/.gitconfig"
    },
    {
      "type": "bind",
      "source": "${localEnv:HOME}/.ssh",
      "target": "/home/vscode/.ssh"
    },
    // If use host's bashrc
    //{
    //  "type": "bind",
    //  "source": "${localEnv:HOME}/.bashrc",
    //  "target": "/home/vscode/.bashrc"
    //},
    // If use WSLG
    //{
    //  "type": "bind",
    //  "source": "/tmp/.X11-unix",
    //  "target": "/tmp/.X11-unix"
    //},
    //{
    //  "type": "bind",
    //  "source": "/mnt/wslg",
    //  "target": "/mnt/wslg"
    //},
  ],
  // denops など、別の実行環境が必要な場合や、
  // 後乗せで追加したいツールがある場合には以下の対象行をコメントアウトするか
  // https://containers.dev/features から必要な feature を探して追加してください。
  //"features": {
  //  "ghcr.io/devcontainers-community/features/deno:1": {}
  //  "ghcr.io/devcontainers/features/node:1": {}
  //  "ghcr.io/devcontainers/features/python:1": {}
  //  "ghcr.io/devcontainers/features/ruby:1": {}
  //  "ghcr.io/devcontainers-extra/features/fzf:1": {}
  //  "ghcr.io/jungaretti/features/ripgrep:1": {}
  //  "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {},
  //  "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  //}
}

開発環境の起動

devcontainer.vim start .

Claude Code のインストール・初期設定

インストール

Vim でターミナルを開き、以下コマンドを実行。

npm install -g @anthropic-ai/claude-code

初期設定

Vim でターミナルを開き、以下コマンドを実行。

cloude
  1. 表示のカラースタイルを聞かれるので答える(僕は Light text にした)
  2. ログイン処理 2.1 Enter 押下で表示される URL にアクセスし、ログインを行う 2.2 ログイン完了後に表示されるコードをターミナルにペーストし、 Enter
  3. Yes, proceed まで Enter を押し続ける
  4. プロンプト入力画面が表示される

あとはここにやって欲しいことを入力していくだけ。

実装

プロジェクトの作成

claude へ次の命令を入力する。

Maven の Java プロジェクトを作り、 Hello, World! を表示したい。 Java のバージョンは 21 とすること。

今回は、以下のような処理を行ってくれた。

  1. mkdir -p src/main/java/com/example

  2. pom.xml の作成

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example</groupId>
        <artifactId>hello-world</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>21</maven.compiler.source>
            <maven.compiler.target>21</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.3.0</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>com.example.App</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
  3. App.java の作成

    package com.example;
    
    public class App {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }
  4. コンパイル(mvn compile)

  5. 実行(mvn exec:java -Dexec.mainClass="com.example.App")

  6. 完了報告(Maven プロジェクトが正常に作成され、「Hello, World!」が表示されました。Java 21 を使用する Maven プロジェクトの基本構造を作成しました。)

良い感じ。

devcontainer.vim 特有のことが無かった気がするけれど、 Claude Code が使えたのでヨシ!

以上。

参考資料

2025年3月26日水曜日

Vim のマクロを使って気持ち良くなった話 - 表のデータを TS の enum にする

こんなデータから、こんなデータを作りたい

PDF に以下のような表がありました。

項目1 項目2
1
2
× 3

実際は行が 200 行くらいあります。

これを、以下のような TypeScript の enum にしたいのです。

enum Type {
= 1;
= 2;
= 3;
}

どうやったか?

まず、 PDF の表から文字列をコピペすると、以下のようなテキストデータになりました。



1


2

×
3

これを、前述の enum の形式にして、 200@q で気持ちよくなりたいわけです。

処理する順番としては以下のようにしました。

  1. 「項目2」 を消す
  2. 「項目1」の行末尾に = を追加
  3. 「項目1」と「値」 の行を結合
  4. 「3.」で結合した末尾に ; を追加
  5. 次の行の先頭にカーソルを配置

こうしてできた文字列を enum 内にコピペしてフォーマッタをかければ enum 定義の完成です。

ではやってみましょう。

<ここにカーソルがある>松

1


2

×
3

という状態から始め、 jddk で「項目2」の行を削除します。(1.)

<ここにカーソルがある>松
1


2

×
3

つづいて A = <Esc> で「項目1」の末尾に = を追加します。(2.)

すると以下の状態になりますになります。

松 = <ここにカーソルがある>
1


2

×
3

J で行を結合します。(3.)

松 = <ここにカーソルがある>1


2

×
3

A;<Esc> で末尾に ; を追加します。(4.)

松 = 1;<ここにカーソルがある>


2

×
3

マクロの連続実行ができるように、j^ で次の行の先頭にカーソルを持っていきます。(5.)

松 = 1;
<ここにカーソルがある>竹

2

×
3

この操作を記録して、 200@q とかすれば、他の項目も全て enum の形式になります。やったね。

2025年3月19日水曜日

Vim のマクロを使って気持ち良くなった話 - モックの JSON データ作成・編集編

モックデータの新規作成

こんなデータを作りたい

ホストにぶら下がっているエッジが大量にあり、そのエッジのステータスを取得する API がある。 その API のモックデータを作りたい。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 120 個くらい続く

どうしたか?

何個かデータを追加していくと、キー操作のパターンが見えてきました。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
<ここにカーソルがある>{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},

上記状態で、qqVjjjjyjjjjpjj<C-a>j<C-a>kkkq としたあと、 117@q と打って気持ちよくなりました。 (実際は何個かやって感覚をつかんでからなので、 114@q くらいだった気がする…)

モックデータの修正

こんなデータを作りたい、既にデータはある

先ほど作ったデータが、実は間違いでした…。 本当は「電球60個に人感センサ60個」なのでした。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 60 個続く
{
    "type", "人感センサ",
    "number", 61,
    "name", "人感センサ1",
},
{
    "type", "人感センサ",
    "number", 62,
    "name", "人感センサ2",
},
{
    "type", "人感センサ",
    "number", 63,
    "name", "人感センサ3",
},
... これが 60 個続く

どうしたか?

このデータだけ見ると、「人感センサについてさっきと同じことすればいいじゃん」と思うでしょう。その通りです。

ただ、考えるのが面倒でこのデータには入れていませんが、既に使われているモックデータのため、「type, name 以外のパラメーターを変更したくない」という制約があったのです。

なんでそんな状況になったか覚えていませんが、そんな状況だったのです。

という事で、制約を守った編集ができるような手順を、マクロ含みで考えました。

まずは、61 個目以降のtype, name の数値部分以外を人感センサに一括置換します。

そうすると、以下のようなデータになります。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",

},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 60 個続く
{
    "type", "人感センサ",
    "number", 61,
    "name", "人感センサ61",
},
{
    "type", "人感センサ",
    "number", 62,
    "name", "人感センサ62",
},
{
    "type", "人感センサ",
    "number", 63,
    "name", "人感センサ63",
},
... これが 60 個続く

後は簡単ですね。

以下の位置にカーソルを移動し、 qq60<C-x>jjjjj^q59@q で完了です。

{
    "type", "電球",
    "number", 1,
    "name", "電球1",
},
{
    "type", "電球",
    "number", 2,
    "name", "電球2",
},
{
    "type", "電球",
    "number", 3,
    "name", "電球3",
},
... これが 60 個続く
{
    "type", "人感センサ",
    "number", 61,
<ここにカーソルがある>    "name", "人感センサ61",
},
{
    "type", "人感センサ",
    "number", 62,
    "name", "人感センサ62",
},
{
    "type", "人感センサ",
    "number", 63,
    "name", "人感センサ63",
},
... これが 60 個続く

これで気持ちよくなれました。

以上です。

2025年2月28日金曜日

Vim でカーソル下の文字コード取得と文字コードでの入力を行う

使いどころはパッと思いつかないけど、過去に何度かお世話になったので備忘録として記す。

カーソル下の文字コード取得

ga コマンドで取得できる。

例えば、 にカーソルを合わせて ga を押すと、以下のように情報が表示される。

<→ > 8594, Hex 2192, Oct 20622, Digr ->

文字コードでの入力

インサートモード中に <C-v> を押すことで、文字コードによる入力ができる。

例えば、前述の を入力したい場合には i<C-v>u2192 と入力する。

以上。

参考資料

2025年1月24日金曜日

ddt.vim を試す

Vim 上で動くターミナルに興味があるので、 denops の環境構築から試していく。

前提

今回使った devcontainer.json:
{
  "name": "ddt.vim study",
  "image": "ubuntu:24.04",
  "features": {
    "ghcr.io/devcontainers-community/features/deno:1": {}
  }
}

必要パッケージのインストール

プラグインインストール簡単化のために、 git が必要なので、インストールする。

apt update
apt install -y git

denops のインストール

Vim のパッケージ機能と git submodule を組み合わせてプラグインのインストールを行う。

なので今回は git submodulepack/denops/start/denops に配置する。

~/.vim に移動して、git リポジトリを初期化・サブモジュールの追加を行う。

cd ~
mkdir .vim
cd .vim
git init
git branch -m main
git submodule add https://github.com/vim-denops/denops.vim.git pack/denops/start/denops

ddt.vim のインストール

同様に `git submodule でインストールする。

git submodule add https://github.com/Shougo/ddt.vim.git pack/b/start/ddt.vim

ddt.vim の ui プラグインをインストール

git submodule add https://github.com/Shougo/ddt-ui-terminal.git pack/b/start/ddt-ui-terminal
git submodule add https://github.com/Shougo/ddt-ui-shell.git pack/b/start/ddt-ui-shell

設定

vimrc を作成し、プラグインの読み込みなど、最低限の設定を行う。

shougo-s-github/vim/rc/ddt.vim - Shougo/shougo-s-github を参考に、 deno の設定も追加。

~/ddt.vimrc:

packadd denops
packadd ddt.vim
packadd ddt-ui-terminal
packadd ddt-ui-shell

let g:denops#server#deno_args = [
    \   '-q',
    \   '-A',
    \ ]
let g:denops#server#deno_args += ['--unstable-ffi']

call ddt#custom#patch_global(#{
      \   uiParams: #{
      \     shell: #{
      \       nvimServer: '~/.cache/nvim/server.pipe',
      \       prompt: '=\\\>',
      \       promptPattern: '\w*=\\\> \?',
      \     },
      \     terminal: #{
      \       nvimServer: '~/.cache/nvim/server.pipe',
      \       command: ['bash'],
      \       promptPattern: has('win32') ? '\f\+>' : '\w*% \?',
      \     },
      \   },
      \ })

vimrc の作成が終わったら Vim を再起動し、以下コマンドで設定を読み込ませる。

:source ~/ddt.vimrc

ddt-ui-terminal の起動

こちらも shougo-s-github/vim/rc/ddt.vim - Shougo/shougo-s-github を参考に terminal ui を起動。

:call ddt#start(#{ name: t:->get('ddt_ui_terminal_last_name', 'terminal-' .. win_getid()), ui: 'terminal', })

Vim の :terminal が起動し、いつもと同じように操作できる。

ddt-ui-shell の起動

おなじく shougo-s-github/vim/rc/ddt.vim - Shougo/shougo-s-github を参考に shell ui を起動。

:call ddt#start(#{name: t:->get('ddt_ui_shell_last_name', 'shell-' .. win_getid()), ui: 'shell', })

空のバッファが表示されるが、一度エンターキーを押下すると、(前述の設定だと)以下のプロンプトが表示される。

/workspaces/TIL/vim/ddt
=\\\> 

ここからは癖強なので細かく説明していく。

  1. ここで、 uname -a を入力し、次の状態に持っていく
/workspaces/TIL/vim/ddt
=\\\> uname -a
  1. :call ddt#ui#do_action('executeLine') を実行する
  2. エンターキーを押下すると、以下のように uname -a の結果が表示される
/workspaces/TIL/vim/ddt
=\\\> uname -a
Linux 84223c761d6e 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
/workspaces/TIL/vim/ddt
=\\\>

このように、コマンドの実行すら関数を呼び出さないと行けないので、使い勝手の良いシェルにするには自分でマッピング定義をする必要がある。

ddt-ui-shell の設定

以下のようなマッピングを行うと、「プロンプトの行でエンターを押すと、記載されたコマンドの実行と結果表示」ができるようになる。

""" {{{ for ddt-ui-shell
augroup ddt-shell
    autocmd!
    autocmd FileType ddt-shell nnoremap <buffer> <CR> <Cmd>call ddt#ui#do_action('executeLine')<CR>
    autocmd FileType ddt-shell inoremap <buffer> <CR> <Cmd>call ddt#ui#do_action('executeLine')<CR>
augroup END
""" }}} for ddt-ui-shell

あとは ddt や ddt-ui-shell 等のヘルプを観ながら自分の好きなようにマッピングを追加していけばよい。

以上。

参考資料

2024年12月16日月曜日

Vim 本体に evalfunc (Vim script 関数) を追加する

この記事は Vim 駅伝 の 2024/12/16 の記事です。 前回の記事は yuys13 さんによる、 2024/12/13 の「ソフトウェア技術者とコミュニティ活動~vim-jp radioに出演しました~」という記事でした。

次回は 2024/12/18 に投稿される予定です。

この記事はなに?

少し前に Vim script 関数を追加する Pull Request を出したので、その流れを忘れないように記録するための記事です。

VimConf 2024 の Kato さんのセッションとかぶってしまっていますが、実装の一例として見ていただくのがいいかと思います。 セッションの方がより深掘りされているので、視聴がおすすめです。

今回は、足し算をする関数を追加してみる。

前提

  • Vim のビルド環境が整った状態からスタート

手順概要

  1. 関数の実体を実装
  2. 関数のエントリーポイントを追加
  3. ドキュメントを追加
    1. 関数の説明を追加
    2. タグを追加
    3. 関数リストに追加
  4. 関数のテストを実装

実装

関数の実体を実装

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,

各定義は以下の通り。

  1. 関数名
  2. 最小引数数
  3. 最大引数数
  4. メソッドとして利用できる引数の位置
  5. 引数の組み合わせ
  6. 戻り値の型
  7. 実際に呼び出すエントリーポイント

ドキュメントを追加

関数の説明を追加

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 で、このファイル内のテストのみを実行できる。

参考資料

2024年12月10日火曜日

Vim の組み込み関数の結果をバッファに出力する

この記事は Vim advent calendar 2024(Adventar) の10日目の記事です。

この記事はなに?

getcellpixels() の追加を行った際に、 テストでバッファに関数の結果を出力する必要があったので、やり方を調べた。

結論

:redi @"
:echo getcellpixels()
:redi END
""p

ここでは、 :redi @" で、コマンドの出力を " レジスタへリダイレクト開始の設定をしている。

その後、 :echo getcellpixels()getcellpixels() 関数の結果を出力しているが、 先のリダイレクト設定により、その結果が " レジスタに格納される。

:redi END でリダイレクト設定を解除し、 ""p" レジスタの内容をバッファにペーストする。

こうすることで、空のバッファにペーストした際には、バッファの 3 行目にコマンドの結果が出力される。

3 行目である理由は謎。

以上。

参考資料

2024年12月6日金曜日

keyinput-delayer.vim で Vim での編集力を鍛える

この記事は Vim advent calendar 2024(Adventar) の4日目の記事です。

この記事はなに?

mikoto2000/keyinput-delayer.vim: 別名「Vimmer 養成ギプス」。 を作ったので、その宣伝です。

人はついつい「知っている方法・慣れた方法」で物事を進めてしまう。

それは Vim における編集でも同じことで、ついつい h, j, k, l での移動をしてしまいがちです。

それはなぜかというと、「キー入力のコストがとても低いから」であると私は考えました。

キー入力のコストがもっと高ければ、丁寧丁寧丁寧に操作を吟味してキー入力をすることでしょう。

例えば、帯域の狭い回線の SSH で、エコーバックがなかなか帰ってこない時、いつもより丁寧に操作をしたことはありませんか?

そんな環境を Vim 上で再現するのが mikoto2000/keyinput-delayer.vim, 別名「Vimmer 養成ギプス」です。

使い方

let g:keyinput_delayer_delay_time = "1000m" のようにディレイ時間を設定し、 keyinput_delayer#ToggleKeyInputDelay() を呼び出すことで、ディレイのあり・なしを切り替えます。

例えばディレイを 1 秒にしたとき、 10 行下に移動するために必要な時間は以下のようになります。

  • j x 10 : 10 秒
  • 10j : 3 秒

これを見て分かる通り、キーインプットのコストが非常に高くなるため、 「タイプ数を減らして編集を実現する」という意識が高くなります。

皆さんも keyinput-delayer.vim を導入して Vim のキーストロークゴルフ思考を身に着けていきましょう!

類似プラグイン

同じ目的のプラグインが存在することを vim-jp で教えていただきました。

こちらは、連続の 1 マス移動でカーソルが全く動かなくなるので、 よりストイックに鍛えたい方に向いているのではないでしょうか?

以上、 keyinput-delayer.vim の宣伝でした。

2024年12月3日火曜日

Nix で Vim をスタティックリンクビルドする。ついでにクロスコンパイルもする

この記事はなに?

mikoto2000/devcontainer.vim の ARM 対応で、 ARM 版のスタティックリンクな Vim が必要になった。

vim-jp にて「Nix ならコマンド一発でできるよ」と教えてもらったのでやってみた。

前提

  • Docker: Docker version 27.3.1, build ce12230
  • 使用イメージ: nixos/nix

Nix のリポジトリアップデート

nix-channel --update

スタティックリンクビルド

nix-build '<nixpkgs>' --cores 20 -A pkgsStatic.vim
  • --cores: make でいうところの -j オプション

aarch64 のクロスコンパイル&スタティックリンクビルド

nix-build '<nixpkgs>' --cores 20 -A pkgsCross.aarch64-multiplatform.pkgsStatic.vim

ビルドされた Vim の場所

find で探しましょう。

bash-5.2# find /nix -name vim
/nix/store/jx5d1dp77cwkarvalh1l8zvfp2ziqzlw-vim-static-aarch64-unknown-linux-musl-9.1.0787/share/vim
/nix/store/jx5d1dp77cwkarvalh1l8zvfp2ziqzlw-vim-static-aarch64-unknown-linux-musl-9.1.0787/bin/vim
/nix/store/7wkl9dji0dq6v7nmdjp1d72wd5pydqpb-vim-static-x86_64-unknown-linux-musl-9.1.0787/share/vim
/nix/store/7wkl9dji0dq6v7nmdjp1d72wd5pydqpb-vim-static-x86_64-unknown-linux-musl-9.1.0787/bin/vim
/nix/store/gnzqq5zg8r55apxa5avlb5yp0ix8qdwk-nixpkgs/nixpkgs/pkgs/applications/editors/vim
/nix/store/gnzqq5zg8r55apxa5avlb5yp0ix8qdwk-nixpkgs/nixpkgs/pkgs/test/vim
/nix/store/yzqnkb2mfzphmhv3248pw0pqh6f1mn6y-7sprarsdfz9qcd7859phvr9nvhi14mri-source/pkgs/applications/editors/vim
/nix/store/yzqnkb2mfzphmhv3248pw0pqh6f1mn6y-7sprarsdfz9qcd7859phvr9nvhi14mri-source/pkgs/test/vim

bin 下のが目的のバイナリですね。

share の方にはランタイムが入っています。

パッケージング

Vim は、ランタイムと一緒に配布しないと上手く動かないので、パッケージングを行う。 さらに、ランタイムの場所はビルド時に決め打ちされるため、 VIM 環境変数を上書きして Vim を起動するシェルスクリプトを用意し、それ経由で実行してもらうようにする。 (今回の場合は AppRun というシェルスクリプトを用意)

# aarch64 のパッケージング
cp -a /nix/store/jx5d1dp77cwkarvalh1l8zvfp2ziqzlw-vim-static-aarch64-unknown-linux-musl-9.1.0787 vim-9.1.0787-aarch64
cd vim-9.1.0787-aarch64
cat << "EOF" > ./AppRun
#!/bin/sh
CURRENT_DIR="$(dirname "$(realpath "$0")")"
export VIM="${CURRENT_DIR}/share/vim/"
exec "${CURRENT_DIR}/bin/vim" "$@"
EOF
chmod a+x ./AppRun
cd ..
tar zcfv ./vim-9.1.0787-aarch64.tar.gz vim-9.1.0787-aarch64

# aarch64 のパッケージング
cp -a /nix/store/7wkl9dji0dq6v7nmdjp1d72wd5pydqpb-vim-static-x86_64-unknown-linux-musl-9.1.0787 vim-9.1.0787-x86_64
cd vim-9.1.0787-x86_64
cat << "EOF" > ./AppRun
#!/bin/sh
CURRENT_DIR="$(dirname "$(realpath "$0")")"
export VIM="${CURRENT_DIR}/share/vim/"
exec "${CURRENT_DIR}/bin/vim" "$@"
EOF
chmod a+x ./AppRun
cd ..
tar zcfv ./vim-9.1.0787-x86_64.tar.gz ./vim-9.1.0787-x86_64

これで、「ダウンロードした tar.gz を展開して、その中の AppRun を実行すれば vim が起動する」という感じになります。

devcontainer.vim で必要なので、このスタティックリンクな Vim を mikoto2000/vim-static: Distributing a static link binary for vim/vim. で配布予定です。

以上。

参考資料

2024年11月25日月曜日

VimConf 2024 で登壇してきました

この記事はなに?

VimConf 2024 の参加記です。

参加レポートも、「登壇者にしか書けないもの」を求められている空気を感じたので、自分語りをやっていきます。

プロポーザルを出したきっかけ

「タイミングが良かった」に尽きる。

devcontainer.vim - VSCode Dev Container の Vim 版。 を 3 月ごろから作り始めて、9 割満足できるくらい出来上がったところで VimConf 2024 の CfP が公開された。

「devcontainer.vim 自体はただのコマンドラインツールで、作った周辺ツールもただのコマンドラインツール なので Vim の話はほとんどで無いけどいいのかな?」と少し悩んだが、 「まー、僕の考えた最強の Vim 開発環境だし」と思い結局エイヤで出してしまった。

実際に出したプロポーザル

Vim Conf 2024 CfP のやつ
---
title: Vim Conf 2024 CfP のやつ
author: mikoto2000
date: 2024/7/13
---

mikoto2000@gmail.com



mikoto2000



https://raw.githubusercontent.com/mikoto2000/TIL/master/svg/icon/myicon.svg



Creating the Vim Version of VSCode Dev Container Extension: Why and How



Vim is great. Containers are great too. But combining them is not as easy as VSCode.
We have created a few tools to make it easier to combine them for development.
I will talk about why I made the tool, its overview, how it works, and the challenges I faced.


# 自身について

## 概要

仕事と趣味でプログラミングをやっているプログラマー。
一生を Getting Started の実施で過ごす人。
最近は [Tauri](https://tauri.app/) のベータ版でアプリを作りながら issue や Pull Request を出す生活をしています。

## Vim 活

「自身の使うプラグインは、できるだけ自身がつくったプラグインで済ませる」という挑戦をしている
 LSP や補完系のものはさすがにあきらめたが、その他小粒なツールは自作している

- ファイルエクスプローラー
- バッファーセレクター
- ファイルファインダー
- スニペットジャンプ


# 講演の概要

コンテナ内で Vim を使った開発をするためのツールを作成しました。
(「VSCode Dev container 拡張機能の Vim 版」と放言しています)
そのツールを何故作ったのか?・概要・仕組み・苦労話を話します。
https://github.com/mikoto2000/devcontainer.vim

Vim と何かをインテグレーションする際の一例として、誰かに刺されば良いかなぁと思っています。


# 話すこと

・何を作ったのか?
(仕組みの比較のため)VSCode Dev Container 拡張機能について。
作ったもの(devcontainer.vim)の仕組み説明

・何故作ったのか?
なんでコンテナ内で Vim を使いたいのか?

・解決したい課題と解決方法
初期の方法とその課題
課題を解決するために取った方法
(ツールの作成と、インテグレーション)
どんな方法でどんな課題を解決したのかの説明。

・(時間があれば)作る際の苦労話をいくつか

- NeoVim移行を考えてあきらめた話
- Vim に Pull Request を送った話

# 話さないこと

以下 2 点以外の Vim の機能全て

- channel による TCP 通信
- コマンドライン引数 `-S` による Vim Script の実効


20, 15



Japanese



English


Yes

書き始めたのは 7/13 だったらしい。実際出したのはもっと後のはず…

採択されてから

CfP を出した時点で章立てがほぼ決まっていたので、それに合わせてがりがりとパワーポイントを書いていった。 図を盛り盛りに盛り込んでインクで印をつけながら説明していくスタイル。

結局発表時間が足りなかったので、「時間があったら話すこと」は省略した。

Slack のログを見ると、スライド自体は 10/21 に提出、英語表現や図の表現に関してレビュー・指摘を受けて 10/23 に再提出したようだ。

スピーカーノートまで含めた最終版は 11/6 に提出。

その後は時間を計りながらしゃべりの練習(合計 10 回くらい?)をして、当日を迎えた。

ちょっと練習足らんかったな…。緊張しててもカンペなしでしゃべれるくらいまでやらないと。

当日の様子

登壇前

死ぬほど緊張していた。

登壇

死ぬほど緊張していましたが、スピーカーノートで一命をとりとめました。カンペ大事。

スピーカーノート通りにしゃべれなかった箇所があったり、改善点はあれど、あの時点でのベストは尽くした…

登壇後

魂が抜けた…

席に戻る途中で TJ 氏に「Good session」(うろ覚え)と声をかけてもらえてとてもうれしかった。

懇親会

端っこで人見知りしていたが、何人かの方が話しかけてくれたり、 ツールの仕組みや Dev container に興味を持って質問してくれたりして嬉しかった。

登壇で話せなかったこと

NeoVim に移行しようとしてあきらめた

  • NeoVim は、VSCode と同じく、 UI と実処理をクライアント/サーバーに分けて起動できる
  • クリップボード連携にとても都合の良い構成なので、この機会に NeoVim に移行し、クライアント/サーバー構成を利用しようとした
  • しかし、利用している自作プラグインが、 job_start を多用しており NeoVim で動かなかった
  • せっかくなら Vim/NeoVim 両対応しようと思って修正していたら、別案の clipboard-data-receiver の仕組みの方が先にできてしまった…

Vim に Pull Request を出した話

  • devcontainers が公開している Docker イメージでは、プロンプトに が使われている
  • ターミナル版 Vim では、 ambiwidth の設定にかかわらず が半角分の領域で描画される
  • が描画された行では、リフレッシュが上手く行われず画面にゴミが残りがちになる
  • これが我慢ならずに Vim に改善の Pull Request を出した

なんでここまでしたの?

VSCode Dev Container 拡張機能の Vim 版という事なんですが、

  1. 「VSCode で Dev container が使えるのがうらやましい → コンテナに Vim 突っ込もう」から始まり、
  2. 「コンテナ内で快適に開発したい」となり、
  3. 「周りが VSCode な中で、どうにかこっそり Vim で Dev container したい」になり、
  4. そんなこんなで「Vim で Dev container を利用した開発ができる、かつ、既存 VSCode ユーザーの邪魔にならないようにする」

という仕組みが出来上がった。

devcontainer って便利なの?

この辺りにメリットを感じる人にはフィットするかも。

  • 「開発環境 as Code」ができる
    • 開発環境の構成が devcontainer.json を見ればわかるし、 devcontainer が自動で解釈してくれるので Docker さえインストールしていれば、開発環境の再現が容易になる
  • docker compose ファイルにも対応しているので、複数サーバーが必要な開発環境も構築できる
  • VSCode Dev 拡張機能で利用されている資産を利用できる

devcontainer.vim って便利なの?

devcontainer のメリットに以下をプラスした感じ。 この辺りにメリットを感じる人にはフィットするかも。

  • いつものイメージにそのまま Vim を突っ込めるので、 Dockerfile の作成が不要
  • LS って大体ランタイムと同じ言語で実装されているので、 何も考えずにコンテナ上に LS をインストールできることが多い (私は、コンテナを立ち上げるたびに vim-lsp-settings で LS をインストールしている)

※ Vim から出れないので、 Vim の :sh:terminal を使いこなせる必要がある

最後に

意外と話したいけど話せなかったことがいっぱいあったな…

devcontainer.vim - VSCode Dev Container の Vim 版。、説明できなかったこまごました機能もあるので、一度 README を読んでみてください!

何か質問があれば @mikoto2000 でもこのブログのコメントでもなんでもよいので聞いていただければと思います。

参考資料