「タグファイルから補完」の版間の差分
変更日の追加、箇条書きの修正 |
ソースコードの整形 |
||
| 129行目: | 129行目: | ||
main() | main() | ||
function main() | function main() { | ||
{ | var ctags = makeCtags() | ||
var tags = makeTags(ctags) | |||
var query = getQueryWord() | |||
var result = tags.lookup(query) | |||
var word = chooseWord(result) | |||
if ("string" === typeof word) { | |||
writeWord(word) | |||
} else if (word === false) { | |||
tags.update() | |||
} else { | |||
jumpToDefinition(word) | |||
} | |||
} | } | ||
function makeCtags() | function makeCtags() { | ||
{ | return { | ||
run: run | |||
} | |||
function run(dir) { | |||
var ctags = findCtags() | |||
try { | |||
Shell.CurrentDirectory = dir | |||
window.Status = 'タグファイルを作成しています お待ちください' | |||
Shell.Run('"' + ctags + '" -o ' + TAGS + " " + CTAGS_FLAGS, 0, true) | |||
} catch (e) {} | |||
window.Status = 'タグファイルを作成しました' | |||
return FileSystem.BuildPath(dir, TAGS) | |||
} | |||
function findCtags() { | |||
if (FileSystem.FileExists(CTAGS)) { | |||
return CTAGS | |||
} | |||
var dir = FileSystem.GetParentFolderName(editor.FullName) | |||
var ctags = FileSystem.BuildPath(dir, CTAGS) | |||
if (FileSystem.FileExists(ctags)) { | |||
return ctags | |||
} | |||
throw new Error("ctags.exeが見つかりませんでした\nMery本体のディレクトリに置くか、絶対パスを設定してください") | |||
} | |||
} | } | ||
function makeTags(ctags) | function makeTags(ctags) { | ||
{ | var fullname = findTagfile() | ||
var text = loadTagfile() | |||
return { | |||
lookup: lookup, | |||
update: update | |||
} | |||
function getPath() { | |||
return FileSystem.GetParentFolderName(fullname) | |||
} | |||
function lookup(word) { | |||
if (/^\s*$/.test(word)) { | |||
return | |||
} | |||
word = reEscape(word) | |||
var opts = CASE_INSENSITIVE ? "igm" : "gm" | |||
var re = new RegExp("^" + word + ".*$", opts) | |||
var lines = text.match(re) | |||
if (!lines) { | |||
return [] | |||
} | |||
return calcWords().concat(calcDefinitions(word)) | |||
function calcWords() { | |||
var words = new Array(lines.length) | |||
words[0] = lines[0].substring(0, lines[0].indexOf("\t")) | |||
if (words.length === 1) { | |||
return words[0] === word ? [] : words | |||
} | |||
var n = 0 | |||
for (var i = 1; i < lines.length; i++) { | |||
var w = lines[i].substring(0, lines[i].indexOf("\t")) | |||
if (words[n] !== w) { | |||
n++ | |||
words[n] = w | |||
} | |||
} | |||
words.length = n + 1 | |||
words.sort(function(a, b) { | |||
return a.localeCompare(b) | |||
}) | |||
return words | |||
} | |||
function calcDefinitions(word) { | |||
var defs = new Array(lines.length) | |||
var n = 0 | |||
for (var i = 0; i < lines.length; i++) { | |||
var line = lines[i] | |||
var tab1 = line.indexOf("\t") | |||
if (tab1 !== word.length) { | |||
continue | |||
} | |||
var tab2 = line.indexOf("\t", tab1 + 1) | |||
var endnum = line.indexOf(";", tab2 + 1) | |||
var sig = line.indexOf("signature:", endnum + 1) | |||
var name = line.substring(0, tab1) | |||
var filename = line.substring(tab1 + 1, tab2) | |||
var linenum = line.substring(tab2 + 1, endnum) | |||
var signature = sig < 0 ? "" : line.substring(sig + "signature:".length) | |||
var fullname = FileSystem.BuildPath(getPath(), filename) | |||
defs[n] = [fullname, linenum, filename, name + signature] | |||
defs[n].toString = joinme | |||
n++ | |||
} | |||
defs.length = n | |||
return defs | |||
} | |||
function joinme() { | |||
return this[3] + " (" + this[2] + " : " + this[1] + ")" | |||
} | |||
} | |||
function reEscape(w) { | |||
return w.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") | |||
} | |||
function loadTagfile() { | |||
if (!fullname) { | |||
fullname = makeTagfile() | |||
} | |||
return slurp(fullname) | |||
} | |||
function findTagfile() { | |||
var dir = document.Path | |||
while (FileSystem.FolderExists(dir)) { | |||
var file = FileSystem.BuildPath(dir, TAGS) | |||
if (FileSystem.FileExists(file)) { | |||
return file | |||
} | |||
dir = FileSystem.GetParentFolderName(dir) | |||
} | |||
} | |||
function makeTagfile() { | |||
var dir = FileSystem.BuildPath(document.Path, DEFAULT_TAGS_DIR) | |||
if (CONFIRM_CREATE_TAGS) { | |||
dir = window.Prompt("タグファイル作成フォルダ", dir) | |||
} | |||
if (!dir) { | |||
window.Quit() | |||
} | |||
return ctags.run(dir) | |||
} | |||
function update() { | |||
return ctags.run(getPath()) | |||
} | |||
function slurp(filename) { | |||
var f = FileSystem.OpenTextFile(filename) | |||
var text = f.ReadAll() | |||
f.Close() | |||
return text | |||
} | |||
} | } | ||
function getQueryWord() | function getQueryWord() { | ||
{ | var s = document.selection | ||
if (!s.IsEmpty) { | |||
return s.Text | |||
} | |||
if (WHOLE_WORD) { | |||
s.SelectWord() | |||
// hoge|(); → hogeFuga|(); のように補完 | |||
if (s.Text.length == 1 && !/\w/.test(s.Text)) { | |||
s.Collapse(meCollapseStart) | |||
s.WordLeft(true) | |||
} | |||
} else { | |||
s.WordLeft(true) | |||
} | |||
if (/\A\s+\z/.test(s.Text)) { | |||
s.Collapse(meCollapseEnd) | |||
} | |||
return s.Text | |||
} | } | ||
function chooseWord(words) | function chooseWord(words) { | ||
{ | if (words && words.length === 1 && typeof words[0] === "string") { | ||
return words[0] | |||
} | |||
var menu = makeMenu() | |||
var i = menu.Track(0) | |||
return i === -1 ? false : words && words[i - 1] | |||
function makeMenu() { | |||
var menu = window.CreatePopupMenu() | |||
initMenu(menu) | |||
menu.Add("タグファイルを更新する", -1) | |||
return menu | |||
} | |||
function initMenu(menu) { | |||
if (!words || words.length == 0) { | |||
return | |||
} | |||
var n = 0 | |||
function addHotkey(word) { | |||
if (n > 34) { | |||
return word | |||
} | |||
n++ | |||
return "&" + n.toString(36) + ". " + word | |||
} | |||
for (var i = 0; i < words.length; i++) { | |||
menu.Add(addHotkey(words[i]), i + 1) | |||
} | |||
menu.Add(undefined, 0, meMenuSeparator) | |||
} | |||
} | } | ||
function jumpToDefinition(def) | function jumpToDefinition(def) { | ||
{ | if (!def) { | ||
return | |||
} | |||
window.Status = def + "にジャンプします" | |||
var file = def[0] | |||
var line = def[1] | |||
editor.OpenFile(file, 0, meOpenAllowNewWindow) | |||
editor.ActiveDocument.selection.SetActivePoint(mePosLogical, 1, line, false) | |||
editor.ActiveDocument.Activate() | |||
} | } | ||
function writeWord(word) | function writeWord(word) { | ||
{ | if (word) { | ||
document.selection.Text = word | |||
} | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
スポンサーリンク