Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all 5718 articles
Browse latest View live

プログラミング初心者がまとめるvi①

$
0
0
$ vi sample.cpp

はじめに

はじめまして。学生バイト・初心者プログラマのT--Tです。

プログラミングのプの字も知らない初心者はまずエディタを起動するところから、ということで
今回はオライリー・ジャパンさんから出版されている『入門vi(第6版)』Vi(Vim)を勉強させてもらいました。
リンクはこちら

学んだ内容を自分の言葉で少しずつまとめていきます。お付き合いください。

入門viの構成

はじめに今回勉強した入門viを紹介しておこうと思います。以下のように段階的な章構成になっています。

  • 1章 テキストエディタvi
  • 2章 基本的な編集作業
  • 3章 素早く素早くジャンプする方法
  • 4章 viの中級コマンド
  • 5章 exエディタ
  • 6章 一括置換
  • 7章 viの高度な使い方
  • 8章 vim ー vi Improved

1章〜2章で基本的なコマンドの説明があり
3章〜4章で不自由を感じなくなるような操作コマンド(ページのスクロールや検索など)が説明され
5章〜8章でviないしvimがいかに強力なエディタであるかを説明されるという構成です。

章ごとの到達度の目安ですが、2章まで学んでようやくエディタとしての機能を果たすようになり、
4〜5章ほどで他のエディタと同じかそれ以上の生産性が生まれ、
それ以降を学んでようやくvim使ってますと周りに言えるかなというレベルになりました。あくまで初心者の個人的感想ですが。

ではviについて簡単にまとめていこうと思います。

viとは

viはUNIXに用意されているいくつかのエディタの中の一つです。
スクリーンエディタといってファイルの一部分を画面上に表示します。
それに対しexなどのラインエディタと呼ばれるエディタはファイルを行単位で読み出し編集します。

(viの場合)

#include "stdio.h"

int main(){
  std::cout << "Hello, world!" << std::endl;
  return 0;
}|
~
~
~
~
~

(exの場合)

Entering Ex mode. 
:1
#include "stdio.h"
:1s/"stdio.h"/<iostream>
#include <iostream>
:|

といってもviやexなどは、他のAtomVSCodeなどのようなエディタと違い、マウスを使ってカーソルを動かしたりCtrl+Pでペーストしたりすることはできません。

ではどうやってファイルを編集するかというと、全てコマンドを用いて編集します。
viを学ぶというのは、言ってしまえばこのコマンドを覚えるということにほぼ等しいと思います。
それぞれのコマンドをうまく覚えるためにモードという概念がよく用いられるのですが、つまるところ全てのコマンドを覚えてさえいればviの能力をフル活用することができます。そのためviを用いて編集するときにはチートシートと呼ばれるコマンド表がよく用いられるのです。

話は逸れますがこのコマンドによる編集というのがこれまたコンピュータを操っている感があって私のような初心者にはたまらなく楽しいのです。

ではそのコマンドの説明に入っていこうと思います。

基本的なコマンド

はじめにviコマンドの基本ルールだけ説明しておきます。

  • コマンドの大文字と小文字は区別します
  • 画面上にコマンドの文字は表示されないものが多いです
  • 基本的にEnterしなくて良いです
  • コマンドは大抵操作の頭文字です

ではまずはviの起動・終了やファイルの入力・保存に関する基本コマンドです。

viの起動
viがお使いのコンピュータにインストール済みならば、ターミナルやコマンドプロンプトで編集したいファイルのあるディレクトリまで移動した後以下のコマンドでviによる編集を開始できます。(このコマンドはEnterしてください)

vi filename

するとviが起動してvi特有の画面に切り替わります。

#include <iostream>
using namespace std;

int main(){
  hogehoge

~
~
~
~
"filename" 6L, 66C

カーソルはファイルの先頭にあると思います。
後で詳しく説明しますが、カーソルの移動もコマンドを用いて行うので矢印キーを押してもカーソルは移動しません(一部の環境を除く)。

基本的なコマンドだけ先に説明しておくと
移動コマンドは右 l 上 k 下 j 左 h です。
コマンド一回につき一文字分移動します。

テキストの入力
ではテキストを入力しましょう。

コマンドiを入力した後テキストを入力してみてください。
コマンドiを入力した後はdeleteキーやEnterキーも他のエディタと同じように機能します。

入力が完了したらEscキーで入力終了です。

このコマンドi入力後からEscキー入力までの間はテキストの入力を自由に行うことができるためインサートモード(入力モード)と呼びます。

それに対し、コマンドi入力前やEscキー入力後のコマンド入力待ちの状態をコマンドモードと呼びます。
基本的にコマンドはこのコマンドモードで入力します。

先に説明した移動コマンドは、このコマンドモードでしか使えないので
(もしインサートモードでも使えるとしたらviではhjklが入力できなくなってしまいます)
カーソルの移動をしたいときはEscキーでコマンドモードに抜けてから移動しましょう。

変更内容の保存・viの終了
Escキーでインサートモードを抜けただけの状態では、実はファイルの変更内容はまだ保存されていません。
バッファを呼ばれる一時的な領域に内容がキープされているだけなので、変更をファイルに反映したければこのバッファの内容をファイルに保存しなくてはなりません。

保存するコマンドは:wです。こちらはEnterしなくてはなりません。

以後Enterする必要があるコマンドは(Enter)と後ろにつけます。

#include <iostream>
using namespace std;

int main(){
  cout <<"Hello, world!" << endl;
  return 0;
}
~
~
~
~
:w

(Enter後)

#include <iostream>
using namespace std;

int main(){
  cout <<"Hello, world!" << endl;
  return 0;
}
~
~
~
~
"filename" 7L, 102C written

このようにwrittenと表示されたら上書き完了です。ちなみに横に表示されているLとCは総行数と総文字数です。
便利。

バッファの内容を破棄したい場合は:e!(Enter)と入力してください。コマンドeは本来別の効果をもつコマンドなのですが、!をつけて強制コマンドにすることでバッファの内容破棄に使えます。

保存が終了したらviを終了しましょう。コマンド:q(Enter)です。
バッファの保存や破棄をしていない状態で:qを入力するとエラーが出るので保存し忘れを防ぎます。ありがたい。

ちなみにこのコマンド:qに!をつけたコマンド:q!(Enter)を入力すると、バッファの内容の破棄とviの終了を同時に行うことができます。
同様にバッファの内容の保存とviの終了を同時に行うコマンドがあり、それがZZです。こちらはEnter不要です。

ここら辺でまとめ

長くなってしまったのでここら辺で一区切りとしようと思います。
最後に今回出てきたコマンドをまとめておくと

  • vi filename (vi起動)
  • l k j h (カーソル移動)
  • i (インサートモード開始)
  • Esc (インサートモード終了)
  • :w (バッファの保存)
  • :e! (バッファの破棄)
  • :q (viの終了)
  • :q! (バッファの破棄・viの終了)
  • ZZ (バッファの保存・viの終了)

となります。

終わりに

初めて技術記事を書いてみたのですがいかがだったでしょうか?
この続きの内容はまた後日書こうと思います。
次はエディタとして必要な機能(コピー&ペーストや効率の良い移動など)になると思います。
最後までお付き合い頂きありがとうございました。


アタシがプログラミングするときの環境はこんなカンジヨ!!

$
0
0

対象

「最近Web開発を始めたワヨ」なアンタ, もしくは 「お気に入りの設定を既にしているけど, 面白そうなのがあれば取り入れよっかな〜」とか言ってるアンタ達には是非見てって欲しいワ.

前提

アタシはRailsが大好きなの. 休日はよくRailsでWebアプリ作ったりしてるワ.
思いついたアイデアをパパッと形にできるところも好きな理由の一つヨ.
だから特別なIDEとかそれに伴ったプラグインとかの紹介はここではしないワ.(個人でネイティヴアプリを作ったりもしてるケドそれは別途記事にするかもしれないワヨ)

エディタ

Vim

アンタ達は普段何でコード書いてるかしら?
アタシは Vimを使っているワ.
なんてったって Vimはキーボード操作で完結できちゃうのヨ.
Vimの詳しい説明はここでは割愛するワ. 興味があったら調べてみてネ.
ただデフォルトの Vimだとちょっと寂しすぎるから, アタシは色んなプラグインをいれてるの.
プラグインマネージャーは vim-plugを使ってるワ.
導入については この記事がオススメヨ.
dotfilesGitHubにあげてるワヨ.

コンソール

次は コンソール ヨ.
アタシはターミナルアプリは iTerm2, シェルは bashを使ってるワ. Catalinaからはログインシェルが zshになるみたいネ.

bash

git

アタシは普段 gitはCUIで操作してるからその辺は少しカスタマイズしてるワ.
ちょこっと紹介するワネ.
💥インストールには Homebrewを使うから先にインストールしておいてネ💥

git-completion

gitコマンドを自動補完してくれるワ.

git-prompt

pwdの脇に作業中のブランチを表示してくれるワ.

tig

git logをGUIっぽく表示してくれるワ.

git-detroit

実はこれアタシが作ったの.
プロジェクトが大きくなってくるとローカルに実装済の作業ブランチが結構溜まってくるわよネ?(アタシだけ?)
git-detroitなら簡単に整理できるワ.
インストールは簡単ヨ.

$ brew tap dj-hirrot/git-detroit
$ brew install git-detroit

これを実行すると git-detroitがインストールされるワ.
整理したいプロジェクトまで移動して,

$ git-detroit
=> do you remove feature/xxxxx_xxxxx ? (y/n): y
Deleted branch feature/xxxxx_xxxxx (was xxxxxx).

で整理できるようになるワ.
詳しくは https://github.com/dj-hirrot/git-detroitをみて欲しいワ. (READMEの英訳PR待ってます!)

最後に

こんなカンジの環境で開発してるワ.
使えそうなのがあったら参考にして欲しいワ.
他にもオススメがあったら是非コメントしてネ.

popup_menu()のcallbackに追加で引数を渡したい

$
0
0

はじめに

popup_menu()のコールバックに(globalに置くような無茶な渡し方などをせずに)上手く追加で値を受け渡す方法を探していて、一つ答えが見つかったのでそのシェアになります。

自分が困ったケース

Vim scriptで選択肢のユーザーインターフェースといえばinputlist()があったと思いますが、最近の機能追加でpopup_menu()が追加され、ポップアップメニューの中からユーザーに選ばせるという選択も増えました。

↓↓popup_menu()の例
スクリーンショット 2019-11-28 1.57.48.png

自分のプラグイン(spelunker.vim)もこれまでinputlist()を使っていたのですが、今回新たにpopup_menu()も利用できるように修正を行おうと思ったのですが、下記のような問題があり、これまでのinputlist()をそのまま置き換えるような修正はできなさそうでした。

これまでのinputlist()の実装例

" ユーザーが選ぶfunction select(arg)letl:list =['111','222','333']letl:selected = inputlist(l:list)" このあとl:selectedを使ってなんかするendfunction

popup_menu()を使う場合の実装例

function select(arg)" ユーザーが選ぶとコールバックが呼ばれるletl:list =['111','222','333']call popup_menu(l:list, #{            \ callback:'callbackFunction',            \ pos:'topleft',            \ line:'cursor+1',            \col:'cursor'            \})endfunctionfunction calbackFunction(id, selected)" a:selectedを使ってなんかするendfunction

ポップアップメニュー選択後、コールバックが呼び出されるようになります。
こうなってくるとselect()の関数内で持っている変数で(a:argなど)、このあとの処理でも使いたい変数はどうやってcalbackFunction()に受け渡せばいいのか...などなど、これは設計にも影響してきそうです。

コールバックに追加で引数を渡す

こちらの記事のクロージャの項目の内容的なアプローチを取ってみます。
https://vim-jp.org/vim-users-jp/2010/08/13/Hack-167.html

" argをコールバックに渡したい!functions:select(arg)" 記事中のクロージャの項目の内容的なアプローチ" https://vim-jp.org/vim-users-jp/2010/08/13/Hack-167.htmlletl:callback ={'arg':a:arg}functionl:callback.funcall(id, selected) dict
        call Popup_callback(a:id,a:selected, self.arg)endfunctionletl:list =['111','222','333']call popup_menu(l:list, #{                \ callback:l:callback.funcall,                \ pos:'topleft',                \ line:'cursor+1',                \col:'cursor'                \})endfunctionfunction Popup_callback(id, selected,arg)" ここでもs:select()のarg(a:arg)を使える!endfunction

引数が上手く追加できましたね。
また、これは簡単にするとこうにもなります。

functions:select(arg)letl:callback ={'arg':a:arg}functionl:callback.funcall(id, selected) dict
        " callbackとしてやりたかった内容をここに移動します" self.argもa:id, a:selectedも使えますendfunctionletl:list =['111','222','333']call popup_menu(l:list, #{                \ callback:l:callback.funcall,                \ pos:'topleft',                \ line:'cursor+1',                \col:'cursor'                \})endfunction

これで一応、popup_menu()の呼び出し元のスコープにある変数の受け渡しができました🙌

vim-lspの定義ジャンプとvim本来のtagジャンプを共存させる

$
0
0

vim-lspの定義ジャンプがいい感じなので<C-]>キーを上書きして使っているのだが、vimのhelpを見る際などに<C-]>が動作しなくて不便なことがある。

方針としてはまず:LspDefinitionを実行してみて失敗したら本来のvimの定義ジャンプを呼び出すようなキーバインドを登録したい。

本質的にはvim-lspに限らず他のプラグインでも同様にできるはず。

nnoremap <expr><silent><C-]> execute(':LspDefinition')=~"not supported" ? "\<C-]>":"\<Nop>"

