Skip to content

Commit 44f8871

Browse files
cleaned up editor interface
1 parent 615be02 commit 44f8871

File tree

3 files changed

+69
-52
lines changed

3 files changed

+69
-52
lines changed

playground/internal/editor/editor.go

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@ const (
1212
// TabWidth is the number of spaces per tab.
1313
TabWidth = 4
1414

15+
EscapeEvent = `escape`
16+
SaveEvent = `save`
17+
UndoEvent = `undo`
18+
RedoEvent = `redo`
19+
1520
commentPrefix = `// `
1621
commentPrefixLen = len(commentPrefix)
1722
)
1823

1924
type CodeBoxWrapper interface {
2025
Code() string
21-
SetCode(code string)
22-
EmitSave()
23-
EmitEscape()
2426
GetSelection() (int, int)
25-
SetSelection(start, end int, code string)
27+
SetCode(selectionStart, selectionEnd int, code string)
28+
EmitEvent(event string)
2629
}
2730

2831
// MeasureLineLength returns the length of the line.
@@ -103,8 +106,7 @@ func (ce *codeEditor) handleKeyDown(key string, shift, ctrl bool) bool {
103106
case `[`:
104107
return ce.insertPair(ctrl, `[`, `]`)
105108
case `Escape`:
106-
ce.EmitEscape()
107-
return true
109+
return ce.handleEscape()
108110
default:
109111
return false
110112
}
@@ -165,11 +167,7 @@ func (ce *codeEditor) handleSpace(shift, ctrl bool) bool {
165167
write(newCode, code[start:])
166168

167169
start = lineStart + tabs + spaces
168-
end = start
169-
170-
code = newCode.String()
171-
ce.SetCode(code)
172-
ce.SetSelection(start, end, code)
170+
ce.SetCode(start, start, newCode.String())
173171
return true
174172
}
175173

@@ -234,9 +232,7 @@ func (ce *codeEditor) addIndents() bool {
234232
})
235233
write(newCode, code[endLine:])
236234

237-
code = newCode.String()
238-
ce.SetCode(code)
239-
ce.SetSelection(newStart, newEnd, code)
235+
ce.SetCode(newStart, newEnd, newCode.String())
240236
return true
241237
}
242238

@@ -295,9 +291,7 @@ func (ce *codeEditor) removeIndents() bool {
295291
})
296292
write(newCode, code[endLine:])
297293

298-
code = newCode.String()
299-
ce.SetCode(code)
300-
ce.SetSelection(newStart, newEnd, code)
294+
ce.SetCode(newStart, newEnd, newCode.String())
301295
return true
302296
}
303297

@@ -363,7 +357,12 @@ func (ce *codeEditor) handleSave(shift, ctrl bool) bool {
363357
return false
364358
}
365359

366-
ce.EmitSave()
360+
ce.EmitEvent(SaveEvent)
361+
return true
362+
}
363+
364+
func (ce *codeEditor) handleEscape() bool {
365+
ce.EmitEvent(EscapeEvent)
367366
return true
368367
}
369368

@@ -449,9 +448,7 @@ func (ce *codeEditor) addCommenting(startLine, endLine int) {
449448
})
450449
write(newCode, code[endLine:])
451450

452-
code = newCode.String()
453-
ce.SetCode(code)
454-
ce.SetSelection(newStart, newEnd, code)
451+
ce.SetCode(newStart, newEnd, newCode.String())
455452
}
456453

457454
// removeCommenting will uncomment any line that starts with the comment prefix
@@ -483,9 +480,7 @@ func (ce *codeEditor) removeCommenting(startLine, endLine int) {
483480
})
484481
write(newCode, code[endLine:])
485482

486-
code = newCode.String()
487-
ce.SetCode(code)
488-
ce.SetSelection(newStart, newEnd, code)
483+
ce.SetCode(newStart, newEnd, newCode.String())
489484
}
490485

491486
// getSelectedLines returns the start and end character indices of that
@@ -585,9 +580,7 @@ func (ce *codeEditor) insertAtSelection(before, after string, keepSelection bool
585580
write(newCode, code[end:])
586581
}
587582

588-
code = newCode.String()
589-
ce.SetCode(code)
590-
ce.SetSelection(newStart, newEnd, code)
583+
ce.SetCode(newStart, newEnd, newCode.String())
591584
}
592585

593586
func (ce *codeEditor) indentAt(start int) string {

playground/internal/editor/editor_test.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package editor
22

33
import (
4+
"errors"
45
"reflect"
56
"strings"
67
"testing"
@@ -943,7 +944,9 @@ func Test_Editor_ProcessKeyDown_Callback(t *testing.T) {
943944
key: `s`,
944945
ctrl: true,
945946
wantPrefentDefault: true,
946-
wantSaveCalls: 1,
947+
wantEventCalls: map[string]int{
948+
SaveEvent: 1,
949+
},
947950
})
948951

949952
runKeyDownTest(t, testKeyDown{
@@ -958,7 +961,9 @@ func Test_Editor_ProcessKeyDown_Callback(t *testing.T) {
958961
code: "func main() {}",
959962
key: `Escape`,
960963
wantPrefentDefault: true,
961-
wantEscapeCalls: 1,
964+
wantEventCalls: map[string]int{
965+
EscapeEvent: 1,
966+
},
962967
})
963968
}
964969

@@ -1135,8 +1140,7 @@ type testKeyDown struct {
11351140
wantSelectionStart int
11361141
wantSelectionEnd int
11371142
wantPrefentDefault bool
1138-
wantSaveCalls int
1139-
wantEscapeCalls int
1143+
wantEventCalls map[string]int
11401144
}
11411145

11421146
func runKeyDownTest(t *testing.T, tt testKeyDown) {
@@ -1152,8 +1156,7 @@ func runKeyDownTest(t *testing.T, tt testKeyDown) {
11521156
check(t, "selectedStart", cb.gotSelectionStart, tt.wantSelectionStart)
11531157
check(t, "selectedEnd", cb.gotSelectionEnd, tt.wantSelectionEnd)
11541158
check(t, "preventDefault", gotPreventDefault, tt.wantPrefentDefault)
1155-
check(t, "saveCalls", cb.getSaveCalls, tt.wantSaveCalls)
1156-
check(t, "escapeCalls", cb.gotEscapeCalls, tt.wantEscapeCalls)
1159+
check(t, "eventCalls", cb.gotEventCalls, tt.wantEventCalls)
11571160
})
11581161
}
11591162

