(2015.06.05追記)
ふと気が付いたのですがgetStringWidth()
が全く不完全で、á
à
â
ä
などの文字も全角に判定されてしまい表示が崩れますね…
ちょっと調べるとUnicodeの全角/半角の文字の配置は結構バラバラの様で一文字ずつ判定するしかないようです。
WindowsならDrawText
のDT_CALCRECTで矩形範囲取得して計算できそうな気もします(やってない)。
nyagos.getviewwidth()
nyagos 4.0.9_0からnyagos.getviewwidth()
が追加されウィンドウの幅を取得できるようになりました。
というか、プルリクエスト送ってマージしてもらえましたw
ウィンドウの幅が分かることで、計算すれば右プロンプト的なことができますので
右プロンプトとしてMercurial/Gitのブランチ名を表示してみたいと思います。
スクリプト
余計なもの(カレントディレクトリの下からn階層だけ取得する部分)を含んだため、ちょっと長くなってしまいました。
prompt.lua
local _prompt = nyagos.prompt
nyagos.prompt = function(template)
return _prompt(makePrompt())
end
------------------------------------------------
-- PROMPT生成部分
function makePrompt()
local prompt = '$e[30;40;1m[' .. getCompressedPath(3):gsub('\\', '/') .. ']$e[37;1m'
local hgbranch = nyagos.eval('hg branch 2> nul')
local gitbranch = ''
local gitbranch_tmp = nyagos.eval('git branch 2> nul')
if (gitbranch_tmp ~= '') then
gitbranch = gitbranch_tmp:match('%*%s(.[^\n]+)', 1)
end
local rprompt = ''
if (hgbranch ~= '') then
rprompt = rprompt .. '$e[30;40;1m[$e[33;40;1m' .. hgbranch .. '$e[30;40;1m]$e[37;1m'
end
if (gitbranch ~= '') then
rprompt = rprompt .. '$e[30;40;1m[$e[33;40;1m' .. gitbranch .. '$e[30;40;1m]$e[37;1m'
end
local pad = nyagos.getviewwidth() - getStringWidth(removeEscapeSequence(prompt .. rprompt))
for i = 1, pad-1 do
prompt = prompt .. ' '
end
return prompt .. rprompt .. '\n$ '
end
------------------------------------------------
------------------------------------------------
-- 文字列の幅を取得
-- 半角文字:1, 全角文字:2 にカウント
function getStringWidth(src)
local width = 0
for p, c in utf8.codes(src) do
if (0 ~= bit32.band(c, 0x7FFFFF80)) then
if (0xFF61 <= c and c <= 0xFF9F) then
width = width + 1
else
width = width + 2
end
else
width = width + 1
end
end
return width
end
------------------------------------------------
------------------------------------------------
-- エスケープシーケンスを削除
function removeEscapeSequence(src)
-- FIXME : なぜか'$e%[(%d+;)+1m'でマッチしない
return src:gsub('$e%[%d+;%d+;1m',''):gsub('$e%[%d+;1m','')
end
------------------------------------------------
-- 最下層nのディレクトリ名だけ表示する文字列生成
function getCompressedPath(num)
local path = chomp(nyagos.eval('pwd'))
local buff = path
local drive = nil
-- HOME以下の場合
local home = nyagos.getenv("HOME") or nyagos.getenv("USERPROFILE")
if path:find(home)then
drive = '~'
path = path:gsub(home, '~')
buff = path
end
-- 通常のドライブ
if drive == nil then
drive = buff:match('(%w+:)\\')
buff = buff:gsub('%w+:\\', '')
end
-- UNCパス
if drive == nil then
drive = buff:match('(\\\\.-)\\')
buff = buff:gsub('\\\\.-\\', '')
end
local tbl = split(buff, "[\\/]")
if #tbl > num then
buff = "/..."
for i = #tbl - (num - 1), #tbl do
buff = buff .. '/' .. tbl[i]
end
path = drive .. buff
end
return path
end
------------------------------------------------
------------------------------------------------
-- srcの末尾から改行を取り除く
function chomp(src)
return string.gsub(src, "[\r\n]+$", "")
end
------------------------------------------------
------------------------------------------------
-- strをpatで分割しテーブルを返す
-- code from 'http://lua-users.org/wiki/SplitJoin'
function split(str, pat)
local t = {} -- NOTE: use {n = 0} in Lua-5.0
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t, cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
------------------------------------------------
既知の問題点
PROMPTの文字数を数えているため、$P
のようなプロンプト表示時に展開されるような変数を使用すると表示が崩れます。
そのため、自前で展開済みの文字列を表示するよう手間が必要です。