なっく日報

技術やら生活やらのメモ

ここ3年ほど使ってみて得られたIdeaVimの知見

IntelliJ IDEAが優秀過ぎてほとんどカスタマイズしてないですがちょっとまとめる機会があったので残しておきます。

github.com

なお、それぞれの設定は ~/.ideavimrc に設定します。

:source ~/.ideavimrc で即時反映されます。

あのPluginが使える

どういう基準かは不明ですが3つだけ組み込まれています。
※ この記事を公開した次の日にeasymotionが増えていた GitHub - easymotion/vim-easymotion: Vim motions on speed!

github.com github.com github.com

set surround
set multiple-cursors
set commentary

私はVimでも普段使いしている surroundcommentary だけ有効にしています(multiple-cursors はあまりなじまなかったため有効にせず)

ideajoin を有効にしておく

J とかで行を連結する際により高機能に使えるので ideajoin は有効にしておきましょう。

set ideajoin

すると↓のような挙動になります。

"Hello" +                 ->       "Hello world"
" world!"

詳しい挙動はこちらのWikiにまとまっています。

https://github.com/JetBrains/ideavim/wiki/%60ideajoin%60-examples

ideaput はOFF、クリップボードは はONに

デフォルトで ideaput がONになってます。これはIndentをいい感じにしてくれるものらしいですが、 私個人的にはなじまなかったのでOFFにしました。

あと、コピーしたタイミングでOS(Mac)のクリップボードにコピーされてほしかったので set clipboard+=unnamed しています。

set clipboard-=ideaput
set clipboard+=unnamed

Actionを任意のキーにマッピングする

IntelliJ IDEAのActionを任意のキーにマッピングできます。

:actionlist で設定できるActionが確認できます。

私はあまり使ってないですが、↓の進む/戻るだけ有効にしてます。 IdeaVimで実装されている <C-o> <C-i> よりも動きがいい気がするのが理由です。

nnoremap <C-o> :<C-u>action Back<CR>
nnoremap <C-i> :<C-u>action Forward<CR>

まとめ

IntelliJ IDEAが優秀だし、IdeaVimもよくできている。

本日はこんなところで。

KotlinのDelegation(デリゲーション、委譲)とView adapterパターンの相性がよい件

最近少しずつ仕事でKotlinを触っているので、ちょっとしたメモ。

Delegation(デリゲーション、委譲)が便利

KotlinにはDelegationというデリゲーション、委譲(まんま)の実装を簡単にしてくれる機能があります。

https://kotlinlang.org/docs/reference/delegation.html

具体的にはJavaだと

class Base {
  private String name;

  Base(String name) {
    this.name = name;
  }

  public String getName() { 
    return this.name; 
  }
}
class Derived {
  private Base base;

  Derived(Base base) {
    this.base = base;
  }

  public String getName() { 
    return this.base.getName(); 
  }
  
  public void printName() {
    System.out.println(this.getName());
  }
}

// new Derived(new Base("名前")).printName();
// 名前

なコードは KotlinでInterfaceを準備すればスッキリ書けると。

interface Base {
    val name: String
}
class BaseImpl(override val name: String) : Base
class Derived(private val base: Base) : Base by base {
  fun printName() = println(this.name)
}

// Derived(BaseImpl("名前")).printName()
// 名前

(例がいまいちですが・・・)

View adapterとは

で、本題。

「レガシーソフトウェア改善ガイド」の「ビューレイヤーの複雑さ」という項目に出てきた「View adapter」なる概念があります。

DB → モデル → ビュー(と表示関連ロジック)

↑は↓にしなさいと。

DB → モデル → View adapter(と表示関連ロジック) → ビュー

テンプレートエンジンに書いてしまいそうな表示関連ロジックを、その言語で実装できるレイヤーに移して実装しましょうということだと理解しています。

JSPとかPHPで分岐がえらいことになっているレガシーなコードを見たことないでしょうか? FreeMarker/Thymeleaf/ERB/Pug どんな言語のどんなテンプレートエンジン使っていても起こりうる現象だと思います)

tech.kitchhike.com

この記事で紹介されているViewModelという概念にも近いと思います。

実装してみた

UserEntityなるモデルからfullNameを返す際にHTMLのタグで囲ってみました。

UserなるInterfaceにデフォルトプロパティ(Javaにはない)とデフォルトメソッドを実装する必要があります。

こんな感じ。UserViewがView adapterです。

interface User {
    val firstName: String;
    val lastName: String;
    val fullName get() = "${firstName} ${lastName}"
}

class UserEntity(
    override val firstName: String, 
    override val lastName: String
) : User

class UserView (
    val user: User
) : User by user { 
    override val firstName
        get() = "<span>${user.firstName}</span>"
    override val lastName
        get() = "<span>${user.firstName}</span>"
    override val fullName get() = "<div>${super.fullName} 様</div>"
}

fun main(args : Array<String>) { 
    val userEntity = UserEntity("太郎", "山田")
    val userView = UserView(userEntity)
    println(userEntity.fullName)
    println(userView.fullName)
}
// 山田 太郎
// <div><span>山田</span> <span>太郎</span> 様</div>

