-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
command_chars.go
210 lines (194 loc) · 8.02 KB
/
command_chars.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package main
import (
"fmt"
"io"
"strings"
)
const (
eof = -1
)
var (
shellAction = rune('!')
bulkMarkAction = rune('"')
searchAction = rune('/') // /re/... establishes the ADDRESSES for the lines against which to execute cmd moving forward
putMarkAction = rune('\'')
searchRevAction = rune('\\') // \re\... establishes the ADDRESSES for the lines against which to execute cmd moving backward
eqAction = rune('=')
appendAction = rune('a')
breakAction = rune('b')
changeAction = rune('c')
deleteAction = rune('d')
editAction = rune('e') // Edit command
reallyEditAction = rune('E') // Edit command
filenameAction = rune('f')
globalIntSearchAction = rune('G')
globalReplaceAction = rune('g') // s/foo/bar/g is the glob suffix which means we replace ALL the matches within a line not just the first
globalSearchAction = rune('g') // g/re/p is the glob prefix which means we use the pattern to print every line that matches [gPREFIX]
historyAction = rune('H')
helpAction = rune('h')
insertAction = rune('i')
joinAction = rune('j')
copyAction = rune('k')
printLiteralAction = rune('l')
mirrorAction = rune('M')
moveAction = rune('m')
printNumsAction = rune('n')
printAction = rune('p')
quitAction = rune('q')
reallyQuitAction = rune('Q')
readAction = rune('r')
simpleReplaceAction = rune('s')
regexReplaceAction = rune('S')
transliterateAction = rune('t')
undoAction = rune('u')
globalNegIntSearchAction = rune('V')
globalNegSearchAction = rune('v') // v/re/p is the glob prefix which means we use the pattern to print every line that doesn't match [gPREFIX]
superWriteAction = rune('W') // write [file] command
writeAction = rune('w') // write [file] command
setPagerAction = rune('z')
// setColumnAction = rune('^')
// printColumnAction = rune('|')
debugAction = rune('*')
)
type quickdoc struct {
example string
explanation string
}
var cmds = map[rune]quickdoc{
shellAction: {`!exe`, "[shell] run $exe and print the output"},
bulkMarkAction: {`(,)"a cmd`, "[mark] print each line marked with the single character $a or do $cmd, if provided, for each line"},
searchAction: {`/regex/`, "[search] find the next line matching $regex"},
putMarkAction: {`(,)'a`, "[mark] mark the given lines with the single character $a"},
searchRevAction: {`\regex\`, "[search] find the previous line matching $regex"},
eqAction: {`=`, "[print] print the address of the current line"},
appendAction: {`(.)a`, "[append] adds text to the buffer after the current line"},
breakAction: {`(,)b/regex/`, "[break] breaks the given lines into many lines at $regex"},
changeAction: {`(,)c`, "[change] replaces the given lines with user input"},
deleteAction: {`(,)d`, "[delete] removes the given lines from the buffer"},
editAction: {"e filename|!exe", "[edit] replaces the current buffer with $filename or the output of $exe"},
filenameAction: {"f name", "[file] set the current buffer to write to file $name"},
reallyEditAction: {"E file", "[edit] replaces the current buffer with $file without prompting to save changes"},
globalIntSearchAction: {"G/regex/", "[global] interactively take commands to run against all lines matching $regex"},
globalReplaceAction: {"", ""},
globalSearchAction: {"g/regex/cmd", "[global] run $cmd against each line matching $regex"},
historyAction: {"H n", "[history] print the last $n commands; disabled when compiled with '-tag readline'"},
helpAction: {"h", "[help] print the manual"},
insertAction: {"(.)i", "[insert] adds text to the buffer before the current line"},
joinAction: {"(,)j/sep/", "[join] join the given lines using $sep"},
copyAction: {"(,)k(.)", "[kopy/paste] copy the given lines to after the given destination"},
printLiteralAction: {"(,)l", "[literal] print the given lines but show special characters"},
mirrorAction: {"(,)M", "[mirror] reverse the order of the given lines"},
moveAction: {"(,)m(.)", "[move] move the given lines to after the given destination"},
printNumsAction: {"(,)n", "[number] print the given lines with line numbers in the left margin"},
printAction: {"(,)p", "[print] print the given lines"},
quitAction: {"q", "[quit] exit the application"},
reallyQuitAction: {"Q", "[quit] exit the application without prompting to save changes"},
readAction: {"(.)r file|!exe", "[read] read the contents of $file or the output of $exe into the buffer after the given line"},
simpleReplaceAction: {"(,)s/pat/sub/n", "[substitute] replace $pat with $sub"},
regexReplaceAction: {"(,)S/regex/sub/n", "[substitute] replace $regex with $sub"},
transliterateAction: {"(,)t/find/repl/", "[transliterate] replace each character in $find with the corresponding character in $repl"},
undoAction: {"u", "[undo/redo] undo the last action; undo is it's own inverse"},
globalNegIntSearchAction: {"V/regex/", "[global] interactively take commands to run against all lines not matching $regex"},
globalNegSearchAction: {"v/regex/cmd", "[global] run $cmd against each line not matching $regex"},
superWriteAction: {"", ""},
writeAction: {"w filename", "[write] write the buffer to the set filename or $filename if provided"},
setPagerAction: {"z n", "[pager] set pager to $n lines"},
debugAction: {"*", "[debug] print debugging information"},
}
var additionalDocs = map[rune]quickdoc{
'>': {"(,)>n", "[peek] print up to n lines after the given lines"},
'<': {"(,)<n", "[peek] print up to n lines before the given lines"},
}
func allCmds() string {
return string(cmdOrder)
}
func excludeFromGlob(r rune) bool {
return contains(string([]rune{
setPagerAction,
globalSearchAction,
globalNegSearchAction,
globalIntSearchAction,
globalNegIntSearchAction,
}), r)
}
func invertDirection(r rune) bool {
return contains(string([]rune{
globalNegSearchAction,
globalNegIntSearchAction,
}), r)
}
var cmdOrder = []rune{
appendAction,
breakAction,
changeAction,
deleteAction,
editAction,
reallyEditAction,
filenameAction,
globalSearchAction,
globalIntSearchAction,
helpAction,
historyAction,
insertAction,
joinAction,
copyAction,
printLiteralAction,
moveAction,
mirrorAction,
printNumsAction,
printAction,
quitAction,
reallyQuitAction,
readAction,
shellAction,
simpleReplaceAction,
regexReplaceAction,
transliterateAction,
undoAction,
globalNegSearchAction,
globalNegIntSearchAction,
writeAction,
superWriteAction,
setPagerAction,
searchAction,
searchRevAction,
putMarkAction,
bulkMarkAction,
eqAction,
debugAction,
}
func quickHelp() string {
var str strings.Builder
for _, r := range cmdOrder {
if q, ok := cmds[r]; ok && len(q.example) > 0 {
fmt.Fprintf(&str, " - %-8s %s\n\n", q.example, wrap(q.explanation, len(q.example), 13))
}
}
for r := range additionalDocs {
if q, ok := additionalDocs[r]; ok && len(q.example) > 0 {
fmt.Fprintf(&str, " - %-8s %s\n\n", q.example, wrap(q.explanation, len(q.example), 13))
}
}
return str.String()
}
func wrap(s string, prev, prepad int) string {
pad := strings.Repeat(" ", prepad)
parts := strings.Split(s, " ")
var final strings.Builder
var l int
if len(s) > 80-8 || prev > 8 {
io.WriteString(&final, "\n")
io.WriteString(&final, pad)
}
for _, part := range parts {
l += len(part) + 1
if l > 80-13 {
io.WriteString(&final, "\n")
io.WriteString(&final, pad)
l = 0
}
io.WriteString(&final, part)
io.WriteString(&final, " ")
}
return final.String()
}