エラーメッセージをマッチさせるという、かなりアドホックなやり方だが現時点ではちゃんと動く。
vim-lspの仕様が変われば動かなくなるかもしれない。

CentOSのVimにMolokaiを導入する

$
0
0

要旨

VimのカラースキームにMolokaiを入れると、見た目が綺麗になり、作業が楽しくなります。

↓未導入 1
image.png

↓導入後 1
image.png

どうですか。この見た目。

Vimを起動するたびに恍惚とした表情で作業できそうです。

ぜひ導入しましょう。

導入

git clone

cd /tmp
git clone https://github.com/tomasr/molokai
mkdir -p ~/.vim/colors/
mv molokai/colors/molokai.vim ~/.vim/colors/

設定ファイル

~/.vimrc
" 下記のように変更、または追記
colorscheme molokai

個人的な好みで設定変更

コメント文字色の変更

Molokaiをそのまま使うと、コメントが黒背景に紛れてやや読み辛いので、変更しておきます。

~/.vim/colors/molokai.vim
" (略)
   "コメント色の変更
   "hi Comment         ctermfg=59
   hi Comment         ctermfg=241
" (略)

tmux設定ファイルの変更

tmuxで256色表示にしておきます。

こうしないと、せっかくMolokaiを導入しても、tmuxのペインの中で色が変わってくれません。

~/.tmux.conf
set-option -g default-terminal screen-256color
set -g terminal-overrides 'xterm:colors=256'   

それではごきげんよう。


  1. ソースコードはこちらのサンプルを使いました。 → https://www.php.net/manual/ja/language.oop5.basic.php#example-186 

日本語vimを自前ビルド

$
0
0

はじめに

vimのリポジトリ https://github.com/vimをそのままビルドしたら日本語化されなかったので、メモ。

知識

  • 正常に日本語化されているvimがある環境では share/vim/vim81/langディレクトリ内に ja/LC_MESSAGES/vim.moファイルがあるが、そうでない環境には存在しない。
  • このファイルを生成するには vim のビルド時に gettextパッケージに含まれる msgfmtコマンドが必要のようだ。
  • msgfmtコマンドがなくても、vimのビルドは問題なく通ってしまう。

手順

sudo aptitude install gettext
git clone git@github.com:vim/vim.git
cd vim
./configure --prefix=$HOME
make
make install

ついでに

日本語マニュアルも導入しておく。

cd ~/.vim
mkdir-p pack/vimdoc-ja/start
cd pack/vimdoc-ja/start
git clone git@github.com:vim-jp/vimdoc-ja.git

vimrcを複数PCで共有・同期する方法

$
0
0

やりたいこと

デスクトップとノートPCでvim設定ファイルを一緒にしたい
gitをpush、pullするのが面倒なので、1つを変更したら、自動で他のPCに反映させたい

前提

わからない単語があれば、ググってください
mac, linuxはpathを適宜読み替えてください

方法

  1. Dropboxや、Google DriveをすべてのPCにインストールする(今回は、Dropboxを使用)
  2. Dropboxの適切な場所に、適切な名前(vimの設定ファイルだとわかるもの)のファイルを作成し、そこに設定を書き込む(今回は、Dropbox直下に、vim_setttingsという名前のファイルを作成)
  3. コマンドプロンプトを管理者モードで開き、User直下(C:\Users\xxx)に移動し、mklink .vimrc Dropbox\vim_settingsとコマンドプロンプトで実行する(Dropbox\vim_settingsは、絶対パスでも良いです。自分が決めたファイルのパスに置き換えてください)

以上
Q.E.D.

vim覚書

$
0
0

現在のカーソル位置から行頭までを削除(インサートモード):ctrl+u


Vim の変数スコープについて簡単に調べた

$
0
0

はじめに

Vim Script を書いているときに、let s:hogeというような変数定義を書くことがあると思います。その時の変数の前置子につけるアルファベットの意味をいつも忘れてしまうので、まとめておこうと思います。

そもそも変数の前置子につけるアルファベットは何か

Vim のマニュアルを調べてみると、変数のスコープを指定するもののようでした。以下、マニュアルを引用します。

前置子の種類前置子スコープ
buffer-variableb:現在のバッファにローカル
window-variablew:現在のウィンドウにローカル
tabpage-variablet:現在のタブページにローカル
global-variableg:グローバル
local-variablel:関数にローカル
script-variables::sourceされたVim scriptにローカル
function-argumenta:関数の引数(関数内のみ)
vim-variablev:グローバル、Vimがあらかじめ定義

例えば変数のスコープをグローバルにした場合、他のプラグインからもアクセスできるため、他の変数との衝突は気にする必要がありそうです。

Vim Script 内でのみアクセスできる変数の場合は、スクリプトローカルを意味する s:をつければ良さそうです。

調べていて面白いなと思ったのは、バッファ、ウインドウ、タブページ内でローカルな変数を定義できることでした。他のバッファ、ウインドウ、タブに影響を与えないようにする変数も定義できるのは便利ですね。

おわりに

普段と違う文法については、意味を知ってから使うほうが楽しいと思うので、引き続き調べていこうと思います。

参考

ホームディレクトリ以外の.vimrcを使う

$
0
0

諸事情で一時期共有ユーザーアカウントを使う羽目になり、
自分の.vimrcを使えなくて大変困ったので、
将来の自分へ宛ててメモ

常識的に考えてユーザーアカウントは分けたほうがいいよ絶対。

よく言われる手順

ネットを調べると単に-uで.vimrcを読みこませる手順が多いが、
筆者の場合、~/.vim/フォルダもホームディレクトリ以外に置きたいので、これだと困る。

$ vim -u /filepath/dotfiles/.vimrc

なお、この記事では設定ファイルは/filepath/dotfiles/に入っている前提とする。
以下のような感じ。

  • /filepath/dotfiles/.vimrc
  • /filepath/dotfiles/.vim/

