「タグファイルから補完」の版間の差分

提供: MeryWiki
ナビゲーションに移動 検索に移動
ページの作成:「;'''説明'''<br> ctagsの生成したtagsファイルから検索して単語のメニューを出します。 項目を選ぶとその単語が挿入されます。 ...」
 
編集の要約なし
1行目: 1行目:
;'''説明'''<br>
ctagsの生成したtagsファイルから検索して単語のメニューを出します。
ctagsの生成したtagsファイルから検索して単語のメニューを出します。


6行目: 5行目:
kazyさんの[[Ctags.exeでtagsファイルを生成、タグジャンプを行うマクロ]]とあわせてお使いください。
kazyさんの[[Ctags.exeでtagsファイルを生成、タグジャンプを行うマクロ]]とあわせてお使いください。


;'''使い方'''<br>


*インストール
*インストール
27行目: 24行目:
#メニューの最後の「タグファイルを更新する」を選ぶと、タグファイルを作り直すことができる
#メニューの最後の「タグファイルを更新する」を選ぶと、タグファイルを作り直すことができる


;'''構文'''<br>


<source lang="javascript">
<source lang="javascript">

2012年6月22日 (金) 17:40時点における版

ctagsの生成したtagsファイルから検索して単語のメニューを出します。

項目を選ぶとその単語が挿入されます。

kazyさんのCtags.exeでtagsファイルを生成、タグジャンプを行うマクロとあわせてお使いください。


  • インストール
  1. 下のスクリプトをコピーして、MeryのMy Macroフォルダなどに保存
  2. マクロを登録し、Ctrl+Shift+SpaceやCtrl+Qキーなどに設定する
  3. Mery.exeのあるフォルダに[ctags.exe]を置く
  • 初回起動
  1. タグファイルが生成されていないので、どこに生成するか尋ねられる
  2. 指定したディレクトリ以下のソースファイル全てが再帰的にタグファイルに登録される
  3. 「タグファイルの作成が完了しました」とステータスバーに出るまで待つ
  • タグファイルの作成後
  1. 補完したい単語の右にカーソルを置き、マクロを起動する
  2. メニューの項目を選ぶと、その単語が挿入される
  3. メニューの最後の「タグファイルを更新する」を選ぶと、タグファイルを作り直すことができる


// タグファイルから補完.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
}
スポンサーリンク