ついカッとなってtext objectのi", a", i', a'を実装した
IdeaVIMって実は text object を実装しているんだけど,どうゆうわけかQuote系(", ', `)とタグ(t)が未実装なのだ。タグは(難しそうだから)まあわかるとして,Quote系くらい実装しといたっていいやんか,と思い,ついカッとなって実装してしまった。:-)
ちょっとあやしい...というか詰めが甘いところがあるけど,普段使いに問題ないから,これ以上は深追いしない。ネット不通なところで作業してたんで,パッチじゃなくてコード片のみ残す。
まずは,こんな感じでEditorActionをいくつか用意する(plugin.xml, RegisterActions.javaの変更点は省略)。
package com.maddyhome.idea.vim.action.motion.object; public class MotionInnerDoubleQuoteAction extends TextObjectAction { public MotionInnerDoubleQuoteAction() { super(new Handler()); } private static class Handler extends TextObjectActionHandler { public TextRange getRange(Editor editor, DataPackage context, int count, int rawCount, Argument argument) { return CommandGroups.getInstance().getMotion().getQuoteRange(editor, context, count, false, '"'); } } }
大事なのは SearchHelper の findQuoteRange() 部分。...その前に MotionGroup(com.maddyhome.idea.vim.group) に getQuoteRange() を新設しとく。
=== SearchHelper.java () === public static TextRange findQuoteRange(Editor editor, char type, int count, boolean isOuter) { int pos = editor.getCaretModel().getOffset(); int line = EditorHelper.getCurrentLogicalLine(editor); int lineOffset = EditorHelper.getLineStartOffset(editor, line); CharBuffer charBuffer = EditorHelper.getLineBuffer(editor, line); int qstart = findQuoteLocation(charBuffer, type, pos - lineOffset, -1); if (qstart == -1) return null; int qend = findQuoteLocation(charBuffer, type, pos - lineOffset, 1); if (qend == -1) return null; int start = qstart + lineOffset + (isOuter ? 0 : 1); int end = qend + lineOffset; return new TextRange(start, end); } private static int findQuoteLocation(CharBuffer chars, char c, int pos, int dir) { while (pos >= 0 && pos < chars.length()) { if (chars.charAt(pos) == c) { // 見つかった if (pos > 0 && chars.charAt(pos - 1) == '\\') { // 前の文字がエスケープ文字だったら,キャンセル } else { return pos; } } pos += dir; } return -1; }
詰めが甘いのは,以下の2点。
- カーソル直下の文字がクォート文字の場合,そのクォート文字しか捕捉できない(ロジックがタコだから)。
- TextRangeの範囲指定がc, dといった編集系とヴィジュアルモード(v)とで終端の解釈にズレがある。
まあ,大した話じゃないので放置。:-P
ps.
ここまで来ると,it, at といったタグオブジェクトも実装したくなるんだけど,こっちはちょーっと手強そうだぬ。:-(