From 3d2e8341f076ae349249a91b747bc28d82978539 Mon Sep 17 00:00:00 2001 From: snaka Date: Wed, 6 May 2009 10:43:59 +0000 Subject: Add new plugin auto_word_select_mode.js git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@33104 d0d07461-0603-4401-acd4-de1884942a52 --- auto_word_select_mode.js | 303 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 auto_word_select_mode.js (limited to 'auto_word_select_mode.js') diff --git a/auto_word_select_mode.js b/auto_word_select_mode.js new file mode 100644 index 0000000..fab9de1 --- /dev/null +++ b/auto_word_select_mode.js @@ -0,0 +1,303 @@ +// +// auto_word_select_mode.js +// +// LICENSE: {{{ +// +// This software distributable under the terms of an MIT-style license. +// +// Copyright (c) 2009 snaka +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// OSI page : http://opensource.org/licenses/mit-license.php +// Japanese : http://sourceforge.jp/projects/opensource/wiki/licenses%2FMIT_license +// +// }}} + +// PLUGIN INFO: {{{ +var PLUGIN_INFO = + + {NAME} + Add auto word select mode. + 単語を自動選択するモードを追加します + 2.0pre + 2.1pre + http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/auto_word_select_mode.js + snaka + MIT style license + 1.0.0 + || + liberator.registerObserver("enter", function() { + mappings.addUserMap( + [modes.AUTO_WORD_SELECT], + ["s"], + "Translate selected word by multi_requester.js.", + function() { + // FIXME: + // A present mode is preserved in the stack beforehand by the push() method + // because it doesn't return to AUTO_WORD_SELECT mode before that when + // returning from the OUTPUT_MULTILINE mode. + modes.push(modes.AUTO_WORD_SELECT, null, true); + + var selText = content.getSelection().toString(); + var pattern = /[a-zA-Z]+/; + selText = pattern.test(selText) ? pattern.exec(selText) : selText; + events.feedkeys(":mr alc " + selText + "", true, true); + } + ); + }); + ||< + + ]]> + || + liberator.registerObserver("enter", function() { + mappings.addUserMap( + [modes.AUTO_WORD_SELECT], + ["s"], + "Translate selected word by multi_requester.js.", + function() { + // FIXME: + // A present mode is preserved in the stack beforehand by the push() method + // because it doesn't return to AUTO_WORD_SELECT mode before that when + // returning from the OUTPUT_MULTILINE mode. + modes.push(modes.AUTO_WORD_SELECT, null, true); + + var selText = content.getSelection().toString(); + var pattern = /[a-zA-Z]+/; + selText = pattern.test(selText) ? pattern.exec(selText) : selText; + events.feedkeys(":mr alc " + selText + "", true, true); + } + ); + }); + ||< + + 上記の例ではAUTO_WORD_SELECTモードにおいて、単語を選択した後、's'キーを + 押すと'alc'で登録されているサービスに対して検索を依頼し、その結果を + 画面下部のバッファに表示します。 + + modes.push()は、OUTPUT_MULTILINEモードから抜けたときに、AUTO_WORD_SELECT + モードに復帰させるために行っています。 + + 追加されたモードに対するマッピングはプラグインを読み込んだ後に行う必要 + があるので、registerObserver()で"enter"のタイミングでaddUserMap()している。 + + multi_requester.jsの使い方については、ソースのコメントや以下の + サイトなどを参照してください。 + - http://vimperator.kurinton.net/plugins/multi_requester.html + - http://d.zeromemory.info/2008/11/20/vimperator-multi_requester.html + + ]]> +; +// }}} + +(function(){ + +const NEW_MODE = "AUTO_WORD_SELECT"; +const KEY = liberator.globalVariables.auto_word_select_key || 'I'; + +if (!modes[NEW_MODE]) + modes.addMode(NEW_MODE, false, function() NEW_MODE); + +mappings.addUserMap( + [modes.NORMAL, modes.CARET, modes.VISUAL], + [KEY], + "Change to AUTO_WORD_SELECT mode.", + function() { + modes.push(modes[NEW_MODE]); + + if (content.getSelection().rangeCount == 0) { + let firstNode = content.document.body.firstChild; + let range = content.document.createRange(); + range.setStart(firstNode, 0); + range.setEnd(firstNode, 0); + content.getSelection().addRange(range); + } + } +); + +mappings.addUserMap( + [modes.AUTO_WORD_SELECT], + [KEY], + "Exit AUTO_WORD_SELECT mode.", + function() { + modes.pop(); + } +); + +mappings.add( + [modes.AUTO_WORD_SELECT], + [":"], + "Change command line mode.", + function() { + // FIXME: + // A present mode is preserved in the stack beforehand by the push() method + // because it doesn't return to AUTO_WORD_SELECT mode before that when + // exit from the COMMAND_LINE mode. + modes.push(modes.AUTO_WORD_SELECT, null, true); + mappings.get(modes.NORMAL, ":").action(); + } +); + +mappings.add( [modes.AUTO_WORD_SELECT], + ["l"], + "Move to right word and select.", + function() { + controller().wordMove(true, false); + if (selectable()) selectWord(); + } +); + +mappings.add( [modes.AUTO_WORD_SELECT], + ["h"], + "Move to left word and select.", + function() { + var before = range(); + content.getSelection().collapseToStart(); + controller().wordMove(false, false); + if (selectable()) selectWord(); + + // FIXME: + // Because the caret doesn't move in a certain situation, + // the following ugly codes are added. + var after = range(); + if (compareRange(before, after)) { + content.getSelection().collapseToStart(); + controller().wordMove(false, false); + } + } +); + +mappings.add( [modes.AUTO_WORD_SELECT], + ["j"], + "Move to below word and select.", + function() { + content.getSelection().collapseToStart(); + controller().lineMove(true, false); + if (selectable()) selectWord(); + } +); + +mappings.add( [modes.AUTO_WORD_SELECT], + ["k"], + "Move to above word and select.", + function() { + var before = range(); + content.getSelection().collapseToStart(); + controller().lineMove(false, false); + if (selectable()) selectWord(); + + // FIXME: + // Because the caret doesn't move in a certain situation, + // the following ugly codes are added. + var after = range(); + if (compareRange(before, after)) { + content.getSelection().collapseToStart(); + controller().lineMove(false, false); + } + + } +); + +function selectWord() { + controller().wordMove(true, false); + controller().wordMove(false, true); +} + +function controller() + buffer.selectionController; + +function compareRange(a, b) { + return (a.startNode.isSameNode(b.startNode) && + a.endNode.isSameNode(b.endNode) && + a.startOffset == b.startOffset && + a.endOffset == b.endOffset ) + ? true + : false; +} + +function range() { + var current = window.content.window.getSelection().getRangeAt(0); + return { + textString: current.toString(), + startNode: current.startContainer, + startOffset: current.startOffset, + endNode: current.endContainer, + endOffset: current.endOffset + } +} + +function selectable() { + var sel = content.getSelection(); + if (sel.anchorNode.nodeType != 3) return false; + if (sel.anchorOffset == sel.anchorNode.textContent.length) return false; + return true; +} + +//// for debuging +//liberator.registerObserver("modeChange", function(oldModes, newModes, stack) { +// liberator.dump(getModeName(oldModes[0]) +" + "+ getModeName(oldModes[1]) +// + " -> " + +// getModeName(newModes[0]) +" + "+ getModeName(newModes[1])); +// liberator.dumpStack(); +//}); +//function getModeName(id) modes.getMode(id) ? modes.getMode(id).name : ""; + +})(); + +// vim:sw=2 ts=2 et si fdm=marker: -- cgit v1.2.3