UserEntityをラップしたUserViewでHTMLのタグで囲ったfullNameを返却させることができました。

Interfaceが必要なのはちょっとまどろっこしいものの、なかなか良さ気に見えます。

実際現場で使っていくかは不明ですが、一つの手段として理解しておくと幸せになれることがあるかもしれません。

ほんでは。

MacのVimでESCまたは<C-[>押した際に日本語入力をOFFにしたい(JISキーボード編)

自分向けのメモです。

MacVimあるいはターミナル上のVimでESCAPEまたは<C-[> を押した際に日本語入力をOFFにする方法です。

Karabiner-Elementsを使う

いろいろ調べましたがこれしかなさそう。

brew cask install karabiner-elements

でインストールします。

設定ファイル作成

※ 追記:標準ルールで準備してくれているので設定ファイルを作成する必要はないです。

https://pqrs.org/osx/karabiner/complex_modifications/ (Karabiner-Elements Preferences → Complex Modifications → Add rule → Import more rules from the Internet で開く画面)

の 「For Japanese (日本語環境向けの設定) (rev 3)」 の「escキーを押したときに、英数キーも送信する(vim用)」と「Ctrl+[を押したときに、英数キーも送信する(vim用) (rev 2)」

をインポートするだけでOKでした。

qiita.com

の記事を参考にさせていただきました。

とてもわかり易くてGOOD!

ただし、JISキーボード使っている人やiTerm2使っている人だと動かないので注意が必要です。

自分の場合

~/.config/karabiner/assets/complex_modifications/FromEscapeToJapanese_eisuu.json

を以下の内容で作成しました。

{
  "title": "ESCまたは^[でIMEをOFF",
  "rules": [
    {
      "description": "VimでESCまたは^[を押したときにIMEをOFFにする",
      "manipulators": [
        {
          "type": "basic",
          "from": { "key_code": "escape", "modifiers": { "optional": [ "any" ] } },
          "to": [ { "key_code": "lang2" }, { "key_code": "escape" } ],
          "conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [
            "^com\\.apple\\.Terminal$", "^org\\.vim\\.", "^com\\.googlecode\\.iterm2$" ] } ]
        },
        {
          "type": "basic",
          "from": { "key_code": "close_bracket", "modifiers": { "mandatory": ["left_control"] } },
          "to": [ { "key_code": "lang2" }, { "key_code": "escape" } ],
          "conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [
            "^com\\.apple\\.Terminal$", "^org\\.vim\\.", "^com\\.googlecode\\.iterm2$" ] } ]
        }
      ]
    }
  ]
}

あとは、PreferencesのComplex ModificationsからAdd ruleするだけです。

ハマりどころ

Karabiner-ElementsのPreferencesより、Virtual Keyboardを45にしないと入力が変になります(USキーボード扱いされている?)

忘れずに変更しておきましょう。

最後に

なお、GitHubにも設定ファイル上げておきました。

https://github.com/yukidarake/dotfiles/blob/master/.config/karabiner/assets/complex_modifications/FromEscapeToJapanese_eisuu.json

CSVファイルの特定の列を空文字にするコマンド

c0,c1,c2,c3,c4
c0,c1,c2,c3,c4
c0,c1,c2,c3,c4
c0,c1,c2,c3,c4
c0,c1,c2,c3,c4

の列の数を変えずにc1だけ消して、↓のようにするにはどうするか?

c0,,c2,c3,c4
c0,,c2,c3,c4
c0,,c2,c3,c4
c0,,c2,c3,c4
c0,,c2,c3,c4

cutコマンドを使うと

cut -d, -f 1,3- a.csv

c0,c2,c3,c4
c0,c2,c3,c4
c0,c2,c3,c4
c0,c2,c3,c4
c0,c2,c3,c4

cutだけに列自体消えてしまいます。

自分が思いついた方法はこう

perl -F, -lape '$F[1]="";$_=join(",",@F)' a.csv

結果、↓のようになります。

c0,,c2,c3,c4
c0,,c2,c3,c4
c0,,c2,c3,c4
c0,,c2,c3,c4
c0,,c2,c3,c4

awkでもいいかもですが一旦これで。

ちなみにperlのオプションは以下の通り

❯ perl -h

