🐜

denopsでvimのcodic拡張機能を書いた

2021/03/25に公開

denopsでvimのcodic拡張機能を書いた

denopsでcodicの拡張機能を書きました。
https://github.com/Omochice/dps-codic-vim

背景

普段プログラムを書いているときに雑にgetとかを雑に使いがちなので、ちゃんと命名をしたいと思ってCodicを使ってます。
(Google翻訳とかだとプログラムでよく使う単語と若干違うのがでるイメージがある)
いちいちブラウザを開いて調べるのは手間なのでエディタからAPIを叩けるようにしました。

あとはvimの拡張機能がdenoで掛けるようになったらしいので勉強がてら書きたかったのもあります。

作っている最中に調べたら既に先人が作っていらっしゃった。

https://github.com/koron/codic-vim

多分こっちのほうが高性能です。

実装

https://github.com/vim-denops/denops.vim
を使っています。

APIからの結果を表示するだけなので80行程度で書けました。

import { start } from "https://deno.land/x/denops_std@v0.4/mod.ts";

async function fetchAPI(text: string[], TOKEN: string) {
  if (text.length >= 4) {
    throw new Error(`The number of texts must be 3 or less.`);
  }
  const BASEURL = "https://api.codic.jp/v1/engine/translate.json";
  const res = await fetch(BASEURL, {
    headers: new Headers({
      "Authorization": `Bearer ${TOKEN}`,
    }),
    body: new URLSearchParams({
      "text": text.join("\n"),
    }),
    method: "POST",
  });
  if (res.status !== 200) {
    console.log(res.status);
  }
  const json = res.json();
  const data = await json;
  return data;
}

start(async (vim) => {
  vim.register({
    async codic(args: unknown): Promise<void> {
      if (typeof args !== "string") {
        throw new Error(`'args' must be a string`);
      }
      const TOKEN = Deno.env.get("CODIC_TOKEN");
      // console.log(`your token is ${TOKEN}`);
      if (TOKEN === undefined) {
        console.error("No token set");
        throw new Error(`No token set`);
      }

      const targets = args.split(/\s+/);

      const data = await fetchAPI(targets, TOKEN);

      const contents: string[] = [];
      for (const datum of data) {
        contents.push(`${datum["text"]} -> ${datum["translated_text"]} `);
        for (const word of datum["words"]) {
          let content = `  - ${word["text"]}: `;
          if (word["successful"]) {
            for (const candidate of word["candidates"]) {
              content += `${candidate["text"]}, `;
            }
          } else {
            content += "null";
          }
          contents.push(content);
        }
        contents.push("");
      }
      await vim.cmd("botright new");

      await vim.call(
        "setline",
        1,
        contents,
      );
      await vim.execute(`
        setlocal bufhidden=wipe buftype=nofile
        setlocal nobackup noswapfile
        setlocal nomodified nomodifiable
      `);
    },
  });

  await vim.execute(`
    command! -nargs=? -bar Codic call denops#request('${vim.name}', 'codic', [<q-args>])
  `);
});

APIを叩くためにアクセストークンを取得する必要があるので、Deno.env.get()$CODIC_TOKENを取得しています。
(環境変数の取得はvim.eval("$CODIC_TOKEN")でもできるようです。)
vim内の変数でlet g:codic_accesstokenとかでもいいかと思いましたがvimrcをdotfilesで管理していたりすると面倒なので環境変数からの読み込みにしました。

:Codic <text>で与えられたtext/\s+/で分割して\nで結合してAPIを叩いています。
API側の制限で1度に変換できるのは3つまでです。

今後実装する予定の機能

  • 選択範囲の変換
     - 選択範囲の置換をするのでcamelCaseだったりsnake_caseを選べるようにする
    vimでの矩形選択がコマンドへは自動で行選択になるようなので断念

参考にさせていただいた記事

追記情報

2021/04/05

  • コードを修正
  • 実装予定の経過を追加
  • リンクをカード形式に変更

Discussion