Skip to content

Commit 35c0d45

Browse files
committed
allow repl to intercept ctrl+c when running a command, closes #275
1 parent 61e340e commit 35c0d45

File tree

8 files changed

+62
-4
lines changed

8 files changed

+62
-4
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ wasm:
2828
GOOS=js GOARCH=wasm go build -o docs/abs.wasm js/js.go
2929
tapes: build_simple
3030
docker build -t abs-tapes docs/vhs
31-
docker run -ti -v $$(pwd)/builds/abs:/usr/bin/abs -v $$(pwd):/abs abs-tapes
31+
docker run -ti -v $$(pwd)/builds/abs:/usr/bin/abs -v $$(pwd):/abs -e TAPE=$(tape) abs-tapes

docs/vhs/images/ip.gif

-487 Bytes
Loading

docs/vhs/images/readme-sample.gif

2.74 KB
Loading

docs/vhs/images/repl-quit-command.gif

10.6 KB
Loading

docs/vhs/images/suggestions.gif

235 Bytes
Loading

docs/vhs/tapes/repl-quit-command.tape

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Output "/abs/docs/vhs/images/repl-quit-command.gif"
2+
3+
Set FontSize 24
4+
Set Width 1200
5+
Set Height 400
6+
Set BorderRadius 10
7+
Set Margin 10
8+
Set MarginFill "#a1a1a1"
9+
Set TypingSpeed 75ms
10+
11+
Source "/abs/docs/vhs/tapes/config.tape"
12+
13+
Type "`sleep 10`"
14+
Enter
15+
Sleep 1
16+
17+
Ctrl+C
18+
Sleep 2

docs/vhs/vhs.abs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
f run_tape(t) {
2-
echo("running tape %s", tape)
3-
res = `vhs /abs/docs/vhs/tapes/$tape`
2+
echo("running tape %s", t)
3+
res = `vhs /abs/docs/vhs/tapes/$t`
44

55
if !res.ok {
66
exit(99, res)

terminal/terminal.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package terminal
22

33
import (
4+
"context"
45
"crypto/rand"
56
"fmt"
67
"io"
@@ -82,6 +83,7 @@ type Model struct {
8283
// to determine that while ABS is executing,
8384
// we should relay stdin from the terminal
8485
isEvaluating bool
86+
cancelEval context.CancelFunc
8587
// function to print the prompt 'prefix'
8688
prompt func() string
8789
// dirty input -- input I may have typed on
@@ -155,7 +157,12 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
155157
// so if we type during this time,
156158
// we should forward this to ABS' stdin
157159
if m.isEvaluating {
158-
return m.interceptStdin(msg)
160+
switch msg.Type {
161+
case tea.KeyCtrlC:
162+
return m.abortEval()
163+
default:
164+
return m.interceptStdin(msg)
165+
}
159166
}
160167

161168
if m.IsSuggesting() {
@@ -253,6 +260,22 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
253260
return m, tiCmd
254261
}
255262

263+
func (m Model) abortEval() (tea.Model, tea.Cmd) {
264+
return m, func() tea.Msg {
265+
// *if* a command was running, let's
266+
// notify it that it should be canceled
267+
if m.cancelEval != nil {
268+
m.cancelEval()
269+
}
270+
271+
// 'fake' a command being done
272+
return doneEval{
273+
out: object.NULL,
274+
ok: false,
275+
}
276+
}
277+
}
278+
256279
func (m Model) search() Model {
257280
if !m.isSearching {
258281
m.isSearching = true
@@ -597,10 +620,27 @@ type doneEval struct {
597620

598621
func (m Model) eval() (Model, tea.Cmd) {
599622
m.isEvaluating = true
623+
ctx, cancel := context.WithCancel(context.Background())
624+
m.cancelEval = cancel
625+
600626
done := make(chan doneEval)
601627

602628
go func() {
629+
defer m.cancelEval()
630+
// obviously we should pass the context to the runner
631+
// but this is for another day. The current implementation
632+
// makes it so that the command will keep running in background,
633+
// but we'll give the user the impression the command is
634+
// terminated (which is bad). Again, I think the real solution
635+
// over time is to introduce a CancelContext to the runner
636+
// that gets passed down all the way to running the commands.
603637
out, ok, parseErrors := runner.Run(m.in.Value(), m.env)
638+
639+
// someone cancelled the eval operation
640+
if err := ctx.Err(); err != nil {
641+
return
642+
}
643+
604644
done <- doneEval{out, ok, parseErrors}
605645
}()
606646

0 commit comments

Comments
 (0)