From 61c8b588cd546d700a27c7b665b66ce76c2c87f6 Mon Sep 17 00:00:00 2001 From: Gokcehan Date: Thu, 22 Feb 2018 18:18:30 +0300 Subject: [PATCH] add promptfmt option to configure prompt line Related #50 --- comp.go | 1 + doc.go | 1 + docstring.go | 1 + eval.go | 2 ++ opts.go | 2 ++ ui.go | 49 +++++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/comp.go b/comp.go index 0d079c9..dd41774 100644 --- a/comp.go +++ b/comp.go @@ -81,6 +81,7 @@ var ( "filesep", "ifs", "previewer", + "promptfmt", "shell", "sortby", "timefmt", diff --git a/doc.go b/doc.go index 580219e..db560aa 100644 --- a/doc.go +++ b/doc.go @@ -84,6 +84,7 @@ The following options can be used to customize the behavior of lf: filesep string (default "\n") ifs string (default '') (not exported if empty) previewer string (default '') (not filtered if empty) + promptfmt string (default "\033[32;1m%u@%h\033[0m:\033[34;1m%w/\033[0m\033[1m%f\033[0m") shell string (default 'sh') sortby string (default 'natural') timefmt string (default 'Mon Jan _2 15:04:05 2006') diff --git a/docstring.go b/docstring.go index 51dacf6..53f5442 100644 --- a/docstring.go +++ b/docstring.go @@ -88,6 +88,7 @@ The following options can be used to customize the behavior of lf: filesep string (default "\n") ifs string (default '') (not exported if empty) previewer string (default '') (not filtered if empty) + promptfmt string (default "\033[32;1m%u@%h\033[0m:\033[34;1m%w/\033[0m\033[1m%f\033[0m") shell string (default 'sh') sortby string (default 'natural') timefmt string (default 'Mon Jan _2 15:04:05 2006') diff --git a/eval.go b/eval.go index 932ffe2..1f82a6a 100644 --- a/eval.go +++ b/eval.go @@ -105,6 +105,8 @@ func (e *setExpr) eval(app *app, args []string) { gOpts.ifs = e.val case "previewer": gOpts.previewer = strings.Replace(e.val, "~", gUser.HomeDir, -1) + case "promptfmt": + gOpts.promptfmt = e.val case "shell": gOpts.shell = e.val case "sortby": diff --git a/opts.go b/opts.go index ecee2c5..bdf356a 100644 --- a/opts.go +++ b/opts.go @@ -17,6 +17,7 @@ var gOpts struct { filesep string ifs string previewer string + promptfmt string shell string sortby string timefmt string @@ -40,6 +41,7 @@ func init() { gOpts.scrolloff = 0 gOpts.tabstop = 8 gOpts.filesep = "\n" + gOpts.promptfmt = "\033[32;1m%u@%h\033[0m:\033[34;1m%w/\033[0m\033[1m%f\033[0m" gOpts.shell = gDefaultShell gOpts.sortby = "natural" gOpts.timefmt = time.ANSIC diff --git a/ui.go b/ui.go index f25dc1d..1e109c8 100644 --- a/ui.go +++ b/ui.go @@ -180,6 +180,34 @@ func applyAnsiCodes(s string, fg, bg termbox.Attribute) (termbox.Attribute, term return fg, bg } +func printLength(s string) int { + ind := 0 + off := 0 + for i := 0; i < len(s); i++ { + r, w := utf8.DecodeRuneInString(s[i:]) + + if r == gEscapeCode && i+1 < len(s) && s[i+1] == '[' { + j := strings.IndexByte(s[i:min(len(s), i+32)], 'm') + if j == -1 { + continue + } + + i += j + continue + } + + i += w - 1 + + if r == '\t' { + ind += gOpts.tabstop - (ind-off)%gOpts.tabstop + } else { + ind += runewidth.RuneWidth(r) + } + } + + return ind +} + func (win *win) print(x, y int, fg, bg termbox.Attribute, s string) (termbox.Attribute, termbox.Attribute) { off := x for i := 0; i < len(s); i++ { @@ -520,29 +548,34 @@ func (ui *ui) drawPromptLine(nav *nav) { pwd := strings.Replace(dir.path, gUser.HomeDir, "~", -1) pwd = filepath.Clean(pwd) - var base string + var fname string curr, err := nav.currFile() if err == nil { - base = filepath.Base(curr.path) + fname = filepath.Base(curr.path) } - if len(gUser.Username)+len(gHostname)+len(pwd)+len(base)+3 > ui.promptWin.w { + var prompt string + + prompt = strings.Replace(gOpts.promptfmt, "%u", gUser.Username, -1) + prompt = strings.Replace(prompt, "%h", gHostname, -1) + prompt = strings.Replace(prompt, "%f", fname, -1) + + if printLength(strings.Replace(prompt, "%w", pwd, -1)) > ui.promptWin.w { sep := string(filepath.Separator) names := strings.Split(pwd, sep) for i, _ := range names { r, _ := utf8.DecodeRuneInString(names[i]) names[i] = string(r) - if len(gUser.Username)+len(gHostname)+len(strings.Join(names, sep))+len(base)+3 <= ui.promptWin.w { + if printLength(strings.Replace(prompt, "%w", strings.Join(names, sep), -1)) <= ui.promptWin.w { break } } pwd = strings.Join(names, sep) } - ui.promptWin.printf(0, 0, termbox.AttrBold|termbox.ColorGreen, bg, "%s@%s", gUser.Username, gHostname) - ui.promptWin.printf(len(gUser.Username)+len(gHostname)+1, 0, fg, bg, ":") - ui.promptWin.printf(len(gUser.Username)+len(gHostname)+2, 0, termbox.AttrBold|termbox.ColorBlue, bg, "%s/", pwd) - ui.promptWin.printf(len(gUser.Username)+len(gHostname)+len(pwd)+3, 0, termbox.AttrBold|fg, bg, "%s", base) + prompt = strings.Replace(prompt, "%w", pwd, -1) + + ui.promptWin.print(0, 0, fg, bg, prompt) } func (ui *ui) drawStatLine(nav *nav) {