Skip to content

Instantly share code, notes, and snippets.

@958
Last active September 26, 2015 02:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 958/1024186 to your computer and use it in GitHub Desktop.
Save 958/1024186 to your computer and use it in GitHub Desktop.
[keysnail]Abbreviations manager
var PLUGIN_INFO =
<KeySnailPlugin>
<name>Abbreviations manager</name>
<description lang="ja">Vimperator の Abbreviations みたいなもの</description>
<updateURL>https://gist.github.com/958/1024186/raw/abbreviations.ks.js</updateURL>
<iconURL>https://sites.google.com/site/958site/Home/files/abbreviations.ks.png</iconURL>
<license>MIT</license>
<minVersion>1.8.5</minVersion>
<author>958</author>
<version>0.0.6</version>
<detail><![CDATA[
=== 概要 ===
略語を定義して、入力時に展開します
Vimperator の :ab とか C-] の劣化版です
=== 使い方 ===
==== 基本的な使い方 ====
まず、略語を定義します
エクステ 'abbreviations-add' を実行して
>||
k keysnail
||<
と入力後 Enter してみてください
そのあとに、どこかのテキストボックス上(たとえばナビゲーションバー) で "k" と入力後、エクステ 'abbreviations-expand' を実行してみてください
k が keysnail に展開されます
以下のようにキーバインドを設定するとよいかもしれません
>|javascript|
key.setEditKey('C-]', function (ev, arg) {
ext.exec('abbreviations-expand', arg, ev);
}, '略語を展開');
||<
また、KeySnail のプロンプト上で、k と入力後 SPC キーを押下してみてください
同様に k が keysnail に展開されます
プロンプト上では SPC キーの他にも " ' キーでも略語展開が行われます
==== 略語一覧 ====
保存済みの略語一覧を表示したり、削除したい場合は、エクステ 'abbreviations-show' を実行してください
なお、太字で表示されている略語は、後述の plugins.options['abbreviations.defined_abbreviations'] で定義されている略語の為、削除することはできません
==== 動的な文字列を展開する略語 ====
どこかのテキストボックス上で "URL" と入力後、エクステ 'abbreviations-expand' を実行してみてください
現在表示中のページの URL がテキストボックス上に表示されます
このような動的な略語があらかじめ定義されています
TITLE:
表示中のページタイトル
URL:
表示中のページ URL
S-URL:
表示中のページの短縮 URL (goo.gl)
SEL:
表示中のページの選択テキスト
これらは plugins.options['abbreviations.defined_abbreviations'] を設定することで上書き可能です
以下のように、展開後の文字列を返却する function を指定してください
>|javascript|
plugins.options['abbreviations.defined_abbreviations'] = {
"TITLE" : function() content.document.title,
"URL" : function() content.location.href,
"S-URL" : function()
JSON.parse(util.request('POST', 'https://www.googleapis.com/urlshortener/v1/url', {
header: { "Content-Type": "application/json" },
params: JSON.stringify({ longUrl: content.location.href })
}).responseText).id || '',
"SEL" : function() (content.getSelection() || "").toString(),
};
||<
なお plugins.options['abbreviations.defined_abbreviations'] には、通常の略語も設定可能です
エクステ 'abbreviations-add' で追加された略語は KeySnail の persist エリアに保存されますが、設定ファイルを統一するために plugins.options['abbreviations.defined_abbreviations'] のみ利用するのも良いかもしれません
>|javascript|
plugins.options['abbreviations.defined_abbreviations'] = {
// 動的な略語定義
"TITLE" : function() content.document.title,
"URL" : function() content.location.href,
"S-URL" : function()
JSON.parse(util.request('POST', 'https://www.googleapis.com/urlshortener/v1/url', {
header: { "Content-Type": "application/json" },
params: JSON.stringify({ longUrl: content.location.href })
}).responseText).id || '',
"SEL" : function() (content.getSelection() || "").toString(),
// 通常の略語定義
"k" : "KeySnail",
};
||<
==== キーを送る ====
エクステ 'abbreviations-add' を実行して
>||
k keysnail<CR>
||<
と入力後 Enter してみてください
その後、検索ボックスなどで k と入力後、エクステ 'abbreviations-expand' を実行してみてください
検索が開始されたと思います
このように、キーイベントを送ることが可能です
以下のキー定義が使用可能です
<CR> <ESC> <f*> <right> <left> <up> <down> <prior> <next> <end> <home> <backspace> <print> <insert> <pause> <delete> <kana> <hangeul> <hangul> <kanji> <hanja> <convert> <nonconvert> <accept> <modechange> <select> <print> <execute> <l_windows> <r_windows>
また、"<5left>" など、"<" の直後に数字を指定するとキーを指定回数送ります
==== 略語内に略語を使用する ====
エクステ 'abbreviations-add' を実行して
>||
info %TITLE %URL
||<
と入力後 Enter してみてください
その後、検索ボックスなどで "info" と入力後、エクステ 'abbreviations-expand' を実行してみてください
このように "%略語" と定義することで、略語内に略語を使用することが出来ます
なお、略語の入れ子は 1 階層のみ対応しています
]]></detail>
</KeySnailPlugin>;
var pOptions = plugins.setupOptions('abbreviations', {
'keymap': {
preset: {
"C-z" : "prompt-toggle-edit-mode",
"SPC" : "prompt-next-page",
"b" : "prompt-previous-page",
"j" : "prompt-next-completion",
"k" : "prompt-previous-completion",
"g" : "prompt-beginning-of-candidates",
"G" : "prompt-end-of-candidates",
"q" : "prompt-cancel",
//
"c" : "create",
"r" : "remove",
},
description: M({
ja: "略語一覧の操作用キーマップ",
en: "Local keymap for abbreviations list"
})
},
'defined_abbreviations': {
preset: {
"TITLE" : function() content.document.title,
"URL" : function() content.location.href,
"S-URL" : function()
JSON.parse(util.request('POST', 'https://www.googleapis.com/urlshortener/v1/url', {
header: { "Content-Type": "application/json" },
params: JSON.stringify({ longUrl: content.location.href })
}).responseText).id || '',
"SEL" : function() (content.getSelection() || "").toString(),
},
description: M({
ja: "略語定義",
en: "Abbreviations"
})
},
'prompt_spc': {
preset: true,
description: M({
ja: "プロンプトで SPC キー等押下時に略語を展開する",
en: "When pressing the space key at the prompt to expand the abbreviation"
})
}
}, PLUGIN_INFO);
const GROUP = 'abbreviations';
var gAbbrs = _.extend(persist.restore(GROUP) || {}, pOptions['defined_abbreviations']);
function getKeysRegExp()
new RegExp('(?:^|"|\'|\\s| )(' + Object.keys(gAbbrs).join('|') + ')$');
function parseExpandText(aValue) {
if (typeof aValue == 'function')
aValue = aValue();
var array = [];
for (var [k, v] in Iterator(gAbbrs)) {
if (aValue.indexOf('%' + k) == -1)
continue;
var value = v;
if (v && typeof v == 'function') {
value = v();
}
aValue = aValue.replace('%' + k, value);
}
aValue.split('<').forEach(function(v, i) {
var temp = v.split('>');
if (i > 0)
temp[0] = '<' + temp[0];
temp = temp.map(function(v, i) {
if (i < temp.length - 1)
v += '>';
return v;
}).filter(function(v) !!v);
Array.prototype.push.apply(array, temp);
});
return array;
}
// Hack prompt text box
(function() {
var textbox = document.getElementById("keysnail-prompt-textbox");
if (!textbox) return;
// clean up
if (my.abbrKeyHandler)
textbox.removeEventListener('keypress', my.abbrKeyHandler, false);
my.abbrKeyHandler = null;
if (pOptions['prompt_spc']) {
my.abbrKeyHandler = function(ev) {
if (/^(SPC|"|')$/.test(key.keyEventToString(ev)))
ext.exec('abbreviations-expand', null, ev);
};
textbox.addEventListener('keypress', my.abbrKeyHandler, false);
}
})();
// Add ext
plugins.withProvides(function (provide) {
provide('abbreviations-add', function (ev, arg) {
prompt.read('Input new abbreviation :', function(word) {
if (!word)
return;
var words = word.trim().split(' ');
if (words.length < 2)
return;
var key = words.shift();
var value = words.join(' ');
gAbbrs[key] = value;
var temp = persist.restore(GROUP) || {};
temp[key] = value;
persist.preserve(temp, GROUP);
});
}, M({ja:'略語を追加', en:'Append abbreviation'}));
provide ('abbreviations-expand', function (ev, arg) {
var elem = ev.originalTarget;
var value = elem.value;
if (!value)
return;
var cursor = elem.selectionStart;
if (cursor != elem.selectionEnd)
return;
var abbr = value.substring(0, cursor).match(getKeysRegExp());
abbr = (abbr && abbr[1]) ? abbr[1] : null;
if (abbr && abbr in gAbbrs) {
elem.selectionStart = cursor - abbr.length;
elem.selectionEnd = cursor;
parseExpandText(gAbbrs[abbr]).forEach(function(k) {
var ev = [];
var count = 1;
if (k.match(/^<(\d*)(.+)>$/)) {
count = parseInt(RegExp.$1, 10) || 1;
k = RegExp.$2;
switch (k) {
case 'CR':
for (var i = 0; i < count; i++)
ev.push(key.stringToKeyEvent('RET', false));
break;
case 'ESC':
for (var i = 0; i < count; i++)
ev.push(key.stringToKeyEvent('ESC', false));
break;
case 'tab':
k = '\t';
break;
default:
try {
for (var i = 0; i < count; i++)
ev.push(key.stringToKeyEvent('<' + k + '>', false));
} catch(ex) {
count = 1;
}
break;
}
}
if (ev.length > 0) {
for (var i = 0; i < count; i++)
elem.dispatchEvent(ev[i]);
} else {
for (var i = 0; i < count; i++)
command.insertText(k);
}
});
}
}, M({ja:'略語を展開', en:'Expand abbreviation'}));
provide ('abbreviations-show', function (ev, arg) {
var presistCache = persist.restore(GROUP) || {};
var collection = [];
for (var [key, value] in Iterator(gAbbrs)) {
var type = typeof value;
if (type == 'function')
value = 'function() { ... }';
collection.push([key, value, type]);
}
prompt.selector({
message : 'Abbreviations :',
collection : collection,
header : ['Key', 'Value'],
flags : [0, 0, HIDDEN|IGNORE],
keymap : pOptions['keymap'],
stylist : function(args, n, cur) {
var style = [];
if (!(args[0] in presistCache))
style.push('font-weight: bold');
if (n == 1 && args[2] == 'function')
style.push('font-style: italic');
return style.join(';');
},
actions : [
[ function() ext.exec('abbreviations-add'), 'Create new abbreviation', 'create' ],
[ function(aIndex, rows) {
if (rows[aIndex][0] in presistCache) {
delete presistCache[rows[aIndex][0]];
persist.preserve(presistCache, GROUP);
delete gAbbrs[rows[aIndex][0]];
rows.splice(aIndex, 1);
prompt.refresh();
}
}, 'Remove selected abbreviation', 'remove,c' ],
]
});
}, M({ja: '略語一覧を表示', en:'Show abbreviations list'}));
}, PLUGIN_INFO);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment