~rjarry/aerc-devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
3 3

[PATCH aerc v2 1/2] binds: refactor parser to be more tolerant

Details
Message ID
<20240220002049.235278-3-tim@timculverhouse.com>
DKIM signature
pass
Download raw message
Patch: +64 -272
Refactor the bind parser to construct arbitrary modified keys instead of
only relying on built in maps. Add additional tests to cover edge cases.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
---
v2: introduce this entire patch

 config/binds.go      | 141 +++++++++++----------------------
 config/binds_test.go |  13 +++-
 doc/aerc-binds.5.scd | 182 ++-----------------------------------------
 3 files changed, 64 insertions(+), 272 deletions(-)

diff --git a/config/binds.go b/config/binds.go
index 95fa8c7d7e1f..3ddc25786022 100644
--- a/config/binds.go
+++ b/config/binds.go
@@ -10,6 +10,7 @@ import (
	"regexp"
	"strings"
	"unicode"
	"unicode/utf8"

	"git.sr.ht/~rjarry/aerc/lib/log"
	"git.sr.ht/~rockorager/vaxis"
@@ -474,10 +475,8 @@ func FormatKeyStrokes(keystrokes []KeyStroke) string {
		for name, ks := range keyNames {
			if ks.Modifiers == stroke.Modifiers && ks.Key == stroke.Key {
				switch name {
				case "cr", "c-m":
				case "cr":
					s = "<enter>"
				case "c-i":
					s = "<tab>"
				case "space":
					s = " "
				case "semicolon":
@@ -485,9 +484,21 @@ func FormatKeyStrokes(keystrokes []KeyStroke) string {
				default:
					s = fmt.Sprintf("<%s>", name)
				}
				// remove any modifiers this named key comes
				// with so we format properly
				stroke.Modifiers &^= ks.Modifiers
				break
			}
		}
		if stroke.Modifiers&vaxis.ModCtrl > 0 {
			sb.WriteString("c-")
		}
		if stroke.Modifiers&vaxis.ModAlt > 0 {
			sb.WriteString("a-")
		}
		if stroke.Modifiers&vaxis.ModShift > 0 {
			sb.WriteString("s-")
		}
		if s == "" && stroke.Key < unicode.MaxRune {
			s = string(stroke.Key)
		}
@@ -512,37 +523,21 @@ var keyNames = map[string]KeyStroke{
	"space":     {vaxis.ModifierMask(0), ' '},
	"semicolon": {vaxis.ModifierMask(0), ';'},
	"enter":     {vaxis.ModifierMask(0), vaxis.KeyEnter},
	"c-enter":   {vaxis.ModCtrl, vaxis.KeyEnter},
	"a-enter":   {vaxis.ModAlt, vaxis.KeyEnter},
	"up":        {vaxis.ModifierMask(0), vaxis.KeyUp},
	"c-up":      {vaxis.ModCtrl, vaxis.KeyUp},
	"a-up":      {vaxis.ModAlt, vaxis.KeyUp},
	"down":      {vaxis.ModifierMask(0), vaxis.KeyDown},
	"c-down":    {vaxis.ModCtrl, vaxis.KeyDown},
	"a-down":    {vaxis.ModAlt, vaxis.KeyDown},
	"right":     {vaxis.ModifierMask(0), vaxis.KeyRight},
	"c-right":   {vaxis.ModCtrl, vaxis.KeyRight},
	"a-right":   {vaxis.ModAlt, vaxis.KeyRight},
	"left":      {vaxis.ModifierMask(0), vaxis.KeyLeft},
	"c-left":    {vaxis.ModCtrl, vaxis.KeyLeft},
	"a-left":    {vaxis.ModAlt, vaxis.KeyLeft},
	"upleft":    {vaxis.ModifierMask(0), vaxis.KeyUpLeft},
	"upright":   {vaxis.ModifierMask(0), vaxis.KeyUpRight},
	"downleft":  {vaxis.ModifierMask(0), vaxis.KeyDownLeft},
	"downright": {vaxis.ModifierMask(0), vaxis.KeyDownRight},
	"center":    {vaxis.ModifierMask(0), vaxis.KeyCenter},
	"pgup":      {vaxis.ModifierMask(0), vaxis.KeyPgUp},
	"c-pgup":    {vaxis.ModCtrl, vaxis.KeyPgUp},
	"a-pgup":    {vaxis.ModAlt, vaxis.KeyPgUp},
	"pgdn":      {vaxis.ModifierMask(0), vaxis.KeyPgDown},
	"c-pgdn":    {vaxis.ModCtrl, vaxis.KeyPgDown},
	"a-pgdn":    {vaxis.ModAlt, vaxis.KeyPgDown},
	"home":      {vaxis.ModifierMask(0), vaxis.KeyHome},
	"end":       {vaxis.ModifierMask(0), vaxis.KeyEnd},
	"insert":    {vaxis.ModifierMask(0), vaxis.KeyInsert},
	"delete":    {vaxis.ModifierMask(0), vaxis.KeyDelete},
	"c-delete":  {vaxis.ModCtrl, vaxis.KeyDelete},
	"a-delete":  {vaxis.ModAlt, vaxis.KeyDelete},
	"backspace": {vaxis.ModifierMask(0), vaxis.KeyBackspace},
	// "help":      {vaxis.ModifierMask(0), vaxis.KeyHelp},
	"exit":    {vaxis.ModifierMask(0), vaxis.KeyExit},
@@ -614,80 +609,6 @@ var keyNames = map[string]KeyStroke{
	"f61":     {vaxis.ModifierMask(0), vaxis.KeyF61},
	"f62":     {vaxis.ModifierMask(0), vaxis.KeyF62},
	"f63":     {vaxis.ModifierMask(0), vaxis.KeyF63},
	"c-space": {vaxis.ModCtrl, ' '},
	"c-a":     {vaxis.ModCtrl, 'a'},
	"c-b":     {vaxis.ModCtrl, 'b'},
	"c-c":     {vaxis.ModCtrl, 'c'},
	"c-d":     {vaxis.ModCtrl, 'd'},
	"c-e":     {vaxis.ModCtrl, 'e'},
	"c-f":     {vaxis.ModCtrl, 'f'},
	"c-g":     {vaxis.ModCtrl, 'g'},
	"c-h":     {vaxis.ModCtrl, 'h'},
	"c-i":     {vaxis.ModCtrl, 'i'},
	"c-j":     {vaxis.ModCtrl, 'j'},
	"c-k":     {vaxis.ModCtrl, 'k'},
	"c-l":     {vaxis.ModCtrl, 'l'},
	"c-m":     {vaxis.ModCtrl, 'm'},
	"c-n":     {vaxis.ModCtrl, 'n'},
	"c-o":     {vaxis.ModCtrl, 'o'},
	"c-p":     {vaxis.ModCtrl, 'p'},
	"c-q":     {vaxis.ModCtrl, 'q'},
	"c-r":     {vaxis.ModCtrl, 'r'},
	"c-s":     {vaxis.ModCtrl, 's'},
	"c-t":     {vaxis.ModCtrl, 't'},
	"c-u":     {vaxis.ModCtrl, 'u'},
	"c-v":     {vaxis.ModCtrl, 'v'},
	"c-w":     {vaxis.ModCtrl, 'w'},
	"c-x":     {vaxis.ModCtrl, 'x'},
	"c-y":     {vaxis.ModCtrl, 'y'},
	"c-z":     {vaxis.ModCtrl, 'z'},
	"c-]":     {vaxis.ModCtrl, ']'},
	"c-\\":    {vaxis.ModCtrl, '\\'},
	"c-[":     {vaxis.ModCtrl, '['},
	"c-^":     {vaxis.ModCtrl, '^'},
	"c-_":     {vaxis.ModCtrl, '_'},
	"a-space": {vaxis.ModAlt, ' '},
	"a-0":     {vaxis.ModAlt, '0'},
	"a-1":     {vaxis.ModAlt, '1'},
	"a-2":     {vaxis.ModAlt, '2'},
	"a-3":     {vaxis.ModAlt, '3'},
	"a-4":     {vaxis.ModAlt, '4'},
	"a-5":     {vaxis.ModAlt, '5'},
	"a-6":     {vaxis.ModAlt, '6'},
	"a-7":     {vaxis.ModAlt, '7'},
	"a-8":     {vaxis.ModAlt, '8'},
	"a-9":     {vaxis.ModAlt, '9'},
	"a-a":     {vaxis.ModAlt, 'a'},
	"a-b":     {vaxis.ModAlt, 'b'},
	"a-c":     {vaxis.ModAlt, 'c'},
	"a-d":     {vaxis.ModAlt, 'd'},
	"a-e":     {vaxis.ModAlt, 'e'},
	"a-f":     {vaxis.ModAlt, 'f'},
	"a-g":     {vaxis.ModAlt, 'g'},
	"a-h":     {vaxis.ModAlt, 'h'},
	"a-i":     {vaxis.ModAlt, 'i'},
	"a-j":     {vaxis.ModAlt, 'j'},
	"a-k":     {vaxis.ModAlt, 'k'},
	"a-l":     {vaxis.ModAlt, 'l'},
	"a-m":     {vaxis.ModAlt, 'm'},
	"a-n":     {vaxis.ModAlt, 'n'},
	"a-o":     {vaxis.ModAlt, 'o'},
	"a-p":     {vaxis.ModAlt, 'p'},
	"a-q":     {vaxis.ModAlt, 'q'},
	"a-r":     {vaxis.ModAlt, 'r'},
	"a-s":     {vaxis.ModAlt, 's'},
	"a-t":     {vaxis.ModAlt, 't'},
	"a-u":     {vaxis.ModAlt, 'u'},
	"a-v":     {vaxis.ModAlt, 'v'},
	"a-w":     {vaxis.ModAlt, 'w'},
	"a-x":     {vaxis.ModAlt, 'x'},
	"a-y":     {vaxis.ModAlt, 'y'},
	"a-z":     {vaxis.ModAlt, 'z'},
	"a-]":     {vaxis.ModAlt, ']'},
	"a-\\":    {vaxis.ModAlt, '\\'},
	"a-[":     {vaxis.ModAlt, '['},
	"a-^":     {vaxis.ModAlt, '^'},
	"a-_":     {vaxis.ModAlt, '_'},
	"nul":     {vaxis.ModCtrl, ' '},
	"soh":     {vaxis.ModCtrl, 'a'},
	"stx":     {vaxis.ModCtrl, 'b'},
@@ -747,10 +668,36 @@ func ParseKeyStrokes(keystrokes string) ([]KeyStroke, error) {
				return nil, errors.New("Expected a key name")
			}
			name = name[:len(name)-1]
			if key, ok := keyNames[strings.ToLower(name)]; ok {
				strokes = append(strokes, key)
			} else {
				return nil, fmt.Errorf("Unknown key '%s'", name)
			args := strings.Split(name, "-")
			// check if the last char was a '-' and we'll add it
			// back. We check for "--" in case it was an invalid
			// keystroke (ie <C->)
			if strings.HasSuffix(name, "--") {
				args = append(args, "-")
			}
			ks := KeyStroke{}
			for i, arg := range args {
				if i == len(args)-1 {
					key, ok := keyNames[strings.ToLower(arg)]
					if !ok {
						r, n := utf8.DecodeRuneInString(arg)
						if n != len(arg) {
							return nil, fmt.Errorf("Unknown key '%s'", name)
						}
						key = KeyStroke{Key: r}
					}
					ks.Key = key.Key
					ks.Modifiers |= key.Modifiers
					strokes = append(strokes, ks)
				}
				switch strings.ToLower(arg) {
				case "s", "S":
					ks.Modifiers |= vaxis.ModShift
				case "a", "A":
					ks.Modifiers |= vaxis.ModAlt
				case "c", "C":
					ks.Modifiers |= vaxis.ModCtrl
				}
			}
		case '>':
			return nil, errors.New("Found '>' without '<'")
diff --git a/config/binds_test.go b/config/binds_test.go
index a92cf22fda77..7d4cd7792811 100644
--- a/config/binds_test.go
+++ b/config/binds_test.go
@@ -13,7 +13,10 @@ func TestGetBinding(t *testing.T) {

	bindings := NewKeyBindings()
	add := func(binding, cmd string) {
		b, _ := ParseBinding(binding, cmd, "")
		b, err := ParseBinding(binding, cmd, "")
		if err != nil {
			t.Fatal(err)
		}
		bindings.Add(b)
	}

@@ -58,6 +61,8 @@ func TestGetBinding(t *testing.T) {
	add("<C-Down>", ":next")
	add("<C-PgUp>", ":prev")
	add("<C-Enter>", ":open")
	add("<C-->", ":open")
	add("<S-up>", ":open")
	test([]KeyStroke{
		{vaxis.ModCtrl, 'a'},
	}, BINDING_FOUND, "c-a")
@@ -73,4 +78,10 @@ func TestGetBinding(t *testing.T) {
	test([]KeyStroke{
		{vaxis.ModCtrl, vaxis.KeyEnter},
	}, BINDING_FOUND, ":open")
	test([]KeyStroke{
		{vaxis.ModCtrl, '-'},
	}, BINDING_FOUND, ":open")
	test([]KeyStroke{
		{vaxis.ModShift, vaxis.KeyUp},
	}, BINDING_FOUND, ":open")
}
diff --git a/doc/aerc-binds.5.scd b/doc/aerc-binds.5.scd
index a46b6427cd0b..de8f436c19f0 100644
--- a/doc/aerc-binds.5.scd
+++ b/doc/aerc-binds.5.scd
@@ -147,8 +147,14 @@ available in each binding context:
# SUPPORTED KEYS

In addition to letters and some characters (e.g. *a*, *RR*, *gu*, *?*, *!*,
etc.), special keys may be specified in *<angle brackets>*. The following
special keys are supported:
etc.), special keys may be specified in *<angle brackets>*. The syntax for
modified or special keys is:

	<C-A-S-key>

Where C is control, A is alt, S is shift, and key is the named key or character.

Valid key names are:

[[ *Name*
:- *Description*
@@ -162,40 +168,16 @@ special keys are supported:
:  Enter
|  *<up>*
:  Up arrow
|  *<c-up>*
:  Ctrl+Up
|  *<a-up>*
:  Alt+Up
|  *<down>*
:  Down arrow
|  *<c-down>*
:  Ctrl+Down
|  *<a-down>*
:  Alt+Down
|  *<right>*
:  Right arrow
|  *<c-right>*
:  Ctrl+Right
|  *<a-right>*
:  Alt+Right
|  *<left>*
:  Left arrow
|  *<c-left>*
:  Ctrl+Left
|  *<a-left>*
:  Alt+Left
|  *<pgup>*
:  Page Up
|  *<c-pgup>*
:  Ctrl+PageUp
|  *<a-pgup>*
:  Alt+PageUp
|  *<pgdn>*
:  Page Down
|  *<c-pgdn>*
:  Ctrl+PageDn
|  *<a-pgdn>*
:  Alt+PageDn
|  *<home>*
:  Home
|  *<end>*
@@ -204,10 +186,6 @@ special keys are supported:
:  Insert
|  *<delete>*
:  Delete
|  *<c-delete>*
:  Ctrl+Delete
|  *<a-delete>*
:  Alt+Delete
|  *<backspace>*
:  Backspace
|  *<exit>*
@@ -222,150 +200,6 @@ special keys are supported:
:  Shift+Tab
|  *<esc>*
:  Escape
|  *<c-space>*
:  Ctrl+Space
|  *<a-space>*
:  Alt+Space
|  *<a-0>*
:  Alt+0
|  *<a-1>*
:  Alt+1
|  *<a-2>*
:  Alt+2
|  *<a-3>*
:  Alt+3
|  *<a-4>*
:  Alt+4
|  *<a-5>*
:  Alt+5
|  *<a-6>*
:  Alt+6
|  *<a-7>*
:  Alt+7
|  *<a-8>*
:  Alt+8
|  *<a-9>*
:  Alt+9
|  *<c-a>*
:  Ctrl+a
|  *<a-a>*
:  Alt+a
|  *<c-b>*
:  Ctrl+b
|  *<a-b>*
:  Alt+b
|  *<c-c>*
:  Ctrl+c
|  *<a-c>*
:  Alt+c
|  *<c-d>*
:  Ctrl+d
|  *<a-d>*
:  Alt+d
|  *<c-e>*
:  Ctrl+e
|  *<a-e>*
:  Alt+e
|  *<c-f>*
:  Ctrl+f
|  *<a-f>*
:  Alt+f
|  *<c-g>*
:  Ctrl+g
|  *<a-g>*
:  Alt+g
|  *<c-h>*
:  Ctrl+h
|  *<a-h>*
:  Alt+h
|  *<c-i>*
:  Ctrl+i
|  *<a-i>*
:  Alt+i
|  *<c-j>*
:  Ctrl+j
|  *<a-j>*
:  Alt+j
|  *<c-k>*
:  Ctrl+k
|  *<a-k>*
:  Alt+k
|  *<c-l>*
:  Ctrl+l
|  *<a-l>*
:  Alt+l
|  *<c-m>*
:  Ctrl+m
|  *<a-m>*
:  Alt+m
|  *<c-n>*
:  Ctrl+n
|  *<a-n>*
:  Alt+n
|  *<c-o>*
:  Ctrl+o
|  *<a-o>*
:  Alt+o
|  *<c-p>*
:  Ctrl+p
|  *<a-p>*
:  Alt+p
|  *<c-q>*
:  Ctrl+q
|  *<a-q>*
:  Alt+q
|  *<c-r>*
:  Ctrl+r
|  *<a-r>*
:  Alt+r
|  *<c-s>*
:  Ctrl+s
|  *<a-s>*
:  Alt+s
|  *<c-t>*
:  Ctrl+t
|  *<a-t>*
:  Alt+t
|  *<c-u>*
:  Ctrl+u
|  *<a-u>*
:  Alt+u
|  *<c-v>*
:  Ctrl+v
|  *<a-v>*
:  Alt+v
|  *<c-w>*
:  Ctrl+w
|  *<a-w>*
:  Alt+w
|  *<c-x>*
:  Ctrl+x
|  *<a-x>*
:  Alt+x
|  *<c-y>*
:  Ctrl+y
|  *<a-y>*
:  Alt+y
|  *<c-z>*
:  Ctrl+z
|  *<a-z>*
:  Alt+z
|  *<c-]>*
:  Ctrl+]
|  *<a-]>*
:  Alt+]
|  *<c-[>*
:  Ctrl+[
|  *<a-[>*
:  Alt+[
|  *<c-^>*
:  Ctrl+^
|  *<a-^>*
:  Alt+^
|  *<c-\_>*
:  Ctrl+\_
|  *<a-\_>*
:  Alt+\_

# SEE ALSO

-- 
2.43.2

[PATCH aerc v2 2/2] ui: enable CSIu key encoding

Details
Message ID
<20240220002049.235278-4-tim@timculverhouse.com>
In-Reply-To
<20240220002049.235278-3-tim@timculverhouse.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +8 -2
Enable CSIu key encoding protocol when support is detected. This will
enable keybinds which traditionally have been unavailable due to
conflicting with other keys (C-i, C-m, C-[, etc).

Remove numlock and capslock from all keypresses to prevent interfering
with key matching.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
---
v2: remove numlock and capslock from modifiers (Robin)

 lib/ui/ui.go | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/ui/ui.go b/lib/ui/ui.go
index d63ebf36c4ca..3b1050b544da 100644
--- a/lib/ui/ui.go
+++ b/lib/ui/ui.go
@@ -49,8 +49,7 @@ var state struct {

func Initialize(content DrawableInteractive) error {
	opts := vaxis.Options{
		DisableMouse:         !config.Ui.MouseEnabled,
		DisableKittyKeyboard: true,
		DisableMouse: !config.Ui.MouseEnabled,
	}
	vx, err := vaxis.New(opts)
	if err != nil {
@@ -144,6 +143,13 @@ func HandleEvent(event vaxis.Event) {
	case vaxis.Redraw:
		Invalidate()
	default:
		// We never care about num or caps lock. Remove them so it
		// doesn't interefere with key matching
		if key, ok := event.(vaxis.Key); ok {
			key.Modifiers &^= vaxis.ModCapsLock
			key.Modifiers &^= vaxis.ModNumLock
			event = key
		}
		// if we have a popover, and it can handle the event, it does so
		if state.popover == nil || !state.popover.Event(event) {
			// otherwise, we send the event to the main content
-- 
2.43.2

[aerc/patches] build success

builds.sr.ht <builds@sr.ht>
Details
Message ID
<CZ9H8E0WII84.3MRB8DDN9AMYD@fra02>
In-Reply-To
<20240220002049.235278-4-tim@timculverhouse.com> (view parent)
DKIM signature
missing
Download raw message
aerc/patches: SUCCESS in 2m51s

[binds: refactor parser to be more tolerant][0] v2 from [Tim Culverhouse][1]

[0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/49698
[1]: tim@timculverhouse.com

✓ #1153807 SUCCESS aerc/patches/openbsd.yml     https://builds.sr.ht/~rjarry/job/1153807
✓ #1153806 SUCCESS aerc/patches/alpine-edge.yml https://builds.sr.ht/~rjarry/job/1153806

Applied: [PATCH aerc v2 1/2] binds: refactor parser to be more tolerant

Details
Message ID
<170842217270.377915.7427414609394074112@ringo>
In-Reply-To
<20240220002049.235278-3-tim@timculverhouse.com> (view parent)
DKIM signature
pass
Download raw message
Tim Culverhouse <tim@timculverhouse.com> wrote:
> Refactor the bind parser to construct arbitrary modified keys instead of
> only relying on built in maps. Add additional tests to cover edge cases.
>
> Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
> ---
> v2: introduce this entire patch

Acked-by: Robin Jarry <robin@jarry.cc>

Applied, thanks.

To git@git.sr.ht:~rjarry/aerc
   782a17dfb056..3c01fd0fcd03  master -> master
Reply to thread Export thread (mbox)