Skip to content

Commit 78c57ef

Browse files
0.0.15 (#33)
* add json output (whole data for requested layout) * support json output * embed web resources * rounded keys Co-authored-by: elder-n00b <elder.noob@yandex.com>
1 parent 038954c commit 78c57ef

File tree

17 files changed

+1047
-597
lines changed

17 files changed

+1047
-597
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2020 Rasmus Lindroth
3+
Copyright (c) 2022 Rasmus Lindroth
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ i3keys text ISO
7171
//or filter text output
7272
i3keys text ISO Mod4+Ctrl
7373
74+
//or output json to the terminal
75+
i3keys json ISO
76+
7477
//or output SVG to the current directory
7578
i3keys svg ISO ./
7679
@@ -144,12 +147,15 @@ The commands are:
144147
web [port]
145148
start the web ui and listen on random port or [port]
146149
147-
text <layout> [mods]
148-
output available keybindings in the terminal
149-
150150
svg <layout> [dest] [mods]
151151
outputs one SVG file for each modifier group
152152
153+
json <layout>
154+
output all keybindings as json
155+
156+
text <layout> [mods]
157+
output available keybindings in the terminal
158+
153159
version
154160
print i3keys version
155161

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
module github.com/RasmusLindroth/i3keys
22

3-
go 1.12
3+
go 1.16
44

55
require (
66
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect
77
github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 // indirect
8-
github.com/felixge/httpsnoop v1.0.2 // indirect
8+
github.com/felixge/httpsnoop v1.0.3 // indirect
99
github.com/gorilla/handlers v1.5.1
1010
github.com/gorilla/mux v1.8.0
1111
go.i3wm.org/i3/v4 v4.18.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046/go.mod h1:uw9h2
77
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
88
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
99
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
10+
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
11+
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
1012
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
1113
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
1214
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=

i3keys.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@ import (
55
"os"
66
"strings"
77

8+
"github.com/RasmusLindroth/i3keys/json"
89
"github.com/RasmusLindroth/i3keys/svg"
910
"github.com/RasmusLindroth/i3keys/text"
1011
"github.com/RasmusLindroth/i3keys/web"
1112
)
1213

13-
const version string = "0.0.14"
14+
const version string = "0.0.15"
1415

1516
func helpText(exitCode int) {
1617
fmt.Print("Usage:\n\n\ti3keys [-i|-s] <command> [arguments]\n")
1718
fmt.Print("\tAdd the flag -i for i3 and -s for Sway if you don't want autodetection\n\n")
1819
fmt.Print("The commands are:\n\n")
1920
fmt.Print("\tweb [port]\n\t\tstart the web ui and listen on random port or [port]\n\n")
20-
fmt.Print("\ttext <layout> [mods]\n\t\toutput available keybindings in the terminal\n\n")
2121
fmt.Print("\tsvg <layout> [dest] [mods]\n\t\toutputs one SVG file for each modifier group\n\n")
22+
fmt.Print("\tjson <layout>\n\t\toutput all keybindings as json\n\n")
23+
fmt.Print("\ttext <layout> [mods]\n\t\toutput available keybindings in the terminal\n\n")
2224
fmt.Print("\tversion\n\t\tprint i3keys version\n\n")
2325
fmt.Print("Arguments:\n\n")
2426
fmt.Print("\t<layout>\n\t\tis required. Can be ISO or ANSI\n\n")
@@ -49,17 +51,17 @@ func main() {
4951
port = os.Args[1+sIndex]
5052
}
5153

52-
layoutCheck := len(os.Args) > 1+sIndex && (strings.ToUpper(os.Args[1+sIndex]) != "ISO" && strings.ToUpper(os.Args[1+sIndex]) != "ANSI")
53-
54-
if cmd == "text" && len(os.Args) < 2+sIndex || (cmd == "text" && layoutCheck) {
55-
fmt.Println("You need to set the <layout> to ISO or ANSI")
56-
os.Exit(2)
57-
}
58-
59-
if (cmd == "svg" && len(os.Args) < 2+sIndex) ||
60-
(cmd == "svg" && layoutCheck) {
61-
fmt.Println("You need to set the <layout> to ISO or ANSI")
62-
os.Exit(2)
54+
layout := ""
55+
if cmd == "text" || cmd == "json" || cmd == "svg" {
56+
if len(os.Args) <= 1+sIndex {
57+
fmt.Println("You need to set the <layout> to ISO or ANSI")
58+
os.Exit(2)
59+
}
60+
layout = strings.ToUpper(os.Args[1+sIndex])
61+
if layout != "ISO" && layout != "ANSI" {
62+
fmt.Println("You need to set the <layout> to ISO or ANSI")
63+
os.Exit(2)
64+
}
6365
}
6466

6567
switch cmd {
@@ -71,6 +73,8 @@ func main() {
7173
} else {
7274
text.Output(wm, os.Args[1+sIndex], os.Args[2+sIndex])
7375
}
76+
case "json":
77+
json.Output(wm, layout)
7478
case "svg":
7579
if len(os.Args) < 3+sIndex {
7680
svg.Output(wm, os.Args[1+sIndex], "", "")

i3parse/group.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func (a sortByNumModifiers) Less(i, j int) bool {
1414
return len(a[i].Modifiers) < len(a[j].Modifiers)
1515
}
1616

17-
//GetModifierGroups groups bindings that have the same modifiers
17+
// GetModifierGroups groups bindings that have the same modifiers
1818
func GetModifierGroups(bindings []Binding) []ModifierGroup {
1919
var groups []ModifierGroup
2020
for _, binding := range bindings {

i3parse/parse.go

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,25 @@ func getLineType(parts []string, c context) lineType {
6262
return skipLine
6363
}
6464

65-
/* TODO:
66-
See i3 documentation for group1,group2,etc.
67-
type Group string
68-
*/
69-
70-
//ParseFromRunning loads config from the running i3 instance
71-
func ParseFromRunning(wm string) ([]Mode, []Binding, error) {
65+
// ParseFromRunning loads config from the running i3 instance
66+
func ParseFromRunning(wm string, logError bool) ([]Mode, []Variable, error) {
7267
switch wm {
7368
case "i3":
74-
return parse(getConfigFromRunningi3())
69+
r, err := getConfigFromRunningi3()
70+
return parse(r, logError, err)
7571
case "sway":
76-
return parse(getConfigFromRunningSway())
72+
r, err := getConfigFromRunningSway()
73+
return parse(r, logError, err)
7774
default:
78-
return parse(getAutoWM())
75+
r, err := getAutoWM()
76+
return parse(r, logError, err)
7977
}
8078
}
8179

82-
//ParseFromFile loads config from path
83-
func ParseFromFile(path string) ([]Mode, []Binding, error) {
84-
return parse(getConfigFromFile(path))
80+
// ParseFromFile loads config from path
81+
func ParseFromFile(path string, logError bool) ([]Mode, []Variable, error) {
82+
r, err := getConfigFromFile(path)
83+
return parse(r, logError, err)
8584
}
8685

8786
func readLine(reader *bufio.Reader, c context, variables []Variable) (string, []string, lineType, error) {
@@ -136,15 +135,15 @@ func readLine(reader *bufio.Reader, c context, variables []Variable) (string, []
136135
return line, lineParts, lineType, err
137136
}
138137

139-
func parseConfig(confReader io.Reader, confPath string, variables []Variable, err error) ([]Mode, []Binding, []Variable, []string, error) {
138+
func parseConfig(confReader io.Reader, confPath string, variables []Variable, logError bool, err error) ([]Mode, []Variable, []string, error) {
140139
if err != nil {
141-
return []Mode{}, []Binding{}, []Variable{}, []string{}, errors.New("couldn't get the config file")
140+
return []Mode{}, []Variable{}, []string{}, errors.New("couldn't get the config file")
142141
}
143142

144143
reader := bufio.NewReader(confReader)
145144

146-
var modes []Mode
147-
var bindings []Binding
145+
modes := []Mode{{}}
146+
148147
var includes []helpers.Include
149148

150149
context := mainContext
@@ -156,7 +155,7 @@ func parseConfig(confReader io.Reader, confPath string, variables []Variable, er
156155
_, lineParts, lineType, readErr = readLine(reader, context, variables)
157156

158157
if readErr != nil && readErr != io.EOF {
159-
return []Mode{}, []Binding{}, []Variable{}, []string{}, readErr
158+
return []Mode{}, []Variable{}, []string{}, readErr
160159
}
161160

162161
switch lineType {
@@ -208,42 +207,41 @@ func parseConfig(confReader io.Reader, confPath string, variables []Variable, er
208207
bindingLine := lineType == bindSymLine || lineType == bindCodeLine
209208

210209
binding, err := parseBinding(lineParts)
211-
if err != nil {
210+
if err != nil && logError {
212211
log.Println(err)
213212
continue
214213
}
215214

216215
isMainContext := context == mainContext || context == bindCodeMainContext || context == bindSymMainContext
217216
if isMainContext && bindingLine {
218-
bindings = append(bindings, binding)
217+
modes[0].Bindings = append(modes[0].Bindings, binding)
219218
}
220219

221220
isModeContext := context == modeContext || context == bindCodeModeContext || context == bindSymModeContext
222221
if isModeContext && bindingLine {
223-
modes[len(modes)-1].Bindings = append(modes[len(modes)-1].Bindings,
224-
binding,
225-
)
222+
l := len(modes) - 1
223+
modes[l].Bindings = append(modes[l].Bindings, binding)
226224
}
227225
}
228226

229227
var includePaths []string
230228
for _, incl := range includes {
231229
matches, err := helpers.GetPaths(incl)
232-
if err != nil {
230+
if err != nil && logError {
233231
log.Printf("couldn't parse the following include \"%s\" got error %v", incl, err)
234232
continue
235233
}
236234
includePaths = append(includePaths, matches...)
237235
}
238236

239-
return modes, bindings, variables, includePaths, nil
237+
return modes, variables, includePaths, nil
240238
}
241239

242-
func parse(confReader io.Reader, err error) ([]Mode, []Binding, error) {
240+
func parse(confReader io.Reader, logError bool, err error) ([]Mode, []Variable, error) {
243241
configPath, _ := helpers.GetSwayDefaultConfig()
244-
modes, bindings, variables, includes, err := parseConfig(confReader, configPath, []Variable{}, err)
242+
modes, variables, includes, err := parseConfig(confReader, configPath, []Variable{}, logError, err)
245243
if err != nil {
246-
return []Mode{}, []Binding{}, errors.New("couldn't get the config file")
244+
return []Mode{}, []Variable{}, errors.New("couldn't get the config file")
247245
}
248246
var parsedIncludes []string
249247
for j := 0; j < len(includes); j++ {
@@ -258,26 +256,37 @@ func parse(confReader io.Reader, err error) ([]Mode, []Binding, error) {
258256
continue
259257
}
260258
f, ferr := os.Open(incl)
261-
if err != nil {
259+
if err != nil && logError {
262260
log.Printf("couldn't open the included file %s, got err: %v\n", incl, ferr)
263261
}
264-
m, b, v, i, perr := parseConfig(f, incl, variables, err)
265-
if err != nil {
262+
m, v, i, perr := parseConfig(f, incl, variables, logError, err)
263+
if err != nil && logError {
266264
log.Printf("couldn't parse the included file %s, got err: %v\n", incl, perr)
267265
}
268-
modes = append(modes, m...)
269-
bindings = append(bindings, b...)
270-
variables = v
266+
// add modes merging existing bindings
267+
for iNew := range m {
268+
found := false
269+
for iOld := range modes {
270+
if m[iNew].Name == modes[iOld].Name {
271+
found = true
272+
modes[iOld].Bindings = append(modes[iOld].Bindings, m[iNew].Bindings...) // duplicates?
273+
break
274+
}
275+
}
276+
if !found {
277+
modes = append(modes, m[iNew])
278+
}
279+
}
280+
variables = v // NOTE: variables are updated in parseConfig
271281
includes = append(includes, i...)
272282
parsedIncludes = append(parsedIncludes, incl)
273283
}
274284

275285
for key := range modes {
276286
modes[key].Bindings = sortModifiers(modes[key].Bindings)
277287
}
278-
bindings = sortModifiers(bindings)
279288

280-
return modes, bindings, nil
289+
return modes, variables, nil
281290
}
282291

283292
func parseMode(line string) string {

0 commit comments

Comments
 (0)