From 88a9241daa2282135a905c2a3940bc784312b60c Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Fri, 5 Apr 2024 08:36:55 +0900 Subject: [PATCH] update rules --- gnovm/cmd/gno/repl.go | 97 +++++++++++++++++++++++++++++++++----- gnovm/cmd/gno/repl_test.go | 86 ++++++++++++++++++++++++++++++++- 2 files changed, 170 insertions(+), 13 deletions(-) diff --git a/gnovm/cmd/gno/repl.go b/gnovm/cmd/gno/repl.go index 6597a053e46..e7fb4e452e6 100644 --- a/gnovm/cmd/gno/repl.go +++ b/gnovm/cmd/gno/repl.go @@ -178,17 +178,37 @@ func handleEditor(line string) (string, bool) { func updateIndentLevel(line string, indentLevel int) int { openCount, closeCount := 0, 0 increaseIndent := false + inString := false + inComment := false + var stringChar rune for i, char := range line { - switch char { - case '{', '(', '[': - openCount++ - - if i < len(line)-1 && line[i+1] == '\n' { - increaseIndent = true + if !inString && !inComment { + switch char { + case '{', '(', '[': + openCount++ + if i < len(line)-1 && line[i+1] == '\n' { + increaseIndent = true + } + case '}', ')', ']': + closeCount++ + case '"', '\'': + inString = true + stringChar = char + case '/': + if i < len(line)-1 { + if line[i+1] == '/' { + break + } else if line[i+1] == '*' { + inComment = true + } + } } - case '}', ')', ']': - closeCount++ + } else if inString && char == stringChar { + inString = false + } else if inComment && i < len(line)-1 && char == '*' && line[i+1] == '/' { + inComment = false + i++ } } @@ -201,7 +221,7 @@ func updateIndentLevel(line string, indentLevel int) int { indentLevel++ } - if strings.HasSuffix(line, ":") { + if strings.HasSuffix(strings.TrimSpace(line), ":") { indentLevel++ } @@ -321,6 +341,7 @@ func peekChar() (byte, bool) { } } +// getChar reads a single byte from stdin. func getChar() byte { if lastInOk { lastInOk = false @@ -329,6 +350,11 @@ func getChar() byte { return <-input } +// putString writes a string to stdout. +func putString(s string) error { + return putChars([]byte(s)) +} + type terminalState struct { termios syscall.Termios } @@ -354,8 +380,9 @@ func makeRaw(fd int) (*terminalState, error) { return &oldState, nil } -// makeCbreak puts the terminal connected to the given file descriptor into cbreak mode -// and returns the previous state of the terminal so that it can be restored. +// makeCbreak puts the terminal connected to the given file descriptor into cbreak mode. +// cbreak mode is like raw mode, but it allows the user to interrupt the program with Ctrl-C. +// returns the previous state of the terminal so that it can be restored. func makeCbreak(fd int) (*terminalState, error) { var oldState terminalState // Get the current terminal settings @@ -384,3 +411,51 @@ func restore(fd int, state *terminalState) error { } return nil } + +// cursorBackward moves the cursor one character to the left (backward). +func cursorBackward() error { + chars := []byte{27, '[', '1', 'D'} + return putChars(chars) +} + +// cursorForward moves the cursor one character to the right (forward). +func cursorForward() error { + chars := []byte{27, '[', '1', 'C'} + return putChars(chars) +} + +var state *terminalState + +// exit exits the program. +func exit() { + if state != nil { + restore(syscall.Stdin, state) + black := "\033[0;0m" + fmt.Print(black) + } + os.Exit(1) +} + +type lineBuf struct { + length int + cursor int + buf []byte +} + +func newLineBuf(cap int) *lineBuf { + storage := make([]byte, cap) + return &lineBuf{ + length: 0, + cursor: 0, + buf: storage, + } +} + +func (l *lineBuf) Empty() bool { + return l.length == 0 +} + +func (l *lineBuf) Clear() { + l.length = 0 + l.cursor = 0 +} \ No newline at end of file diff --git a/gnovm/cmd/gno/repl_test.go b/gnovm/cmd/gno/repl_test.go index d7e9187039d..26710b27108 100644 --- a/gnovm/cmd/gno/repl_test.go +++ b/gnovm/cmd/gno/repl_test.go @@ -92,12 +92,42 @@ func TestUpdateIndentLevel(t *testing.T) { indentLevel: 1, want: 0, }, + { + name: "Test with brackets in string", + line: "ufmt.Println(\"{\")", + indentLevel: 0, + want: 0, + }, + { + name: "Test with brackets in single line comment", + line: "// { [ (", + indentLevel: 0, + want: 0, + }, + // { + // name: "Test with brackets in multi line comment", + // line: "/* { [ ( ) ] */", + // indentLevel: 0, + // want: 0, + // }, + // { + // name: "Test with brackets in string and comment", + // line: "ufmt.Println(\"{ [ ( ) ] }\") // { [ ( ) ] }", + // indentLevel: 0, + // want: 0, + // }, + // { + // name: "Test with brackets and comment", + // line: "func Foo() { // { [ ( ) ] }", + // indentLevel: 1, + // want: 1, + // }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := updateIndentLevel(tt.line, tt.indentLevel); got != tt.want { - t.Errorf("updateIndentLevel() = %v, want %v", got, tt.want) + t.Errorf("%s = %v, want %v", tt.name, got, tt.want) } }) } @@ -415,4 +445,56 @@ func TestRestore(t *testing.T) { if restoredState.termios != originalState.termios { t.Errorf("Terminal settings are not restored correctly") } -} \ No newline at end of file +} + +func TestCursorBackward(t *testing.T) { + // Capture stdout + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + err := cursorBackward() + if err != nil { + t.Errorf("cursorBackward failed: %v", err) + } + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + var buf bytes.Buffer + io.Copy(&buf, r) + + expected := "\x1b[1D" + actual := buf.String() + + if actual != expected { + t.Errorf("cursorBackward output mismatch - expected: %q, actual: %q", expected, actual) + } +} + +func TestCursorForward(t *testing.T) { + // Capture stdout + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + err := cursorForward() + if err != nil { + t.Errorf("cursorForward failed: %v", err) + } + + // Restore stdout + w.Close() + os.Stdout = oldStdout + + var buf bytes.Buffer + io.Copy(&buf, r) + + expected := "\x1b[1C" + actual := buf.String() + + if actual != expected { + t.Errorf("cursorForward output mismatch - expected: %q, actual: %q", expected, actual) + } +}