From 67a4ebd25e46b0c62fffd7c4be5a4739fea48fc2 Mon Sep 17 00:00:00 2001 From: bison3 Date: Tue, 25 Mar 2025 19:09:46 -0400 Subject: [PATCH 1/8] First draft of dynamic keybindings display --- internal/config/settings.go | 1 + internal/display/infowindow.go | 28 ++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/internal/config/settings.go b/internal/config/settings.go index 14e5f18b7a..7cfcf64986 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -65,6 +65,7 @@ var defaultCommonSettings = map[string]interface{}{ "fastdirty": false, "fileformat": defaultFileFormat(), "filetype": "unknown", + "helpbindings": "Ctrl-q,Ctrl-s,Ctrl-o,Ctrl-g,Ctrl-e,Ctrl-k,Ctrl-f,Ctrl-z,Ctrl-y,Ctrl-a,Ctrl-d,Ctrl-t", "hlsearch": false, "hltaberrors": false, "hltrailingws": false, diff --git a/internal/display/infowindow.go b/internal/display/infowindow.go index 878d40ff3e..9369d32ab1 100644 --- a/internal/display/infowindow.go +++ b/internal/display/infowindow.go @@ -1,6 +1,8 @@ package display import ( + "strings" + runewidth "github.com/mattn/go-runewidth" "github.com/micro-editor/tcell/v2" "github.com/zyedidia/micro/v2/internal/buffer" @@ -178,10 +180,8 @@ func (i *InfoWindow) displayBuffer() { } } -var keydisplay = []string{"^Q Quit, ^S Save, ^O Open, ^G Help, ^E Command Bar, ^K Cut Line", "^F Find, ^Z Undo, ^Y Redo, ^A Select All, ^D Duplicate Line, ^T New Tab"} - func (i *InfoWindow) displayKeyMenu() { - // TODO: maybe make this based on the actual keybindings + keydisplay := getKeyDisplay() for y := 0; y < len(keydisplay); y++ { for x := 0; x < i.Width; x++ { @@ -194,6 +194,26 @@ func (i *InfoWindow) displayKeyMenu() { } } +func getKeyDisplay() []string { + keybinds := strings.Split(config.GlobalSettings["helpbindings"].(string), ",") + mid := len(keybinds) / 2 + + return []string{ + getKeyBinds(keybinds[:mid]), + getKeyBinds(keybinds[mid:]), + } +} + +func getKeyBinds(binds []string) string { + var sb strings.Builder + + for _, b := range binds { + sb.WriteString(b + ": " + config.Bindings["buffer"][b] + ", ") + } + + return strings.TrimSuffix(sb.String(), ", ") +} + func (i *InfoWindow) totalSize() int { sum := 0 for _, n := range i.Suggestions { @@ -267,7 +287,7 @@ func (i *InfoWindow) Display() { } keymenuOffset := 0 if config.GetGlobalOption("keymenu").(bool) { - keymenuOffset = len(keydisplay) + keymenuOffset = len(getKeyDisplay()) } draw := func(r rune, s tcell.Style) { From 56def76a34a5b8f56e0a8735abfeca256c1552aa Mon Sep 17 00:00:00 2001 From: bison3 Date: Tue, 25 Mar 2025 19:18:21 -0400 Subject: [PATCH 2/8] None if keybind doesn't exist --- internal/display/infowindow.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/display/infowindow.go b/internal/display/infowindow.go index 9369d32ab1..a1dc411ea2 100644 --- a/internal/display/infowindow.go +++ b/internal/display/infowindow.go @@ -208,7 +208,13 @@ func getKeyBinds(binds []string) string { var sb strings.Builder for _, b := range binds { - sb.WriteString(b + ": " + config.Bindings["buffer"][b] + ", ") + action, exists := config.Bindings["buffer"][b] + + if !exists { + action = "None" + } + + sb.WriteString(b + ": " + action + ", ") } return strings.TrimSuffix(sb.String(), ", ") From 4e3a34fbde12954f52415a0ba7893920ac5e5f3d Mon Sep 17 00:00:00 2001 From: bison3 Date: Tue, 25 Mar 2025 23:20:42 -0400 Subject: [PATCH 3/8] Draft of what it would like to specify actions instead of keys --- internal/config/settings.go | 2 +- internal/display/infowindow.go | 33 ++++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/internal/config/settings.go b/internal/config/settings.go index 7cfcf64986..9758af45f9 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -65,7 +65,7 @@ var defaultCommonSettings = map[string]interface{}{ "fastdirty": false, "fileformat": defaultFileFormat(), "filetype": "unknown", - "helpbindings": "Ctrl-q,Ctrl-s,Ctrl-o,Ctrl-g,Ctrl-e,Ctrl-k,Ctrl-f,Ctrl-z,Ctrl-y,Ctrl-a,Ctrl-d,Ctrl-t", + "helpactions": "Quit,Save,OpenFile,ToggleHelp,CommandMode,CutLine,Find,Undo,Redo,SelectAll,Duplicate,AddTab", "hlsearch": false, "hltaberrors": false, "hltrailingws": false, diff --git a/internal/display/infowindow.go b/internal/display/infowindow.go index a1dc411ea2..c67898cb29 100644 --- a/internal/display/infowindow.go +++ b/internal/display/infowindow.go @@ -1,6 +1,7 @@ package display import ( + "slices" "strings" runewidth "github.com/mattn/go-runewidth" @@ -195,7 +196,7 @@ func (i *InfoWindow) displayKeyMenu() { } func getKeyDisplay() []string { - keybinds := strings.Split(config.GlobalSettings["helpbindings"].(string), ",") + keybinds := strings.Split(config.GlobalSettings["helpactions"].(string), ",") mid := len(keybinds) / 2 return []string{ @@ -205,19 +206,37 @@ func getKeyDisplay() []string { } func getKeyBinds(binds []string) string { + var keys = make(map[string][]string, 0) + + for k, v := range config.Bindings["buffer"] { + for _, sub := range binds { + if strings.Contains(v, sub) { + keys[sub] = append(keys[sub], k) + } + } + } + var sb strings.Builder - for _, b := range binds { - action, exists := config.Bindings["buffer"][b] + for i, bind := range binds { + slices.Sort(keys[bind]) - if !exists { - action = "None" + sb.WriteString(bind + ": ") + + for j, key := range keys[bind] { + sb.WriteString(key) + + if len(keys[bind])-1 != j { + sb.WriteString(", ") + } } - sb.WriteString(b + ": " + action + ", ") + if len(binds)-1 != i { + sb.WriteString(" | ") + } } - return strings.TrimSuffix(sb.String(), ", ") + return sb.String() } func (i *InfoWindow) totalSize() int { From 1618dd9afce777d991b6271d8189ad5d544eb779 Mon Sep 17 00:00:00 2001 From: bison3 Date: Tue, 25 Mar 2025 23:26:37 -0400 Subject: [PATCH 4/8] Using Cut instead of CutLine for default value --- internal/config/settings.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/config/settings.go b/internal/config/settings.go index 9758af45f9..301d9ab545 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -65,7 +65,7 @@ var defaultCommonSettings = map[string]interface{}{ "fastdirty": false, "fileformat": defaultFileFormat(), "filetype": "unknown", - "helpactions": "Quit,Save,OpenFile,ToggleHelp,CommandMode,CutLine,Find,Undo,Redo,SelectAll,Duplicate,AddTab", + "helpactions": "Quit,Save,OpenFile,ToggleHelp,CommandMode,Cut,Find,Undo,Redo,SelectAll,Duplicate,AddTab", "hlsearch": false, "hltaberrors": false, "hltrailingws": false, From 022a1e255835dade389fe44d1b62c645d2fc9cfe Mon Sep 17 00:00:00 2001 From: bison3 Date: Sat, 29 Mar 2025 11:32:02 -0400 Subject: [PATCH 5/8] Using a regex to split the bindings on the different possible delimiters (&, |, ,) to avoid matching similarily named actions --- internal/display/infowindow.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/internal/display/infowindow.go b/internal/display/infowindow.go index c67898cb29..fd0305221a 100644 --- a/internal/display/infowindow.go +++ b/internal/display/infowindow.go @@ -1,6 +1,7 @@ package display import ( + "regexp" "slices" "strings" @@ -205,33 +206,34 @@ func getKeyDisplay() []string { } } -func getKeyBinds(binds []string) string { - var keys = make(map[string][]string, 0) +func getKeyBinds(actions []string) string { + keys := make(map[string][]string, 0) + re := regexp.MustCompile(`[&|,]+`) - for k, v := range config.Bindings["buffer"] { - for _, sub := range binds { - if strings.Contains(v, sub) { - keys[sub] = append(keys[sub], k) + for key, binding := range config.Bindings["buffer"] { + for _, action := range actions { + if slices.Index(re.Split(binding, -1), action) != -1 { + keys[action] = append(keys[action], key) } } } var sb strings.Builder - for i, bind := range binds { - slices.Sort(keys[bind]) + for i, action := range actions { + slices.Sort(keys[action]) - sb.WriteString(bind + ": ") + sb.WriteString(action + ": ") - for j, key := range keys[bind] { + for j, key := range keys[action] { sb.WriteString(key) - if len(keys[bind])-1 != j { + if len(keys[action])-1 != j { sb.WriteString(", ") } } - if len(binds)-1 != i { + if len(actions)-1 != i { sb.WriteString(" | ") } } From 6f483fa11857ab103914df0079965061765bc70a Mon Sep 17 00:00:00 2001 From: bison3 Date: Sat, 29 Mar 2025 12:06:20 -0400 Subject: [PATCH 6/8] Ctrl keys now displayed with ^ instead of whole Ctrl-, to take less space --- internal/display/infowindow.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/display/infowindow.go b/internal/display/infowindow.go index fd0305221a..e71b482094 100644 --- a/internal/display/infowindow.go +++ b/internal/display/infowindow.go @@ -213,7 +213,13 @@ func getKeyBinds(actions []string) string { for key, binding := range config.Bindings["buffer"] { for _, action := range actions { if slices.Index(re.Split(binding, -1), action) != -1 { - keys[action] = append(keys[action], key) + k := key + + if strings.Contains(key, "Ctrl-") { + k = "^" + key[len(key)-1:] + } + + keys[action] = append(keys[action], k) } } } @@ -223,6 +229,7 @@ func getKeyBinds(actions []string) string { for i, action := range actions { slices.Sort(keys[action]) + // TODO Those hard coded keys could also be editable in the settings file - making it a bit more customizable sb.WriteString(action + ": ") for j, key := range keys[action] { @@ -234,7 +241,7 @@ func getKeyBinds(actions []string) string { } if len(actions)-1 != i { - sb.WriteString(" | ") + sb.WriteString(" - ") } } From d1502fba59b46a1841b1d048207ff8234b5f4c47 Mon Sep 17 00:00:00 2001 From: bison3 Date: Sun, 30 Mar 2025 16:43:20 -0400 Subject: [PATCH 7/8] Now only generating the keydisplay once instead of everytime the display is called --- internal/display/infowindow.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/internal/display/infowindow.go b/internal/display/infowindow.go index e71b482094..b95129ca76 100644 --- a/internal/display/infowindow.go +++ b/internal/display/infowindow.go @@ -18,7 +18,8 @@ type InfoWindow struct { *info.InfoBuf *View - hscroll int + keydisplay []string + hscroll int } func (i *InfoWindow) errStyle() tcell.Style { @@ -48,6 +49,8 @@ func NewInfoWindow(b *info.InfoBuf) *InfoWindow { iw.InfoBuf = b iw.View = new(View) + iw.keydisplay = getKeyDisplay() + iw.Width, iw.Y = screen.Screen.Size() iw.Y-- @@ -183,14 +186,12 @@ func (i *InfoWindow) displayBuffer() { } func (i *InfoWindow) displayKeyMenu() { - keydisplay := getKeyDisplay() - - for y := 0; y < len(keydisplay); y++ { + for y := 0; y < len(i.keydisplay); y++ { for x := 0; x < i.Width; x++ { - if x < len(keydisplay[y]) { - screen.SetContent(x, i.Y-len(keydisplay)+y, rune(keydisplay[y][x]), nil, i.defStyle()) + if x < len(i.keydisplay[y]) { + screen.SetContent(x, i.Y-len(i.keydisplay)+y, rune(i.keydisplay[y][x]), nil, i.defStyle()) } else { - screen.SetContent(x, i.Y-len(keydisplay)+y, ' ', nil, i.defStyle()) + screen.SetContent(x, i.Y-len(i.keydisplay)+y, ' ', nil, i.defStyle()) } } } @@ -229,7 +230,7 @@ func getKeyBinds(actions []string) string { for i, action := range actions { slices.Sort(keys[action]) - // TODO Those hard coded keys could also be editable in the settings file - making it a bit more customizable + // TODO Those hardcoded keys could also be editable in the settings file sb.WriteString(action + ": ") for j, key := range keys[action] { @@ -241,7 +242,7 @@ func getKeyBinds(actions []string) string { } if len(actions)-1 != i { - sb.WriteString(" - ") + sb.WriteString(" | ") } } @@ -321,7 +322,7 @@ func (i *InfoWindow) Display() { } keymenuOffset := 0 if config.GetGlobalOption("keymenu").(bool) { - keymenuOffset = len(getKeyDisplay()) + keymenuOffset = len(i.keydisplay) } draw := func(r rune, s tcell.Style) { From 73c0fbabd6583db914643f991951651d5d46a50f Mon Sep 17 00:00:00 2001 From: bison3 Date: Sun, 30 Mar 2025 16:44:11 -0400 Subject: [PATCH 8/8] alphabetical order --- internal/display/infowindow.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/display/infowindow.go b/internal/display/infowindow.go index b95129ca76..451224d977 100644 --- a/internal/display/infowindow.go +++ b/internal/display/infowindow.go @@ -18,8 +18,8 @@ type InfoWindow struct { *info.InfoBuf *View - keydisplay []string hscroll int + keydisplay []string } func (i *InfoWindow) errStyle() tcell.Style {