@@ -1165,25 +1168,29 @@ type fakeCodeBox struct {
11651168
gotCode string
11661169
gotSelectionStart int
11671170
gotSelectionEnd int
1168-
getSaveCalls int
1169-
gotEscapeCalls int
1171+
gotEventCalls map[string]int
11701172
}
11711173

11721174
var _ CodeBoxWrapper = (*fakeCodeBox)(nil)
11731175

1174-
func (cb *fakeCodeBox) Code() string { return cb.initCode }
1175-
func (cb *fakeCodeBox) SetCode(code string) { cb.gotCode = code }
1176-
func (cb *fakeCodeBox) EmitSave() { cb.getSaveCalls++ }
1177-
func (cb *fakeCodeBox) EmitEscape() { cb.gotEscapeCalls++ }
1176+
func (cb *fakeCodeBox) Code() string { return cb.initCode }
1177+
1178+
func (cb *fakeCodeBox) EmitEvent(event string) {
1179+
if cb.gotEventCalls == nil {
1180+
cb.gotEventCalls = map[string]int{}
1181+
}
1182+
cb.gotEventCalls[event]++
1183+
}
11781184

11791185
func (cb *fakeCodeBox) GetSelection() (int, int) {
11801186
return cb.initSelectionStart, cb.initSelectionEnd
11811187
}
11821188

1183-
func (cb *fakeCodeBox) SetSelection(start, end int, _ string) {
1184-
// the code parameter is unused in this fake implementation
1185-
// since it should match the gotCode set via SetCode and is only
1186-
// used when setting the selection after a code change.
1189+
func (cb *fakeCodeBox) SetCode(start, end int, code string) {
1190+
if cb.gotCode != "" {
1191+
panic(errors.New(`SetCode called multiple times`))
1192+
}
1193+
cb.gotCode = code
11871194
cb.gotSelectionStart = start
11881195
cb.gotSelectionEnd = end
11891196
}
@@ -1210,7 +1217,8 @@ func check[T any](t *testing.T, name string, got, want T) {
12101217
return
12111218
}
12121219

1213-
if reflect.TypeOf(want).Kind() == reflect.Slice {
1220+
kind := reflect.TypeOf(want).Kind()
1221+
if kind == reflect.Slice || kind == reflect.Map || kind == reflect.Struct {
12141222
if diff := cmp.Diff(want, got); len(diff) > 0 {
12151223
diff = strings.ReplaceAll(diff, "\n", "\n ")
12161224
t.Errorf("%s was not as expected:\n"+

playground/internal/react/codeBox.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,27 @@ type codeBoxAssistant struct {
7979

8080
var _ editor.CodeBoxWrapper = (*codeBoxAssistant)(nil)
8181

82-
func (cba *codeBoxAssistant) Code() string { return cba.curCode }
83-
func (cba *codeBoxAssistant) SetCode(code string) { cba.setCode(code) }
84-
func (cba *codeBoxAssistant) EmitSave() { cba.onSave() }
85-
func (cba *codeBoxAssistant) EmitEscape() { cba.onEscape() }
82+
func (cba *codeBoxAssistant) Code() string { return cba.curCode }
8683

87-
// TODO(grantnelson-wf): Implement undo/redo stack since textarea
88-
// only handles undo/redo itself for non-programmatic changes but
89-
// doesn't handle undo/redo for when setCode is called.
84+
func (cba *codeBoxAssistant) EmitEvent(event string) {
85+
switch event {
86+
case editor.SaveEvent:
87+
cba.onSave()
88+
case editor.EscapeEvent:
89+
cba.onEscape()
90+
91+
//case editor.UndoEvent, editor.RedoEvent:
92+
// TODO(grantnelson-wf): Implement undo/redo stack since textarea
93+
// only handles undo/redo itself for non-programmatic changes but
94+
// doesn't handle undo/redo for when setCode is called.
95+
96+
// TODO(grantnelson-wf): If it is possible to detect a paste event,
97+
// then cleanup and indent the pasted code automatically.
98+
99+
default:
100+
println("Unknown event was requested to be emitted from CodeBox:", event)
101+
}
102+
}
90103

91104
func (cba *codeBoxAssistant) onInput(e *js.Object) {
92105
cba.setCode(e.Get(`target`).Get(`value`).String())
@@ -116,7 +129,10 @@ func (cba *codeBoxAssistant) GetSelection() (int, int) {
116129
return start, end
117130
}
118131

119-
func (cba *codeBoxAssistant) SetSelection(start, end int, code string) {
132+
func (cba *codeBoxAssistant) SetCode(start, end int, code string) {
133+
// Update the code state for react.
134+
cba.setCode(code)
135+
120136
// Pre-update the textarea value so that the caret and scroll can be set
121137
// correctly before the next render so that the next render doesn't reset them.
122138
cba.textAreaRef.Set(`value`, code)

0 commit comments

Comments
 (0)