~/.vim/フォルダも別のパスに移す手順

  1. まず、.vimrc, .vim/を以下の通りにリネームする。
    • .vimrc -> vimrc
    • .vim/ -> vimfiles
  2. 以下のコマンドでvimを起動すると/filepath/dotfiles/.vim/以下もきちんと読み込んでくれる。
$ VIM=/filepath/dotfiles/ VIMRUNTIME=/usr/local/share/vim/vim81 vim

VIMRUNTIMEのところは環境に合わせて適宜変えてあげる必要がある。
筆者の場合、自分でビルドしたvimを使っているのでこのパスだけど、
ubuntuなら普通は/usr/share/vim/vimXXとかになると思う。
MAC, Windowsはわからない。

aliasを設定する

毎回打つのはだるいのでaliasを設定する。
~/.bashrcとかに書きたくなるけれど、ホームディレクトリのファイルを弄りたくないので、
これは端末開くたびに打つしか無いか。。。

$ alias myvim="VIM=/filepath/dotfiles/ VIMRUNTIME=/usr/local/share/vim/vim81 vim"

ようこそdotfilesの世界へ

$
0
0

はじめに

少し前から話題になっているが、日本の労働生産性はG7で最も低いらしい。
seisansei.png
日本生産性本部資料より https://www.jpc-net.jp/intl_comparison/intl_comparison_2018_press.pdf

日本は人口減少に突入していることもあって、「作業の効率化」や「自動化・省力化」をいうフレーズをあらゆる業種で聞くようになった。

ITエンジニアは、あらゆる職業の中でも最も効率化、自動化をして生産性を高められるといっても過言ではないだろう。プログラマの三大美徳(「怠惰」「短気」「傲慢」)にもあるように、同じことを何度もやらない、楽をするためにがんばるという生産性を意識した感性が重要視されているからだ。
生産性を高めることで、勉強する時間が作れたり、新しいことを経験したりするなどしてさらにスキルアップができ、さらに生産性が上がるという好循環を作り出すことができる。

この好循環を作り出すために必要な原動力、そうそれが dotfilesだ!

dotfilesとは?

dotfilesとは、ホームディレクトリに置いてあるドット(.)から始まる設定ファイル(.bashrcとか)を管理しているリポジトリのことである。シェルやエディタの設定からアプリケーションの設定まで幅白いものが置かれている。
dotfilesはGitなどでバージョン管理されており、GitHubで公開されていることが多い。(GitHub以前はオレの.bashrcを晒すぜ!などのブログタイトルでブログにそのまま貼り付けられている形式が多かった)

dotfilesを極めることで、どこで作業していても自分の環境を瞬時にサクっと作り出すことができ(ハッカーみたいでかっこいい)、いきなり快適な作業環境で、ストレスなく、生産性Maxの状態で開発をスタートできる。
まさにこれからの時代の働き方である。これからの働き方にはdotfilesが必要なのだ!

特におすすめな人

ここでどのような人がdotfilesを作るべきか具体的な対象を列挙してみよう。

  • いろんなサーバー上で開発する人
  • dockerとかの中で開発するのが好きな人
  • 仕事柄新しいPCで作業することが多い人
  • もっと効率的に作業できないかを考えている人
  • 自分の環境じゃなきゃ生産性ガタ落ちする人
  • パフォーマンス中毒な人
  • 数ヶ月に1度そろそろOS入れ替えよかっなーってなる人
  • すぐ新しいパソコンが欲しくなる人
  • あれ?前も設定したと思うあれどうやるんだっけ??ってなる人
  • 今日は働く気がしないけど仕事してるフリはしなくちゃいけなくて困ってる人
  • 育成ゲームが好きだったり、育てがいのあるペットが欲しい人
  • 次こそはミスしないぞ!と固く誓っている人
  • 怠惰を極めすぎていて同じこと2回以上したくない人
  • なんかハッカーっぽいおれおれ環境で周りにドヤ顔したい人
  • dotfilerに「そんな非生産的な環境でよく仕事できてるね」って煽られたくない人
  • 暇な人

まぁつまり全エンジニアが対象だ!!!

私の環境

あとの説明部分で環境による差異が発生する可能性が高いため、一応私の使っている環境を書いておく。

  • ArchLinux
  • Desktop(i3)
  • zsh, tmux
  • vim(neovim)

ちなみに私のdotfilesはこちら https://github.com/yutakatay/dotfiles
外部プラグインに依存していないシンプル版はこちら https://github.com/yutakatay/dotfiles-mini

今すぐにでも始められる最小dotfilesの作り方

ここからはdotfilesってのはわかったけど、具体的なはじめ方がわからないという人のために 今すぐにでも始められる簡単なやり方を書いていく。以下のとおり作業すれば、君も今日からdotfilerの仲間入りだ!

  1. GitHubにてdotfilesという名前のリポジトリを作成する(とりあえず、READMEだけでも作る)
  2. 自分のPCにdotfilesのリポジトリを git cloneしてくる(ここでは$HOME/dotfilesに置いたと想定する)
  3. とりあえず、使っているシェルの設定(~/.bashrc)をdotfiles以下にコピーする
  4. 元の~/.bashrcを退避させる mkdir backup && mv ~/.bashrc backup
  5. dotfilesの.bashrcにシンボリックリンクを貼る ln -s ~/dotfiles/.bashrc ~
  6. あとはdotfiles以下でコミットしてpushしたら出来上がり :tada:
  7. 同じように管理したいものdotfilesディレクトリにコピーしてシンボリックリンクを貼っていく

dotfilesの使い方

更新時

  1. 作業をしているとき、ふと「なんか生産性落ちてる気がする。。。効率を上げられないかな」と考える・感じる (たとえば、ターミナルでコマンド履歴から前のコマンドを上矢印で探してくるのめんどくさいなーとか)
  2. ネットで調べて効率が上がる設定を見つけ出す! (fzfを使い履歴を簡単に検索する方法がヒット。なるほど、履歴をファジーサーチできるようにしてそれをショートカットとして登録すればいいのか!)
  3. 該当の方法を設定ファイルに入力する (この場合だとシェルの設定、.bashrc, .zshrcを更新する)
  4. シンボリックリンクとなっているはずなので、gitが差分を検知しているはず
  5. git add, commit, pushを行いremoteに反映する

構築時

  1. GitHubからgit clone https://github.com/xxx/dotfiles.gitでdotfilesを持ってくる
  2. インストーラー(後述)を起動する
  3. はい、もう自分の環境が構築できている!

注意点

複数人でアカウントを共有している環境で作業している場合は他の人の許可を得た上でdotfilesを展開したほうがいい。(他の人がいきなり環境が変わってびっくりしてしまうため)

自分だけで使いたい場合は export HOME=/your/home/dirと自分だけのディレクトリにHOMEを変更してそこで使えば他の人への影響を防ぐことができる。(ただしシェルにログインするたび毎回 exportを実行する必要がある)

あまりガチガチに設定したくない、他の人とも共有したいという環境用に別のdotfilesを作っておくのもおすすめ。たとえば、誰もが使いたいようなgitのステータス情報やコマンドの実行時刻の情報をシェルのプロンプトに出したものを共有用のdotfilesにしておくなど。
https://github.com/yutakatay/dotfiles-mini

何を管理すればよい?

dotfilesでよく管理されているものの例

  • シェルの設定(~/.bashrc, ~/.zshrc, ~/.config/fish, etc)
  • エディタの設定(~/.vimrc, ~/.emacs.el, ~/.config/Code/User, etc)
  • ターミナルの設定(~/.config/alacritty, etc)
  • CLIツールの設定(~/.tmux.conf, ~/.gdbinit, etc)
  • アプリの設定(~/.i3, ~/.autokey, etc)
  • gitの設定(~/.gitignore_global, etc)

dotfilesで管理しにくいもの

  • .gitconfig(プライベートと会社でアカウントを分けている場合はUser情報が記述されているため共有しづらい)
  • 環境によって動的に内容が変わるもの(シェルスクリプトで自動生成するようにする)
  • シンボリックリンクを読み取ってくれないもの、ファイルで上書きしてしまうもの(~/.config/mimeapps.list etc)
  • プログラムやプラグインやアプリケーション(管理してもよいが機能更新に追従できなくなるため、パッケージマネージャーやプラグインマネージャーを使ってできるだけ最新版をダウンロードするようにしたほうがいい)

[注意]dotfilesで絶対に管理してはいけないもの

  • 認証情報が入っているディレクトリは 絶対に dotfilesにて管理しないこと
    • .ssh, .aws等

dotfilesのディレクトリレイアウトの例

私が実際にdotfilesでどのようなものを管理しているか抜粋して記載しておく。
※ 簡略化のために実際の私のdotfilesと変更している箇所がある

