プロンプトで履歴を使って補完する

昨日作っていた関数を使うときに変数が長くなったり、何度も調べるときいちいち入力しなおすのが面倒なので履歴を使って補完できるようにした。

awful.promptにやりたいことと大体同じことをしてくれる関数があるので、それを使えればいいのだがlocalがついていて外からアクセスできなさそうだったのと、書き換えるのが面倒だったので単にrc.luaにコピーすることにした。

-- 履歴を格納するテーブル

data = {}
data.history = {}

-- 履歴をロードする関数 awful/prompt.luaからのコピー
function history_check_load(id, max)
    if id and id ~= ""
        and not data.history[id] then
        data.history[id] = { max = 50, table = {} }
        
        if max then
                data.history[id].max = max
        end
        
        local f = io.open(id, "r")
            
        -- Read history file
        if f then
                for line in f:lines() do
                    table.insert(data.history[id].table, line)
                    if #data.history[id].table >= data.history[id].max then
                       break
                    end
                end
                f:close()
        end
    end
end

-- data.historyに新しく入力されたデータを追加する関数 awful/prompt.luaからのコピー
-- history_saveは元の関数がやってくれるのでコメントアウト
function history_add(id, command)
    if data.history[id] then
        if command ~= ""
            and command ~= data.history[id].table[#data.history[id].table] then
            table.insert(data.history[id].table, command)

            -- Do not exceed our max_cmd
            if #data.history[id].table > data.history[id].max then
                table.remove(data.history[id].table, 1)
            end

            --history_save(id)
        end
    end
end

-- completion_callbackを返す関数
function completion_callback_using_history (id)
    history_check_load(id)
    f =  function (text, cur_pos, ncomp)
            return awful.completion.generic(text, cur_pos, ncomp, data.history[id].table)
         end
    return f
end

あとは、前回作った関数を以下のように書き換える。

以下に対応する引数あるいは行を追加した。

  • 履歴ファイルの指定
  • 履歴ファイルからの補間関数の作成
  • 実行に履歴を保存
    awful.key({ modkey, "Shift" }, "x",
              function ()
                  awful.prompt.run({ prompt = "variable name: " },
                  mypromptbox[mouse.screen].widget,
                  function (var) 
                      history_add(awful.util.getdir("cache") .. "/history_variable_check", var)
                      awful.util.eval("dbg('" .. var .. "'," .. var .. ")")
                  end,
                  completion_callback_using_history(awful.util.getdir("cache") .. "/history_variable_check"),
                  awful.util.getdir("cache") .. "/history_variable_check")
              end),

これで何度も同じ文字列を入力することはなくなり、だいぶ便利になった。補完にはシェルを利用した関数も用意されているので、うまく利用すればパスの入力の手間を省いたりすることもできそう。

今回はコードをコピーして書いて、二度手間のような動作になってしまったが、実際にはawful.promptを少し書き換えたほうが(localを外せば)もっと簡単できれいにできると
思う。

キーバインドが増えてきて忘れそうなので、awful.keyやawful.promptを書き換えて、
キーバインドのリストを表示できるようにしたい。