タグファイルから補完
ctagsの生成したtagsファイルから検索して単語のメニューを出します。
項目を選ぶとその単語が挿入されます。
kazyさんのctags.exe_で_tags_ファイルを生成、タグジャンプを行うマクロとあわせてお使いください。
- インストール
- 下のスクリプトをコピーして、MeryのMy Macroフォルダなどに保存
- マクロを登録し、Ctrl+Shift+SpaceやCtrl+Qキーなどに設定する
- Mery.exeのあるフォルダに[ctags.exe]を置く
- 初回起動
- タグファイルが生成されていないので、どこに生成するか尋ねられる
- 指定したディレクトリ以下のソースファイル全てが再帰的にタグファイルに登録される
- 「タグファイルの作成が完了しました」とステータスバーに出るまで待つ
- タグファイルの作成後
- 補完したい単語の右にカーソルを置き、マクロを起動する
- メニューの項目を選ぶと、その単語が挿入される
- メニューの最後の「タグファイルを更新する」を選ぶと、タグファイルを作り直すことができる
// タグファイルから補完.js r4
/** 設定 **/
// タグファイルの名前
var TAGS = "tags"
// ctags.exeの名前
// 相対パスの場合は以下のディレクトリから順に探します
// ・mery本体と同じディレクトリ
// ・スクリプトと同じディレクトリ
// ・何もなし(PATHにあることを期待)
var CTAGS = "ctags.exe"
// ctagsに与える引数 (初期設定:位置を行番号で記憶(tagJump.js互換)、フォルダを再帰的に処理)
var CTAGS_FLAGS = "--excmd=number --recurse"
// 単語の途中で補完する際の挙動
// trueにするとカーソルの置かれた単語全体から補完
// falseにするとカーソルより左から補完します
var WHOLE_WORD = false
/** 本体 **/
var FileSystem = new ActiveXObject("Scripting.FileSystemObject")
var Shell = new ActiveXObject("WScript.Shell")
main()
function main()
{
var ctags = makeCtags()
var tags = makeTags(ctags)
var query = getQueryWord()
var words = tags.lookup(query)
var word = chooseWord(words, tags)
writeWord(word)
}
function makeCtags()
{
return { run: run }
function run(dir)
{
var ctags = findCtags()
if (!ctags)
{
throw new Error("ctags.exeが見つかりません")
}
window.Status = 'タグファイルを作成しています お待ちください'
Shell.CurrentDirectory = dir
Shell.Run(ctags + " -f " + TAGS + " " + CTAGS_FLAGS, 0, true)
window.Status = 'タグファイルを作成しました'
return FileSystem.BuildPath(dir, TAGS)
}
function findCtags()
{
return findCtagsFrom(window.ScriptFullName) ||
findCtagsFrom(editor.FullName) ||
findCtagsFrom("")
}
function findCtagsFrom(hint)
{
var dir = FileSystem.GetParentFolderName(hint)
var ctags = FileSystem.BuildPath(dir, CTAGS)
if (FileSystem.FileExists(ctags))
{
return hint == "" ? CTAGS : '"' + FileSystem.GetAbsolutePathName(ctags) + '"'
}
}
}
function makeTags(ctags)
{
var text = loadTagfile()
return { lookup: lookup, update: update }
function lookup(word)
{
var re = new RegExp("^" + reEscape(word) + "[^\\t]*", "igm")
return text.match(re)
}
function reEscape(w)
{
return /^\s*$/.test(w) ? "\\w" : w.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
}
function loadTagfile()
{
var tagfile = findTagfile()
if (!tagfile)
{
tagfile = makeTagfile()
}
return slurp(tagfile)
}
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 = window.Prompt("タグファイル作成フォルダ", document.Path)
if (!dir)
{
window.Quit()
}
return ctags.run(dir)
}
function update()
{
var file = findTagfile()
if (!file) { throw new Error("タグファイルが見つかりません") }
var dir = FileSystem.GetParentFolderName(file)
return ctags.run(dir)
}
function slurp(filename)
{
var f = FileSystem.OpenTextFile(filename)
var text = f.ReadAll()
f.Close()
return text
}
}
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, tags)
{
var menu = makeMenu()
var i = menu.Track(0)
if (i == -1)
{
tags.update()
}
return 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 }
uniq(words)
words.sort(function(a, b)
{
return a.localeCompare(b)
})
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 writeWord(word)
{
if (word)
{
document.selection.Text = word
}
}
function uniq(array)
{
var n = 0
for (var i = 1; i < array.length; i++)
{
if (array[n] !== array[i])
{
n++
array[n] = array[i]
}
}
array.length = n + 1
}
スポンサーリンク