dotfiles
├── .bin/ # dotfilesのインストールスクリプトとよく使う自作スクリプトを格納する│   ├── gitconfig.sh*│   ├── make_conkyrc.sh*│   ├── arch-extra-setup.sh*# メインで使っているOSの追加のインストールスクリプト│   └── install.sh*# dotfilesのインストールスクリプト├── .bin.local/ # .localがつくものはその環境でしか使わないものを格納する│   └── .gitkeep
├── .config/
│   ├── alacritty/ # ターミナルの設定ファイル│   │   └── alacritty.yml
│   ├── Code/ # みんなが大好きなVSCodeの設定ファイル│   │   ├── _install.sh*# だけどインストールした直後に設定が作られるためdotfilesとしては管理しずらいのでインストールスクリプトを用意しておく│   │   └── User/
│   │       ├── keybindings.json
│   │       └── settings.json
│   ├── nvim -> ../.vim/
│   └── systemd/ # ユーザー用のsystemdの常駐設定も管理しておくと便利│       └── user/
│           └── i3-cycle-focus.service
├── .gdbinit
├── .github/
│   └── workflows/
│       └── test.yml
├── .gitignore
├── .gitignore_global
├── .i3/ # デスクトップ環境の設定ファイル│   ├── config
│   └── i3blocks.conf
├── .ideavimrc
├── LICENSE
├── README.md
├── .tmux/
│   ├── conf/ # 行数が増えた設定ファイルで外部ファイルを読み込めるものは設定ごとに分割したほうが見通しがよくなる│   │   ├── base.tmux*│   │   ├── bind.tmux*│   │   ├── color.tmux*│   │   └── plugin.tmux*│   └── log/
├── .tmux.conf
├── .vim/
│   ├── after/
│   │   ├── ftplugin/
│   │   └── .gitkeep
│   ├── backup/
│   ├── coc-settings.json
│   ├── ftdetect/
│   ├── ftplugin/
│   ├── info/
│   │   └── .gitkeep
│   ├── init.vim -> ../.vimrc
│   ├── rc/
│   │   ├── autocmd.vim
│   │   ├── base.nvim
│   │   ├── base.vim
│   │   ├── coloring.vim
│   │   ├── command.vim
│   │   ├── display.vim
│   │   ├── init.vim
│   │   ├── keyconfig.vim
│   │   ├── mappings.vim
│   │   ├── pluginconfig.vim
│   │   ├── pluginlist.vim
│   │   └── statusline.vim
│   ├── sessions/
│   │   └── .gitkeep
│   ├── snippets/
│   │   └── .gitkeep
│   ├── swap/ # 使用しているときに一時ファイルができるディレクトリは後述のgitignoreの設定で差分が発生しないように管理する│   │   └── .gitkeep
│   ├── template/
│   │   └── .gitkeep
│   └── undo/
│       └── .gitkeep
├── .vimrc
├── .xinitrc
├── .Xmodmap
├── .xprofile*├── .Xresources
├── .xsessionrc
├── .zfunc/
│   └── .gitkeep
├── .zsh/
│   ├── completion/
│   │   └── .gitkeep
│   ├── dircolors│   └── rc/
│       ├── alias.zsh
│       ├── base.zsh
│       ├── bindkey.zsh
│       ├── commandconfig.zsh
│       ├── completion.zsh
│       ├── function.zsh
│       ├── option.zsh
│       ├── pluginconfig/
│       ├── pluginlist.zsh
│       └── prompt.zsh
├── .zshenv
└── .zshrc
  • .vimrcや.zshrcなどは長くなったら(個人的には1500行超えるときつくなってくる)役割ごとでファイルを分けたほうが読みやすくなる
  • .gitconfig(ユーザー名を別途入れたい)、.conkyrc(PCによってコア数等を変更したい),.i3/config(インストールされているパッケージ構成によって動的に生成したい)などのものは、生成するためのシェルスクリプトを.bin/で管理する
  • 個別の環境で設定を変更したい場合に備えて設定ファイル内でローカルの設定ファイルがあれば読み込むようにしておく(.zshrc.local, .vimrc.local)

dotfiles用の.gitignoreの設定

エディタやシェルにプラグインを入れるなどし始めるとdotfiles管理下のディレクトリに勝手にファイルが作られることが多々ある。他のファイルが追加されても更新があるように見えないようにするため.gitignoreをホワイトリスト形式にする。

.gitignore
# 最初にすべての階層のファイルを無視します# 階層は必要なだけ追加する### all ignore ###
/*
/.*
/.*/*
/.*/*/*
/.*/*/*/*
/.*/*/*/*/*# .gitignoreは上から解釈されていくので# 管理対象のファイルをホワイトリストのように追記します### not ignore ###!/.zshrc
!/.zshenv
!/.zfunc/
/.zfunc/*# ディレクトリは管理したいけど中身はいらないときはこんな感じ!/.zsh/
!/.zsh/dircolors
!/.zsh/rc
!/.zsh/rc/*!/.zsh/rc/pluginconfig
!/.zsh/rc/pluginconfig/*!/.zsh/zkbd/
!/.zsh/zkbd/*!/.zsh/zfunc/
!/.zsh/zfunc/*!/.zsh/completion/
/.zsh/completion/*!/.virc
!/.vimrc
!/.vim/
!/.vim/*/
!/.vim/rc/*!/.vim/rc/myplugins/*!/.vim/rc/files/*!/.vim/ftplugin/*!/.vim/ftdetect/*!/.vim/template/*!/.vim/snippets/*!/.vim/after/*!/.vim/after/*/*!/.vim/after/*/*/*!/.vim/init.vim
!/.vim/coc-settings.json
!/.bin/
!/.bin/*!/.bin/*/*!/.bin/*/*/*!/.bin/*/*/*/*!/.bin.local
!/.tmux.conf
!/.tmux/
!/.tmux/conf/
!/.tmux/conf/*!/.tmux/conf/scripts/
!/.tmux/conf/scripts/*!/.tmux/log/
!/.tmux/powerline-rc/
!/.tmux/powerline-rc/*!/.gdbinit
!/.conkycolors/
!/.conkycolors/conkyrc
!/.i3/
!/.i3/*
/.i3/config
/.i3/config.local
!/.i3/scripts
!/.i3/scripts/*!/.i3/scripts/blocks
!/.i3/scripts/blocks/*!/.i3/systemd/
!/.i3/systemd/*!/.github
!/.github/*!/.github/*/
!/.github/*/*!/.ideavimrc
!/.Xmodmap
!/.Xresources
!/.xinitrc
!/.xprofile
!/.xsessionrc
!/.config
!/.config/*!/.config/*/*!/.config/*/*/*!/.gitignore_global

!/README.md
!/LICENSE
!.gitignore
!.gitkeep

シンプルなdotfilesインストーラーを作ってみよう

dotfilesを作ったが毎回手でシンボリックリンクを貼るのは面倒である。だからdotfiles用のインストーラーを作ったほうがいい。
インストーラーには、専用ツールやansibleを使う方法、Python,Rubyなどのスクリプト言語を使う方法などいろいろやり方は存在するが、今回は一番簡単なシェルスクリプトを使う方法を紹介しようと思う。

.bin/install.sh
#!/usr/bin/env bashset-ue

helpmsg(){command echo"Usage: $0 [--help | -h]" 0>&2
  command echo""}

link_to_homedir(){command echo"backup old dotfiles..."if[!-d"$HOME/.dotbackup"];then
    command echo"$HOME/.dotbackup not found. Auto Make it"command mkdir"$HOME/.dotbackup"fi

  local script_dir="$(cd"$(dirname"${BASH_SOURCE[0]}")"&&pwd)"local dotdir=$(readlink-f${script_dir}/..)if[["$HOME"!="$dotdir"]];then
    for f in$dotdir/.??*;do[[`basename$f`==".git"]]&&continue
      if[[-L"$HOME/`basename$f`"]];then
        command rm-f"$HOME/`basename$f`"fi
      if[[-e"$HOME/`basename$f`"]];then
        command mv"$HOME/`basename$f`""$HOME/.dotbackup"fi
      command ln-snf$f$HOMEdone
  else
    command echo"same install src dest"fi}while[$# -gt 0 ];do
  case${1}in--debug|-d)set-uex;;--help|-h)
      helpmsg
      exit 1
      ;;*);;esacshift
done

link_to_homedir
command echo-e"\e[1;36m Install completed!!!! \e[m"

dotfilesでもCIしてみよう

dotfilesだってCIで質を高めたい!インストールしているパッケージ名称が変わったり、インストールしたプラグインの依存しているプログラムに変更があったり、インストーラーを変更したらピュアな環境でインストールが失敗するようになったり、更新してもしなくても壊れることは多い。

今回はGitHub Actionsで複数のOS(Linux Distribution)へのインストールできるか確認をする。
他にもLintや各種プラグインのインストールチェックを設定しても効果的かと思われる。

