Implement parsing of map
This commit is contained in:
parent
e4fbcb707f
commit
5329546f21
@ -478,10 +478,49 @@ def go_type_data(parser_func: ParserFuncType, ctype: str, is_multiple: bool = Fa
|
||||
return {int: 'int64', str: 'string', float: 'float64'}[rettype], f'{p}(val)'
|
||||
|
||||
|
||||
mod_map = {
|
||||
"shift": "shift",
|
||||
"⇧": "shift",
|
||||
"alt": "alt",
|
||||
"option": "alt",
|
||||
"opt": "alt",
|
||||
"⌥": "alt",
|
||||
"super": "super",
|
||||
"command": "super",
|
||||
"cmd": "super",
|
||||
"⌘": "super",
|
||||
"control": "ctrl",
|
||||
"ctrl": "ctrl",
|
||||
"⌃": "ctrl",
|
||||
"hyper": "hyper",
|
||||
"meta": "meta",
|
||||
"num_lock": "num_lock",
|
||||
"caps_lock": "caps_lock",
|
||||
}
|
||||
|
||||
def normalize_shortcut(spec: str) -> str:
|
||||
if spec.endswith('+'):
|
||||
spec = spec[:-1] + 'plus'
|
||||
parts = spec.lower().split('+')
|
||||
key = parts[-1]
|
||||
if len(parts) == 1:
|
||||
return key
|
||||
mods = parts[:-1]
|
||||
return '+'.join(mod_map.get(x, x) for x in mods) + '+' + key
|
||||
|
||||
|
||||
def normalize_shortcuts(spec: str) -> Iterator[str]:
|
||||
spec = spec.replace('++', '+plus')
|
||||
spec = re.sub(r'([^+])>', '\\1\0', spec)
|
||||
for x in spec.split('\0'):
|
||||
yield normalize_shortcut(x)
|
||||
|
||||
|
||||
def gen_go_code(defn: Definition) -> str:
|
||||
lines = ['import "fmt"', 'import "strconv"', 'import "kitty/tools/config"', 'import "kitty/tools/utils/style"',
|
||||
'var _ = fmt.Println', 'var _ = config.StringToBool', 'var _ = strconv.Atoi', 'var _ = style.ParseColor']
|
||||
a = lines.append
|
||||
keyboard_shortcuts = tuple(defn.iter_all_maps())
|
||||
choices = {}
|
||||
go_types = {}
|
||||
go_parsers = {}
|
||||
@ -509,6 +548,8 @@ def gen_go_code(defn: Definition) -> str:
|
||||
a(f'{name} []{gotype}')
|
||||
else:
|
||||
a(f'{name} {gotype}')
|
||||
if keyboard_shortcuts:
|
||||
a('KeyboardShortcuts []*config.KeyAction')
|
||||
a('}')
|
||||
|
||||
def cval(x: str) -> str:
|
||||
@ -540,6 +581,16 @@ def gen_go_code(defn: Definition) -> str:
|
||||
else:
|
||||
dval = repr(d)
|
||||
a(f'{name}: {dval},')
|
||||
if keyboard_shortcuts:
|
||||
a('KeyboardShortcuts: []*config.KeyAction{')
|
||||
for sc in keyboard_shortcuts:
|
||||
aname, aargs = map(serialize_as_go_string, sc.action_def.partition(' ')[::2])
|
||||
a('{'f'Name: "{aname}", Args: "{aargs}", Normalized_keys: []string''{')
|
||||
ns = normalize_shortcuts(sc.key_text)
|
||||
a(', '.join(f'"{serialize_as_go_string(x)}"' for x in ns) + ',')
|
||||
a('}''},')
|
||||
a('},')
|
||||
|
||||
a('}''}')
|
||||
|
||||
for oname, choice_vals in choices.items():
|
||||
@ -582,6 +633,11 @@ def gen_go_code(defn: Definition) -> str:
|
||||
a(f'c.{oname} = append(c.{oname}, temp_val...)')
|
||||
else:
|
||||
a(f'c.{oname} = temp_val')
|
||||
if keyboard_shortcuts:
|
||||
a('case "map":')
|
||||
a('tempsc, err := config.ParseMap(val)')
|
||||
a('if err != nil { return fmt.Errorf("Failed to parse map = %#v with error: %w", val, err) }')
|
||||
a('c.KeyboardShortcuts = append(c.KeyboardShortcuts, tempsc)')
|
||||
a('}')
|
||||
a('return}')
|
||||
return '\n'.join(lines)
|
||||
|
||||
@ -9,10 +9,11 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"kitty/tools/utils"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"kitty/tools/utils"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
@ -5,6 +5,7 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"kitty/tools/utils"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@ -183,3 +184,72 @@ func StringLiteral(val string) (string, error) {
|
||||
}
|
||||
return ans.String(), nil
|
||||
}
|
||||
|
||||
var ModMap = (&utils.Once[map[string]string]{Run: func() map[string]string {
|
||||
return map[string]string{
|
||||
"shift": "shift",
|
||||
"⇧": "shift",
|
||||
"alt": "alt",
|
||||
"option": "alt",
|
||||
"opt": "alt",
|
||||
"⌥": "alt",
|
||||
"super": "super",
|
||||
"command": "super",
|
||||
"cmd": "super",
|
||||
"⌘": "super",
|
||||
"control": "ctrl",
|
||||
"ctrl": "ctrl",
|
||||
"⌃": "ctrl",
|
||||
"hyper": "hyper",
|
||||
"meta": "meta",
|
||||
"num_lock": "num_lock",
|
||||
"caps_lock": "caps_lock",
|
||||
}
|
||||
}}).Get
|
||||
|
||||
var ShortcutSpecPat = (&utils.Once[*regexp.Regexp]{Run: func() *regexp.Regexp {
|
||||
return regexp.MustCompile(`([^+])>`)
|
||||
}}).Get
|
||||
|
||||
func NormalizeShortcut(spec string) string {
|
||||
parts := strings.Split(strings.ToLower(spec), "+")
|
||||
key := parts[len(parts)-1]
|
||||
if len(parts) == 1 {
|
||||
return key
|
||||
}
|
||||
mods := parts[:len(parts)-1]
|
||||
mmap := ModMap()
|
||||
mods = utils.Map(func(x string) string {
|
||||
ans := mmap[x]
|
||||
if ans == "" {
|
||||
ans = x
|
||||
}
|
||||
return ans
|
||||
}, mods)
|
||||
utils.Sort(mods, func(a, b string) bool { return a < b })
|
||||
return strings.Join(mods, "+") + "+" + key
|
||||
}
|
||||
|
||||
func NormalizeShortcuts(spec string) []string {
|
||||
if strings.HasSuffix(spec, "+") {
|
||||
spec = spec[:len(spec)-1] + "plus"
|
||||
}
|
||||
spec = strings.ReplaceAll(spec, "++", "+plus")
|
||||
spec = ShortcutSpecPat().ReplaceAllString(spec, "$1\x00")
|
||||
return utils.Map(NormalizeShortcut, strings.Split(spec, "\x00"))
|
||||
}
|
||||
|
||||
type KeyAction struct {
|
||||
Normalized_keys []string
|
||||
Name string
|
||||
Args string
|
||||
}
|
||||
|
||||
func ParseMap(val string) (*KeyAction, error) {
|
||||
spec, action, found := strings.Cut(val, " ")
|
||||
if !found {
|
||||
return nil, fmt.Errorf("No action specified for shortcut %s", val)
|
||||
}
|
||||
action_name, action_args, _ := strings.Cut(action, " ")
|
||||
return &KeyAction{Name: action_name, Args: action_args, Normalized_keys: NormalizeShortcuts(spec)}, nil
|
||||
}
|
||||
|
||||
@ -4,7 +4,10 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
@ -24,3 +27,18 @@ func TestStringLiteralParsing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeShortcuts(t *testing.T) {
|
||||
for q, expected_ := range map[string]string{
|
||||
`a`: `a`,
|
||||
`+`: `plus`,
|
||||
`cmd+b>opt+>`: `super+b alt+>`,
|
||||
`cmd+>>opt+>`: `super+> alt+>`,
|
||||
} {
|
||||
expected := strings.Split(expected_, " ")
|
||||
actual := NormalizeShortcuts(q)
|
||||
if diff := cmp.Diff(expected, actual); diff != "" {
|
||||
t.Fatalf("failed with input: %#v\n%s", q, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user