Usage: perl [switches] [--] [programfile] [arguments]
  -a                autosplit mode with -n or -p (splits $_ into @F)
  -e program        one line of program (several -e's allowed, omit programfile)
  -F/pattern/       split() pattern for -a switch (//'s are optional)
  -l[octal]         enable line ending processing, specifies line terminator
  -p                assume loop like -n but print line also, like sed

Digg Readerの代替RSS Reader

2018/03/26で愛用していたDigg Readerが終了してしまうとのこと。

で、使用感の似ている代わりのRSS Readerを探したのですが、なかなか見つからず。。

alternative.me

medium.com

らへんの記事を見たのですが、FeedlyとかInoreaderとかは使用感がちょっと合わず(思えば、Google Readerが終了した際にも試して、しっくりこないで諦めたのでした・・・)

で、もうこうなったら書かれているのをしらみつぶしに試していこうと思い、見ていった結果、移転先は・・・

theoldreader.com

になりました。

決め手は

  • スマホのブラウザで見られること(iPhoneChromeで見たい。アプリは嫌)
  • リスト表示に対応していること(サムネイルとかは不要。タイトルのみでいい)
  • できればキーボードショートカットに対応していること(たまにPCで見たときにいい)

らへん。今のところいい感じに使えています。

【オレオレ】ターミナル環境2017変更点

こんにちは!こんにちは!

2018年ですが、2017年に書きかけだった記事をアップしておきます。

昨年久々にターミナル上で、とあるシステムの開発をした際に得られた知見です。

※ リモートのLinuxサーバにSSHでアクセスして開発してました。普段は手元のPCでIntelliJJavaやらJavaScriptやらで開発しています。この時の言語はPHPだったのですが諸事情によりこのスタイルで開発せざるを得ず。。

大方針

極力設定が少ないモノを使う。さらに極力デフォルトの設定を使う。

シェル

相変わらずfish推しです。fish いいですよ fish。

Vim

Syntastic → ale

github.com

Asynchronous Lint Engine との略とのことで、シンタックスチェックが非同期でできます(SyntasticはLintのトリガーとして保存が必要でした)

Syntasticより快適。

NeoBundle → vim-plug

github.com

パッケージマネージャはよりシンプルなものに。

Unite.vim → fzf.vim

github.com

Unite.vimと機能的に同一ではないですが - プロジェクト内のファイルをファジーな感じで探す - 全ファイルの全行から単語検索 みたいな一番やりたいことは実現できるので乗り換えました。

vim-plug使い始めた+fishシェルに乗り換えてfzfを使い始めたという理由もあります(作者が同じ。fzfはpecoと同じようなツール)

The Silever Searcher(ag) → ripgrep(rg)

grepの代替ツールとして。

github.com

速いので乗り換えました。本当に速い。

fzf.vim との連携は

https://github.com/junegunn/fzf.vim#advanced-customization

公式に設定例があります。

その他

Tmuxも相変わらず使ってますが、2.5に上げると設定ファイルの書き方が変わっていて嵌りました。

https://github.com/tmux/tmux/issues/754#issuecomment-297452143

コチラ参考になりました。

急に動かなくなるので気をつけましょう。

まとめ

と、いろいろ書いてきましたが、IntelliJに一度慣れてしまった今、IntelliJの方が開発しやすいと思える身体になってしまいました。

言語や作るシステムの規模にもよりますが、ターミナル環境を整えたりバージョンアップに追従する時間のコストを考えると、 どうにもコスパが・・・

とはいえ、必要な場面もまだまだあるので、なるべくデフォルト設定に身体を最適化させる方針でちょいちょい整えていこうかと思います。

Windowsでシェルスクリプト書きたいときはShellJSが使える

久々のブログ更新となります。

シェルスクリプトWindows用に移植したい・・・という場面でShellJSが便利だったというお話です。

ShellJSとは?

github.com

ヤツです。

採用実績

YeomanとかZeptoとかJS界隈の有名どころで使われています。
GitHubスター数も5,835(2017/05/03現在)なので結構人気あるライブラリと言ってよいのではないでしょうか。 自分は ESLintで使われていて知りました。

何で必要になった?

当初JSファイルをcatして結合するだけの単純なスクリプトシェルスクリプトで書いてました(LinuxWindows(MSYS2)だけで動けばよい)
ところが、Windowsコマンドプロンプト使っている人が・・・
コマンドプロンプト用にバッチファイル書いて二重管理とかアレだなぁと思っていたところ、ふと存在を思い出しました。

イメージ

https://github.com/shelljs/shelljs の例そのままですが、↓のようなノリで書けます。

var shell = require('shelljs');

if (!shell.which('git')) {
  shell.echo('Sorry, this script requires git');
  shell.exit(1);
}

// Copy files to release dir
shell.rm('-rf', 'out/Release');
shell.cp('-R', 'stuff/', 'out/Release');

// Replace macros in each .js file
shell.cd('lib');
shell.ls('*.js').forEach(function (file) {
  shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
  shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
  shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file);
});
shell.cd('..');

// Run external tool synchronously
if (shell.exec('git commit -am "Auto-commit"').code !== 0) {
  shell.echo('Error: Git commit failed');
  shell.exit(1);
}

自分の場合

catして結合したテキストをgrep -vして書き出すスクリプトがこう変わりました。

シェルスクリプト

cat src/*.js | grep -vE '^\s*//.+' > target/bundle.js

ShellJS版

npm install shelljs でインストールしておく。この辺のNode.jsの説明は省略。

const shell = require('shelljs');
shell.cat('src/*.js').grep('-v', '^\s*//.+').to('target/bundle.js');

パイプもいい感じに書けます。

まとめ

Windowsシェルスクリプトが書きたい→ShellJS お試しください。