dotfiles/.github/workflows/check.yml
name:CIon:[push]jobs:ubuntu:runs-on:ubuntu-latestcontainer:ubuntu:lateststeps:-uses:actions/checkout@v1-name:Install required packagesrun:apt-get update && apt-get install -y git sudo-name:Install dotfilesrun:.bin/install.sh installcentos:runs-on:ubuntu-latestcontainer:centos:lateststeps:-uses:actions/checkout@v1-name:Install required packagesrun:yum install -y git sudo-name:Install dotfilesrun:.bin/install.sh installalpine:runs-on:ubuntu-latestcontainer:alpine:lateststeps:-uses:actions/checkout@v1-name:Install required packagesrun:apk add git sudo bash-name:Install dotfilesrun:.bin/install.sh installarch:runs-on:ubuntu-latestcontainer:archlinux/base:lateststeps:-uses:actions/checkout@v1-name:Update packagesrun:pacman -Syu --noconfirm-name:Install required packagesrun:pacman -S --noconfirm git sudo-name:Install dotfilesrun:.bin/install.sh installlint:runs-on:ubuntu-latestcontainer:ubuntu:lateststeps:-uses:actions/checkout@v1-name:Update packagesrun:apt-get update-name:Install packages for install repositoryrun:apt-get install -y git sudo software-properties-common-name:Install required repositoryrun:apt-add-repository "deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe"-name:Install required packagesrun:apt-get update; apt-get install -y shellcheck-name:Execute shellcheckrun:test $(shellcheck  -f gcc ~/.zshrc ~/.zsh/rc/* | grep -v "SC1036\|SC1056\|SC1070\|SC1072\|SC1073\|SC1083\|SC2034\|SC2139\|SC2148\|SC1090\|SC1117\|SC2206\|SC1009\|SC2016\|SC2046\|SC2154" | tee -a /dev/stderr | wc -l) -le 1

dotfilesを成長させていくためには?

dotfilesは作って終わりではない。しっかり育てて(メンテナンスし続けて)こそ価値がある。
他の人の作業の様子や設定を見たり、新しいツールを試したりすることであなたのdotfilesはどんどん進化していくだろう。

一般的なdotfiles関連の情報収集ができるサイトは

あたりだろう。

ただもっとも大事なのは、日々の作業の中でもう少し改善できないかな?、未来で楽をするために今できることはないかなと考え続ける心だと思う。

さいごに

dotfilesは今すぐ始められます!
日々育てていくものなので、はやく始めたほうがそれだけ生産性が上がりますよ。

dotfilesと一緒に日々成長していきましょう!!!

はじめてのScala

$
0
0

scala-2.12.8

objectHello{defmain(args:Array[String]):Unit={valstr="Hello"println(str)}}

始まりは、書籍から。

Scalaに興味があり、書いてみようと逆引きレシピを中古本で購入した。送料込みで700円弱だった。書店で買うと3000円を超える値段である。それだと初学者としては手が届きにくい存在である。もともと、古本屋でスケーラブルプログラミングの第1版を入手にしていたのもあり、学ぶ意欲はあった。書いてみると逆引きレシピ本の通りには動かない、バージョンエラーだろうか。それでたどり着いたハローワールド。コンパイルする方法と、スクリプトとしてクラスを生成しない方法があることも理解した。

テキストエディタ選び

VimをもしScalaを書くテキストエディタで選んだとして、Deopleteを入力補完で選んだとする。DeopleteのwikiにScalaの入力補完リストがないことに気づいて、入力補完辞書ミニを使ったMinTabを作った。そしてDeopleteのWikiにも登録した。TabNineと合わせればそれなりに使えると思う。私はそうして、はじめてScalaでコーディングの練習をするようになった。まだまだ初学者だが、Scalaのトレイトに感心を持っている。

リンク先

MinTab

Deoplete.nvim

Scalaで今後

Webサイトをみているとmvnでscalaのライブラリは登録や実行ができそうだ。これぞという機能を作り、凝った作りであれば尚良いが、ライブラリ登録をしていきたいとも思う。他のスクリプトにはない魅力があるように思える。JVMで動作するのも魅力。難しいビルドもいらない。scalaenvを使えば割と簡単に違うバージョンが手に入る。そのときにライブラリとして初期段階に入れておくものを作りたい。

リンク先

maven

まだ始まったばかり。

初歩的な初歩。Scalaを始めたのは、もっと前だが取り組んだのは現在。まだ始まったばかりである。希望を語ったので来年のアドベントカレンダーには1年かけて作成したであろうライブラリの説明ができるようにしていきたい。

Windows+gVim+Poetryのpython開発環境構築

$
0
0

目標

Windows+gVim+Poetryで開発をするときに、ライブラリのコード補完やリンターが効くような環境を構築する。

gVimインストール

image.png

  • ダウンロードしたzipを展開し、gvim.exeがあるフォルダをPATHに追加する。

git for windowsのインストール

image.png

  • ダウンロードしたインストーラを実行する
  • オプション等は特に変更する必要なし。

vimプラグインのインストール

  • vimプラグインであるvim-lsp,ALEをインストールします。
  • powershellで下記コマンドを実行
    • 独自にパッケージ管理をしている方はそちらでインストールしてください
cd~New-Itemvimfiles/pack/mypackage/opt-ItemTypeDirectorycdvimfiles/pack/mypackage/optgitclonehttps://github.com/prabirshrestha/vim-lsp.gitgitclonehttps://github.com/prabirshrestha/async.vim.gitgitclonehttps://github.com/dense-analysis/ale.git

~/_vimrcに下記追記

letg:ale_completion_enabled=1packadd ale 
letg:ale_lint_on_save=1letg:ale_sign_column_always=1packadd async.vimpackaddvim-lsp
letg:lsp_diagnostics_enabled=0 " エラー表示はALEで行う
function!s:configure_lsp() abort
  setlocal omnifunc=lsp#complete
  nnoremap <buffer><C-]>:<C-u>LspDefinition<CR>
  nnoremap <buffer> gd :<C-u>LspDefinition<CR>
  nnoremap <buffer> gD :<C-u>LspReferences<CR>
  nnoremap <buffer> gs :<C-u>LspDocumentSymbol<CR>
  nnoremap <buffer> gS :<C-u>LspWorkspaceSymbol<CR>
  nnoremap <buffer> gQ :<C-u>LspDocumentFormat<CR>
  vnoremap <buffer> gQ :LspDocumentRangeFormat<CR>
  nnoremap <buffer> K :<C-u>LspHover<CR>
  nnoremap <buffer><F1>:<C-u>LspImplementation<CR>
  nnoremap <buffer><F2>:<C-u>LspRename<CR>endfunction"python用設定if executable('pyls')
    augroup lsp_pyls_enable
        autocmd!
        autocmd User lsp_setup call lsp#register_server({                    \'name':'pyls',                    \'cmd':{server_info->['pyls']},                    \'whitelist':['python'],                    \})
        autocmd FileType python calls:configure_lsp()
        autocmd FileType python imap <expr>.".\<C-X>\<C-O>"
    augroup endendif

pythonのインストール

  • pythonの公式サイトから使いたいバージョンのpythonインストーラをダウンロード
  • 今回はpython3.7.5をダウンロードします。
    image.png

  • ダウンロードしたインストーラを実行する。

image.png
image.png

Visual C++ 再配布パッケージのインストール

  • コード補完で使うpython-language-serverのインストールに必要
  • Visual C++ ダウンロードページからインストーラをダウンロード image.png
  • ダウンロードしたインストーラを実行する

image.png

poetryのインストール

  • powershellを起動し下記コマンドを実行する
pipinstall--user--upgradepippipinstallpoetry

Poetryプロジェクトの作成

  • プロジェクトを作成したいディレクトリで下記コマンドを実行
poetrynewtestprojectcdtestprojectpoetryadd--devpython-language-serverpoetryadd--devflake8

gVim起動

  • gVimを起動するときはpoetry shellに入ってから起動する
cdtestprojectpoetryshellgvimmain.py
  • ファイルを保存したときにpep8に準拠していなければエラー箇所が表示されます
  • 補完は<C-x><C-o>でできますが、.(ドット)を入力後は自動で補完がでます

エディタ遍歴とLSP

$
0
0

僕が初めてソースコードというものを触ったのは小学生か中学生の時でした。それから現在までプライベートでコードを書いたり、仕事をしたりという中でこ使用しているエディタは変化してきました。今まではあまり「これだ」というものに巡り会えていなかったのですが、Language Server Protocol (以下LSP) の出現により、最近ようやく手に馴染むエディタが定まりつつあります。そこでエディタ遍歴を振り返りつつLSPについても少し触れたいと思います。

初めてのコード

僕が初めてコードを書いたのは、初心者向けのパソコン雑誌の後ろの方に書かれていた"ホームページ"作成入門の記事でした。そこにはWindowsのメモ帳を開き、何やら英語っぽいものを記述して .htmという名前をつけて保存するということが書かれていました。ちなみにその時のソースコートはこんな感じだったと思います。今では見ることのないタグが並んでいますが、人によっては懐かしいのではないでしょうか。

<html><head><title>ようこそ!</title></head><bodybgcolor="pink"><center><fontsize="7">ようこそ!</font><br><br><marquee>ここは<fontcolor="darkgreen"><b>〇〇〇〇</b></font>のホームページです!
      </marquee><br><br><i>メニュー</i><tableborder="5"style="text-align: center;"><tr><td><ahref="#">日記</a></td><tdrowspan="4"><imgsrc=""alt="トップ画像"width="150px"height="150px"></td></tr><tr><td><ahref="#">イラスト</a></td></tr><tr><td><s>掲示板</s> (工事中)</td></tr><tr><td><ahref="#">リンク集</a></td></tr></table><br><br><hr><small>Copyright © 20xx ○○○○ All Rights Reserved.</small></center></body></html>

初めて書いたソースコードであったと同時に、僕が初めてテキストエディタに触れたときでした。ただのメモ帳に書かれた文字の羅列がホームページになったという体験が、プログラミングの仕事に就こうと思った最初のきっかけです。実際に動くコードはこちら。懐かしいですね。

空白期間

中学生くらいでソースコードを書くことを覚えましたが、高校に入ると部活が忙しく、大学でも文系に進学したのでほとんどソースコードを触ることがありませんでした。少しだけJavaScriptを書くのにDreamweaverは触りましたが、なにか書くときは主にメモ帳で書いていたのでシンタックスハイライトのあるエディタは逆に使いにくかった記憶があります。

IDE入門

新卒で入った会社の新人研修でJavaを学ぶときに初めてIDEであるEclipseを触りました。そこでIDEによる開発を知り、しばらくはIDEを使っていました。この頃はIDEが便利というよりはIDEが必須だと考えていました。

IDEでの開発

ゲーム会社でPythonを書くようになりますが、IDEに慣れていたためEclipseにPyDevプラグインを入れて開発していました。新しいMacを使い始めたのをきっかけに、ここ最近はPyCharmを使っていました。PythonのようなLLでもIDEを使っている理由は、最初の設定が楽だからです。とくにPyCharmのように言語に特化したIDEでは、自動補完やメソッド定義へのジャンプなど、特に設定せずに使えます。

Vim入門

開発はIDEですが、ちょっとしたテキストの編集はテキストエディタを使用していました。Windowsではメモ帳、MacではCotEditorを使っていました。それが一番慣れているキーバインドを使用できたからです。

そのうち少しだけVimも触るようになりました。はじめは git commitのときはデフォルトでVimが起動するので仕方なく使っていた程度でした。前職のCTOの下で働いているときに、彼がVimを便利そうに使っていて、その憧れもありMarkdownやYamlなどちょっとしたファイルの編集や、ちょっとPythonの修正するときにVimを使うようになりました。

途中、Emacsも経由しましたが常用エディタにするのは挫折しました。でもMacを使う上ではEmacsのキーバインドは練習してよかったと思ってます。

Vimでの開発

IDEでの開発は便利なのですが、ちょっとコードを書きたいだけなのにわざわざプロジェクトを作らなければいけなかったり、違う言語を書くときにそのためのIDEをインストールしたりというのが面倒になってきました。

ただ、Vimでの開発も、言語に合わせてプラグインを探してvimrcに変更を加えて…というのが必要でした。特にPythonを書くときには pythonbrewvirtualenvpyenvvenvなどで仮想環境を作ることが多いし、Python2とPython3の違いによって動かないプラグインがあったりと、一つ一つ解決するのも面倒でした。とくにWindowsも使い始めて、Windows Subsystem for Linux を使っていると特に設定が面倒でした。

迷走

Vimのキーバインドに慣れて、手に馴染んでいたのですが、Pythonを書くときに色々設定が面倒だったのでPyCharmにVimキーバインドのプラグインを入れて開発していました。そこから手に馴染み、設定の楽なエディタを探してAtomや Visual Studio Code なども触りましたが、結局 PyCharm + Vimプラグイン を使っていました。

Language Server Protocol との出会い

VimConf2018に参加したときに Language Server Protocol (以下LSP) という言葉を知りました。

Language Server Protocol とは

あまり詳しくはないので詳細についてはその他の記事に譲ります。IDEでは定義ジャンプ・自動補完・エラー分析…などの機能を提供していると思いますが、各言語に合わせてプラグインを作成するなど、IDE側が対応する必要があります。LSPは簡単に言うと、言語側がサーバーを起動し、共通のプロトコルを提供することでIDEと同様の機能を実現する仕組みです(…と理解しています)。LSPのない世界で完全に言語対応しようとすると、エディタやIDEの数✕言語の数の開発を行わなければなりません。しかし、エディタ側がLSPにさえ対応すれば、LSPに対応している言語をサポートできるようになります。

VimとLSPを使った開発

LSPを知った頃はあまり情報もなく、「こんなものもあるのか」くらいの感想でしたが、VimConf2019に参加した際に去年以上にLSPが盛り上がっていたので重い腰を上げてVimに導入しました。

導入したプラグイン

vimrcの設定

Python用の設定やマッピングは「Pythonの補完環境をjedi-vimからvim-lspに移行した話」を参考にしました。

Language Server 導入

LSPを利用するためにその言語用の Language Server をインストールします。現在対応しているのはこちら。
https://microsoft.github.io/language-server-protocol/implementors/servers/

Pythonの場合はpipでインストールできます

pip install python-language-server

これで pylsというサーバーが実行できるようになるので、vim-lspを使ってPythonによる開発をする準備ができました。なお、 venvpyenv-virtualenv、グローバルなPython環境で試してみましたが今の所それぞれの環境で問題なく動いています。

動き

lsp.gif

VimとLSPを使った開発の感想

補完や定義先の参照が早い

vim-lspや、その周辺のプラグインが優秀なので、補完や定義先の参照がとにかく早いです。言語特化のIDEと変わりない速さで動作します。IDEを立ち上げるような大きなプロジェクトじゃなくても、とくに設定もせずにこの速さでこれらの機能が使えることに感動すら覚えました。

vimrcがスッキリ

今までpyenv対応やPython2用・3用の設定、あるいは他の言語の設定などでvimrcが膨らんでいましたが、それらはvim-lspの設定を入れ、各言語用のサーバーを走らせれば良いのでvimrcは少しスッキリしました。

エンドゲームか?

今までのエディタをまとめてみると↓の用になりました。
この他にもPL/SQLやPowerbuilderというパッケージの言語? Excel VBA などの開発も行っていましたがもはや何を使っていたか覚えていません。

NamePlugin / (Remarks)LanguageOSType
1メモ帳HTML, CSS, JavaScriptWindowsText Editor
2DreamweaverHTML, CSS, JavaScriptWindowsText Editor
3EclipseJavaWindowsIDE
4NetBeansJavaWindowsIDE
5RDERubyWindowsIDE
6Flash Builder ?ActionScriptWindowsIDE ?
7Processing ?ProcessingWindowsIDE ?
8Arduino ?Arduino ?WindowsIDE ?
9EclipseADT PluginJava (Android)WindowsIDE
10EclipsePHPWindowsIDE
11EclipsePyDevPythonMac OS XIDE
12Aptana StudioPyDevPythonMac OS XIDE
13EclipseLua Development ToolsLuaMac OS XIDE
14Emacs(挫折)いろいろMac OS XText Editor
15LiteIDEGoMac OS XIDE
16RStudioRMac OS XIDE
17Gogland(Goland ではなく)GoMac OS XIDE
18Vimjedi-vim, vim-go などいろいろMac OS XText Editor
19Android StudioKotlin (Android)Mac OS XIDE
20PyCharmPythonMac OS X, Ubuntu, WindowsIDE
21Atom(迷走)PythonMac OS X, Ubuntu, WindowsText Editor
22Visual Studio Code(迷走)PythonMac OS X, Ubuntu, WindowsText Editor
23Vimvim-lspいろいろMac OS X, Ubuntu, WindowsText Editor

いろいろ使ってきた中でそれぞれにいいところや不満があったのですが、今の所VimとLSPの組み合わせではストレスになるような不満はありません。もう少し手に馴染むような設定はできると思いますが、もしかしたらエディタ探しは一旦エンドゲームと言えるのかもしれません。

余談

いろいろ書きましたが、僕はIDE推奨派で、特にプログラミング初学者にはIDEが良いと考えています。理由は設定が楽だし、マウスも使えるのでプログラミング以外のことに時間を使うことが無いためです。すごい人の中には簡素なエディタを使っている人もいますしIDEを使っている人もいます。高価なキーボードじゃないと開発できない人もいるしMacの薄いキーボードで十分な人もいます。道具にこだわるかこだわらないかはスキルと相関がないと思っています。自分の使いやすい道具を使えばいいので、VimでなければとかEmacsでなければ…というのは気にしなくてもいいと思います。もちろんかっこいいからVimを使うというのは良いと思います。

popup windowsで簡易ファイラーを作る

$
0
0

ども、ゴリラです。
今年もやってまいりましたVimアドベントカレンダーです。

今日はpopup windowを使ってファイル一覧をpopup windowで選択して開くプラグインを作ってみようと思います。
プラグイン作ってみたい方は、ぜひ読んでみてください。意外とプラグインは簡単に作れます。

はじめに

まずどんな機能を作るかを整理します。本記事は次の機能を実装することをゴールにします。

  1. 指定パスのファイル一覧をpopup windowに表示
  2. 選択したファイルを開く(分割、タブ、カレントバッファ)

ディレクトリ構成

プラグインのディレクトリ構成は以下にします。一般的にautoload配下にメインの処理関数を定義して、
pluginでメイン処理の関数を呼び出すコマンドを定義します。

autoloadに定義した関数は、コマンドで呼び出されるまでロードされないようになっています。
これは、Vimの起動時間に影響を与えないようにするためです。

popupfiles.vim/
├── autoload
│   └── popupfiles.vim
└── plugin
    └── popupfiles.vim

ディレクトリの置き場

プラグインマネージャーを使う方が多くいると思います、プラグイン開発を行うとき筆者はよくpackages機能を使用します。
packpath配下にstartディレクトリを作成してそこにディレクトリを置くことで、Vim起動時にプラグインを読み込んでくれます。

ちなみに、筆者の場合は次のようになっています。

/Users/skanehira/.vim/pack/plugins/start/popupfiles.vim

詳しく知りたい方は:h packagesでヘルプを引いてみてください。

ファイル一覧をpopup windowに表示

ファイル一覧を取得

まずはカレントディレクトリ配下のファイルを一覧の配列を返す関数を用意します。
コードはautoload/popupfiles.vimに記述します。

" パスのセパレーターを取得lets:sep= fnamemodify('.',':p')[-1:]function!s:get_files(path) abort
    " `expand()`はパスをフルパスに展開" 例えば`~/`は`/home/gorilla`に展開letp= expand(a:path)let entries =[]" `readdir`は指定したディレクトリ内の要素を配列で返すforfin readdir(p)" `.`から始まるディレクトリとファイルをスキップiff[0]is# '.'
            continue
        endiflet file_path =p.s:sep.fif isdirectory(file_path)let entries +=s:get_files(file_path)elseif file_path[0]is# '.'let file_path = file_path[2:]endifcall add(entries, file_path)endifendforreturn entries
endfunction

popup windowを作る

次にpopup windowを作る関数を定義します。popup windowを作る関数はいくつかありますが、今回はpopup_menuを使用します。popup_menuを使用することで要素の選択、操作を簡単に実装できます。

こちらも、コードはautoload/popupfiles.vimに記述します。

function! popupfiles#files() abort
    call popup_menu(s:get_files('.'),{})endfunction

ここで1つポイントです。popupfiles#files()という関数名はpluginで呼び出すためにautoloadのルールに従って命名しています。
autoloadの命名ルールはfilename#funcname()になっています。こうすることで、どのファイルのどの関数を呼び出すかVim側が判断できるようになるからです。

popup windowを呼び出す

メインの処理ができたので、次にpluginpopupfiles#files()を呼び出すコマンドを次のように定義します。

" プラグインを再度ロードしないようにガードif exists('g:loaded_popupfiles')finishendifletg:loaded_popupfiles=1" vi互換の設定を一旦退避lets:save_cpo=&cpo
set cpo&vim" コマンドの定義
command! PopupFiles call popupfiles#files()" 互換設定を戻すlet&cpo =s:save_cpo
unlet s:save_cpo

一度Vimを再起動するか、:source plugin/popupfiles.vim:source autoload/popupfiles.vimでファイルを読み込むかしてください。

適用後:PopupFilesコマンドを実行すると次のようにpopup windowにファイル一覧が表示されるはずです。

image.png

これでpopup windowにファイル一覧を表示させることができました。
ちなみに、popup_menuではデフォルトで次のキーが利用できます。

キー説明
j次の要素
k前の要素
enter/ space要素を選択
x / esc / ctrl-cキャンセル

では、次に選択したファイルを開くキーバインドを追加していきましょう。

選択したファイルを開く

popup_menuでは第1引数に要素、第2引数にオプションを渡すことができます。
もう一度コードを見てみましょう。第2引数は{}は空のオブジェクトになっています。
このオブジェクトにオプションを定義していきます。

function! popupfiles#files(path) abort
    call popup_menu(s:get_files(a:path),{})endfunction

popup windowにはfilterというオプションがあります。
このオプションではキー入力を受け付けて何かしらの処理を行う関数を指定することができます。

このフィルター関数、デフォルトではwinidkeyの2つの引数を受け取ります。
フィルター関数の定義と呼び出しは次のようになります。

function! popupfiles#files() abort
    call popup_menu(s:get_files('.'),{                \'filter':function('s:popup_files_filter')                \})endfunctionfunction!s:popup_files_filter(winid, key) abort
    " 入力キーに応じた処理" それ以外は通常のpopup_filter_menuに渡すreturn popup_filter_menu(a:winid,a:key)endfunction

ここで1つポイントですが、function()で関数への参照を取得して、filterオプションに渡す必要があります。

また、popup_filter_menuというVimの組み込み関数がありますが、これはfilterが何も指定されないときにデフォルトで使用されるフィルター関数になっています。この関数を使用することでjkといったキーバインドの操作が出来るようになります。

しかし、このまま実装しようとすると、
フィルター関数に選択したファイルが渡ってこないため、ファイルを特定できないという問題があります。
そこで、Vim scriptのPartialという仕組みを使用して必要な情報をフィルター関数の引数に追加します。
function()の第2引数に配列を渡すことで、その中身が関数の引数として先頭に順に追加されます。

function! popupfiles#files() abort
    letfiles=s:get_files('.')let ctx ={                \'idx':0,                \'files':files,                \}call popup_menu(files,{                \'filter':function('s:popup_files_filter',[ctx])                \})endfunctionfunction!s:popup_files_filter(ctx, winid, key) abort
    " 入力キーに応じた処理" それ以外は通常のpopup_filter_menuに渡すreturn popup_filter_menu(a:winid,a:key)endfunction

idxfilesから選択したファイルを取り出すために必要な配列番地の情報です。

これで必要な情報をフィルター関数内で扱うことができるので、あとはキー入力に応じてファイルを開く処理を実装すれば良いです。

今回は、次のキーバインドを実装することにします。

キー説明
enterカレントバッファに開く
ctrl-v水平分割で開く
ctrl-x垂直分割で開く
ctrl-tタブページで開く

実装したコードが次になります。

function!s:popup_files_filter(ctx, winid, key) abort
    " 入力キーに応じた処理ifa:keyis# 'j'ifa:ctx.idx < len(a:ctx.files)-1leta:ctx.idx =a:ctx.idx +1endifelseifa:keyis# 'k'ifa:ctx.idx >0leta:ctx.idx =a:ctx.idx -1endifelseifa:keyis# "\<cr>"returns:open_file(a:winid,'e',a:ctx.files[a:ctx.idx])elseifa:keyis# "\<c-v>"returns:open_file(a:winid,'vnew',a:ctx.files[a:ctx.idx])elseifa:keyis# "\<c-x>"returns:open_file(a:winid,'new',a:ctx.files[a:ctx.idx])elseifa:keyis# "\<c-t>"returns:open_file(a:winid,'tabnew',a:ctx.files[a:ctx.idx])endif" それ以外は通常のpopup_filter_menuに渡すreturn popup_filter_menu(a:winid,a:key)endfunctionfunction!s:open_file(winid, open,file) abort
    call popup_close(a:winid)
    execute a:opena:filereturn1endfunction

これで簡易ファイラーの実装は以上になります。

まとめ

いかがだったでしょうか?合計で100行くらいで簡易ファイラーを実装できるVim script、便利ですね。
これをきっかけにプラグインを作ってみようってなってくれたら嬉しいなと思っています。

本記事のソースコードはリポジトリに置きましたので、全体像を掴めていない方は覗いてみてください。

https://github.com/skanehira/popupfiles.vim

なお、本記事はVim scriptの基本構文について触れていないので、詳しく知りたい方は:h scriptでヘルプを参照してください。


VS codeのvim extensionにおけるWaiting for second key of chordについて

$
0
0

問題

vscodeのvim extensionを導入した際、インサートモードにもかかわらず、"["を押すとコマンドにWaiting for second key of chordというメッセージが出て,"["が出力されないという致命的な挙動が起きた。

対処法

単にkeyboardshortcutの項目から、extension.vimを検索。
"["が割り当てられたcommandをDefaultに切り替えればうまくいった。(なぜかSourceの欄がUserになっていた.)

コミュニティで調べても、同様の問題はよく起きてるようで、原因はよくわかっていない模様。
時間があったら調べたい。

vimのインサートモードをemacsぽく使う

$
0
0

はじめに

Vimが好きなのですが、mac標準の入力やブラウザの入力でEmacsコマンドが使えるということに気づき、最近はそちらを使うようにしています。
Vimのインサートモードでは、コマンドを使っていないので、Emacsライクに使おうかなーと思って設定してみました。

設定したVimrc

~/.vimrc
" use insert mode like emacs
inoremap <C-d><Del>
inoremap <C-h><BS>
inoremap <C-a><home>
inoremap <C-e><End>
inoremap <C-p><Up>
inoremap <C-n><Down>
inoremap <C-f><right>
inoremap <C-b><left>

できること

インサートモードでは基本的に移動しませんが、Emacsライクに移動・BackSpace・Deleteできるようになりました。
emacs使いではないため、最低限ですが、こちらに記載したコマンドの一部が使用できます。

操作コマンド
上移動C-p
下移動C-n
左移動C-b
右移動C-f
左削除C-h
右削除C-d
行頭移動C-a
行末移動C-e

Vimプラグイン"の"カテゴリまとめ

$
0
0

Vimのプラグインがたくさんあってなにがどうなっているかの整理できていない!という人向けによくあるプラグインのカテゴリをまとめてみました。プラグインを見つけた際にどこらへんに該当するかなーと判断の参考にしてもらえればと思います。

はじめに

  • 対象はVim初心者から中級者一歩手前くらいを想定しています。
  • プラグイン自体の説明はあまりするつもりはないので、リンクのGitHubのREADMEを読むなり使ってみるなりしてみてください。
  • 表の中の四角括弧[]は機能が重複しているプラグインです。同じようなプラグイン複数入れると良からぬことが起こるのでいずれか一つを試すのがよいと思います。
  • 個人的によく使う特におすすめのものは★を書いておきます。(ちなみにNeovim使いです)

プラグインのカテゴリ

プラグインマネージャー

まずはプラグインをいれるためのプラグイン(GitHubからダウンロードしたり、読み込んだりしてくれるもの)をいれます。

いろいろ種類はありますが、

  • vim-plug: 世界的に利用者が多くシンプル
  • dein.nvim: 日本人に使っている人が多く、高速

を選んでおくと無難かと思います。

標準機能拡張系

ここでは、Vimの標準機能を拡張するプラグインをまとめます。

カテゴリ(説明)代表的なプラグイン
移動改善 (Vimの醍醐味でもあるスッと移動する機能を拡張する)[vim-easymotion, vim-sneak], quick-scope★
選択 (文字選択をスマートに行う)vim-expand-region★, vim-multiple-cursors
検索vim-anzu★, vim-asterisk★
全体検索(今開いているファイル以外からも検索)vim-grepper★
Highlight (同じ単語を識別しやすくする)vim-quickhl★, [vim-illuminate, coc-highlight]
ヤンク(コピー)[yankround.vim, nvim-miniyank]
Undoundotree
ウインドウ (画面分割等のウィンドウを拡張する)winresizer, vim-choosewin
バッファ操作vim-bufonly, vim-bbye
コマンド (コマンドモードの拡張)suda.vim, CmdlineComplete, capture.vim★
編集支援 (括弧を入れ替えたり、単語をクオートでくくったりできる)[vim-sandwich★, vim-surround]
整形支援vim-easy-align★, vim-table-mode, vim-partedit
行結合、分割vim-jplus, splitjoin.vim
Difflinediff.vim★
Markvim-signature
Manual (Helpを引いたり)vim-ref★, vim-cheatsheet
Tag (タグジャンプ用のタグを管理する)vim-gutentags
Session (Vimのセッションを管理して以前の状態を復元したりする)vim-obsession
Quickfix (ビルド後などに使用する下の方に表示されるウィンドウ)vim-qf, quickr-preview.vim★
ファイラー (ファイル一覧からファイルを選択したりするやつ)[defx.nvim, fila.vim, vim-dirvish]

レイアウトカスタマイズ系

ここでは、主にVimの見た目をカスタマイズするプラグインをまとめます。

カテゴリ(説明)代表的なプラグイン
スタートメニュー (Vimを起動したときにメニューを表示できるようにする)vim-startify★
ColorScheme (Vimの色を変更する。いろいろなプラグインに対応している方が望ましい。そうしないとプラグインを追加するごとに色を調整する必要がでてくる)[gruvbox-material★, iceberg.vim]
Statusline (Vimの下に表示される情報を出すバー)lightline.vim★, vim-airline

機能追加系

ここでは、Vimに本来備わっている以外の機能を追加したプラグインをまとめます。

カテゴリ(説明)代表的なプラグイン
ファイル切り替えvim-buffergator, vim-xtabline★
メモ機能memolist.vim★
ファジーファインダー (曖昧検索でファイルやコマンドを検索する)[fzf.vim★, denite.nvim, ctrp.vim, vim-clap]
Git操作gina.vim, vim-fugitive, git-messenger.vim, committia.vim

コーディング支援系

主にプログラミングをする際の支援をしてくれるプラグインたちです。

カテゴリ(説明)代表的なプラグイン
自動補完[coc.nvim★, asyncomplete.vim, deoplete.nvim]
LSP[coc.nvim★, vim-lsp, LanguageClient-neovim]
ライティング支援nerdcommenter★, vim-better-whitespace, vim-autoformat
リーディング支援indentLine
コードジャンプ[vista.vim, tagbar], vim-altr★
タスクランナー[vim-test, vim-dispatch, asyncrun.vim, vim-quickrun]
Checker (最近はLSPにて代替が可能な場合が多いため使用しないこともある)ale
括弧可読支援rainbow_parentheses.vim, vim-matchup
括弧入力支援[lexima.vim, coc-pairs★, delimitMate]
スニペット (定型文入力支援)[coc-snippets★, neosnippet.vim, ultisnips], sonictemplate-vim
プロジェクト管理vim-rooter, vim-localvimrc

プログラミング言語別プラグイン

Vim(だいたいのエディタでもそうですが)では、各プログラミング言語ごとに専用のプラグインが存在し、言語固有の便利機能を提供していることが多いです。シンタックス(コードの色付け)の設定だけが必要ならvim-polyplotを入れれば大抵の言語は適切に色がついた状態で表示できます。

カテゴリ(説明)代表的なプラグイン
Markdown[previm, markdown-preview.nvim★]
言語ごとのシンタックス設定vim-polyglot(いろいろな言語のシンタックスがセットになっている。 ただしトラブルことも多い気がするので特定の言語しか書かない場合は個別にインストールするほうがよい)

さいごに

プラグインを選ぶ際のポイント

  • 継続的にメンテナンスされているか
    • Vim scriptは比較的簡単に書けるため最初作ったまま放置されるパターンも多い
      • プラグイン作者のGitHubのアクティビティなども参考にする
    • Vim本体の機能に追従していっているか
      • 機能追加でそのプラグイン自体が不要となるケースもある
      • 最近話題の機能を取り込めているか
        • 非同期実行ができるようになった(2016-)
        • LSPが出てきた(2016-)
        • ポップアップ(floating window)ができるようになった(2019)
  • そのプラグインよりメジャーなプラグインがないか調べてみる
    • あまりGitHubスターはあてにならない。古いプラグインのほうが星がたくさんついていることが多いため。
    • プラグインの移り変わりは激しいので(検索ワードとしては、xxx alternativeとかでよい)

プラグインを管理する際のポイント

  • プラグインを入れること自体は悪いことではないのでどんどん試して入れるとよいと思う。ただし、ただ入れて放置して管理していない状態にはならないように定期的に見直すこと。
  • たくさんいれるとプラグイン同士が干渉することがある(主にマッピングがかぶって動かなくなるなど)
    • トラブったときはプラグインを全部オフにして徐々に有効化してあたりをつけていくのがよい
  • たくさんいれすぎると起動が遅くなることがある

    デフォルトのvimよりもどのくらい遅くなっているか確認するワンライナー
    echo"scale=3; $(vi --startuptime /tmp/stime_mine.log -c'quit'> /dev/null &&tail-n 1 /tmp/stime_mine.log | cut-d' '-f1) / $(vi -u DEFAULTS --startuptime /tmp/stime_def.log -c'quit'> /dev/null &&tail-n 1 /tmp/stime_def.log | cut-d' '-f1)" | bc | xargs -iecho{}x slower your Vim than the default.
    

継続的に調査する

プラグインの移り変わりは激しいので定期的に情報を取得する必要があります。以下に私がよく使っているサイトのリンクを記載しておきます。

Vimの操作方法をMind Mapで書いている話(もしくは書いてた話)

$
0
0

こちらの記事は Vim2 Advent Calendar 2019 2日目の記事になります。

Vimのコマンド、最初はなかなか覚えられないものです。

と言う事で今回は私がVimを覚え始めた頃にMind Mapで作成したコマンドチーとシートを紹介します。

スクリーンショット 2019-12-01 22.20.25.png

PDF版は こちらからダウンロード出来ます。

途中まで作成して放置した関係で色々とコマンドが違ってる部分もありますが大体動くと思います。

現場からは以上です。

参考サイト

ReactでVimライクなInputを書いた

$
0
0

こんにちは

今年入社しました @tom-ockです。
昨日terraformの記事を上げてくれた @Sadalsuudさんと同じチームで開発しております。
担当ほどはっきりしたモノは今まだないですが、最近Reactが面白いです。

自己紹介はこれくらいにして早速本題に。

TL;DR

Reactでviっぽいinputコンポーネントを作りました(type="text"です)。

ScreenShot 8.jpg

実演

注意

  • VimiumなどはOffにしてください
  • 仕様上英語入力しか受け付けません
  • 入力にはFocusする必要があるためクリックしてから入力してください
  • 幅も有限なので、入力しすぎたらノーマルモードでdを押してください
  • スマホからは操作できません!ごめんなさい

See the Pen Vinput by Tomoki Oke (@litalico-tomokioke) on CodePen.

(あるいは:octocat:こちら(Github Pages))

実装概説

テキストエディタっぽいカーソルをどうしても表現したかったのですが、
inputを使用して実装する方法が思い浮かばなかったので今回は全てdivで実装し、
inputはhiddenでstateで渡すことにしました。

stateはreducerで管理しています。

state.内容
value入力文字列
cursorIndexカーソルポジション
modeモード

今回はノーマルモードとインサートモードの切り替え、文字列の入力、ノーマルモードでのいくつか移動を実装しました。
これらの3つの属性のstate + 入力されるキーから、次のstateが決定されるためそれをreducerに書きました。

:file_folder: useVi.ts

constnormalReducer:React.Reducer<State,Action>=(state,action)=>{switch(action.key){case"d":{return{...state,value:"",cursorIndex:getIndex.start(state)};}case"i":{return{...state,mode:"INSERT"};}case"a":{return{...state,mode:"INSERT",cursorIndex:getIndex.append(state)};

至る所で移動する次のstateを計算するとごちゃごちゃしたので、カーソル移動とテキスト編集をそれぞれ別のファイルに分けて関数化したものをreducerでは使用しています。

:file_folder: getIndex.ts

constright:IndexGetter=({value,mode,cursorIndex})=>{if(value.length===0||cursorIndex!==value.length-1){returncursorIndex+1;}else{returncursorIndex;}};constleft:IndexGetter=({value,mode,cursorIndex})=>{if(cursorIndex>0){returncursorIndex-1;}else{returncursorIndex;}};

:file_folder: getValue.ts

constbackspace:ValueGetter=({value,mode,cursorIndex})=>{return(value.slice(0,cursorIndex-1)+value.slice(cursorIndex,value.length));};constinsert:ValueGetter=({value,mode,cursorIndex,key})=>{return(value.slice(0,cursorIndex)+key+value.slice(cursorIndex,value.length));};

ここに苦労しました

ボックス形のCaret

Caret(入力時にカーソルの位置を示す部分)を操作するCSSは現在caret-colorが提供されています。
これは色の操作のみ操作できるプロパティで、viライクなボックス形のCaretは表現出来ません。
そこでハック感ありますが、inputタグは使わずにdivタグで入力フォームを表現する事にしました。

キー入力をReducerのActionとしたかったのでonKeydownを使用した結果、英数字の入力のみ行える(日本語入力できない)仕様になったのはかなり心残りです。。

3.gif

Reducer

カーソル位置は前述のcursorIndexで保持し、NORMALモードとINSERTモードのカーソル移動を実現しました。

入力値、カーソル位置、モードなどの状態は

これらの3つの属性のstate + 入力されるキーから、次のstateが決定されるためそれをreducerに書きました。

次のstateを前のstateから副作用のない関数として返せるような構造(getValue.ts, getIndex.ts)に分けています。
Vimならではのモーションとオペレーターのイメージで分けたからか、意外と見やすいReducerになった気がします。

機能

そこまで多くないのであえて書きません。
READMEに書いてあるので、気になる方はこちらへ!
:octocat: Github(https://github.com/ok8omk/Vinput)

文字の入力をkeydownにしてしまったので日本語入力を受け付けられなかったり、
正規表現パワー足りず実装できてない部分あったり、
本当は複数行のテキストエリアを実装したかったり…
…色々やり残してるのでPR絶賛お待ちしています :bow:

終わりに

ブラウザとかSlackとかで入力してる時に、全部Vimみたいにカーソル移動できたらいいのに!と思う瞬間が度々あるのが発端でした。(たまにありませんか?)

jsでCLIを表現するのは不毛な実装感がありますが、Reactとreducerのいい練習になりました。

npmで公開したので興味持って頂けた方は是非使って下さい!
npm(@ok8omk/vinput)

課題だらけと思うのでissue大歓迎です、気長に直していくのでぜひお願いします :bow:

ReactをVimで書く記事はあっても、
ReactでVimを書く記事は見たことないなあと思って書いたので、
パイオニアであることを祈っております… :aries::gemini::scorpius:

明日は @litalico-takamasa-mizukamiさんのAMP Storyです。
お楽しみに!

Viewing all 5718 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>