diff --git a/README.md b/README.md
index a730de81..6616026d 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,16 @@ It's a great library but it's been abandoned
for quite a while.
This project aims to continue its development.
+The library has been rewritten in many aspects, fixing existing bugs and adding new essential functionality.
+
+Most notable changes include:
+- Support for custom syntax highlighting with a lexer
+- Multiline editing
+- A scrolling buffer is used for displaying the current content which makes it possible to edit text of arbitrary length (only the visible part of the text is rendered)
+- Support for automatic indentation when pressing Enter and the input is incomplete or for executing the input when it is complete. This is determined by a custom callback function.
+
+I highly encourage you to see the [changelog](CHANGELOG.md) which fully documents the changes that have been made.
+
---
A library for building powerful interactive prompts inspired by [python-prompt-toolkit](https://github.com/jonathanslenders/python-prompt-toolkit),
@@ -49,9 +59,21 @@ func main() {
## Features
+### Automatic indentation with a custom callback
+
+![automatic indentation](readme/automatic-indentation.gif)
+
+### Multiline editing with scrolling
+
+![multiline editing](readme/multiline-editing.gif)
+
+### Custom syntax highlighting
+
+![syntax highlighting](readme/syntax-highlighting.gif)
+
### Powerful auto-completion
-[![demo](https://github.com/c-bata/assets/raw/master/go-prompt/kube-prompt.gif)](https://github.com/c-bata/kube-prompt)
+[![autocompletion](https://github.com/c-bata/assets/raw/master/go-prompt/kube-prompt.gif)](https://github.com/c-bata/kube-prompt)
(This is a GIF animation of kube-prompt.)
diff --git a/_example/README.md b/_example/README.md
index 02fe6057..f32f422e 100644
--- a/_example/README.md
+++ b/_example/README.md
@@ -9,6 +9,12 @@ Uses a custom lexer that colours every character with an even index green.
Shows you how to hook up a custom lexer for syntax highlighting.
+## automatic indenter
+
+Inserts a newline and indentation when the Enter key is pressed unless the input ends with a curly brace `}` and the amount of opening and ending braces is the same (then it gets printed).
+
+Shows you how to define a custom callback which determines whether the input is complete and should be executed or a newline with indentation should be inserted (after Enter has been pressed).
+
## bang-executor
Inserts a newline when the Enter key is pressed unless the input ends with an exclamation point `!` (then it gets printed).
diff --git a/_example/automatic-indenter/main.go b/_example/automatic-indenter/main.go
new file mode 100644
index 00000000..f14f4646
--- /dev/null
+++ b/_example/automatic-indenter/main.go
@@ -0,0 +1,44 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+ "unicode/utf8"
+
+ "github.com/elk-language/go-prompt"
+)
+
+func main() {
+ p := prompt.New(
+ executor,
+ prompt.WithPrefix(">>> "),
+ prompt.WithExecuteOnEnterCallback(ExecuteOnEnter),
+ )
+
+ p.Run()
+}
+
+func ExecuteOnEnter(input string, indentSize int) (int, bool) {
+ lines := strings.SplitAfter(input, "\n")
+ var spaces int
+ if len(lines) > 0 {
+ lastLine := lines[len(lines)-1]
+ for _, char := range lastLine {
+ if char == '}' {
+ spaces -= 2 * indentSize
+ break
+ }
+ if char != ' ' {
+ break
+ }
+ spaces++
+ }
+ }
+
+ char, _ := utf8.DecodeLastRuneInString(input)
+ return 1 + spaces/indentSize, char == '}' && strings.Count(input, "}") == strings.Count(input, "{")
+}
+
+func executor(s string) {
+ fmt.Println("Your input: " + s)
+}
diff --git a/_example/bang-executor/main.go b/_example/bang-executor/main.go
index b6bbb3c0..df4caf6f 100644
--- a/_example/bang-executor/main.go
+++ b/_example/bang-executor/main.go
@@ -23,5 +23,5 @@ func ExecuteOnEnter(input string, indentSize int) (int, bool) {
}
func executor(s string) {
- fmt.Println("You printed: " + s)
+ fmt.Println("Your input: " + s)
}
diff --git a/_example/build.sh b/_example/build.sh
index 8c561684..6472f4e9 100755
--- a/_example/build.sh
+++ b/_example/build.sh
@@ -12,3 +12,4 @@ go build -o ${BIN_DIR}/simple-echo ${DIR}/simple-echo/main.go
go build -o ${BIN_DIR}/simple-echo-cjk-cyrillic ${DIR}/simple-echo/cjk-cyrillic/main.go
go build -o ${BIN_DIR}/even-lexer ${DIR}/even-lexer/main.go
go build -o ${BIN_DIR}/bang-executor ${DIR}/bang-executor/main.go
+go build -o ${BIN_DIR}/automatic-indenter ${DIR}/automatic-indenter/main.go
diff --git a/_example/even-lexer/main.go b/_example/even-lexer/main.go
index 0ca21956..3805848f 100644
--- a/_example/even-lexer/main.go
+++ b/_example/even-lexer/main.go
@@ -2,6 +2,7 @@ package main
import (
"fmt"
+ "unicode"
"unicode/utf8"
"github.com/elk-language/go-prompt"
@@ -11,13 +12,15 @@ import (
func main() {
p := prompt.New(
executor,
- prompt.WithLexer(prompt.NewEagerLexer(lexer)),
+ prompt.WithLexer(prompt.NewEagerLexer(wordLexer)),
+ prompt.WithLexer(prompt.NewEagerLexer(charLexer)), // the last one overrides the other
)
p.Run()
}
-func lexer(line string) []prompt.Token {
+// colors every other character green
+func charLexer(line string) []prompt.Token {
var elements []prompt.Token
for i, value := range line {
@@ -37,6 +40,47 @@ func lexer(line string) []prompt.Token {
return elements
}
+// colors every other word green
+func wordLexer(line string) []prompt.Token {
+ if len(line) == 0 {
+ return nil
+ }
+
+ var elements []prompt.Token
+ var currentByte strings.ByteNumber
+ var wordIndex int
+ var lastChar rune
+
+ var color prompt.Color
+ for i, char := range line {
+ currentByte = strings.ByteNumber(i)
+ if unicode.IsSpace(char) {
+ if wordIndex%2 == 0 {
+ color = prompt.Green
+ } else {
+ color = prompt.White
+ }
+
+ element := prompt.NewSimpleToken(color, currentByte)
+ elements = append(elements, element)
+ wordIndex++
+ continue
+ }
+ lastChar = char
+ }
+ if !unicode.IsSpace(lastChar) {
+ if wordIndex%2 == 0 {
+ color = prompt.Green
+ } else {
+ color = prompt.White
+ }
+ element := prompt.NewSimpleToken(color, currentByte)
+ elements = append(elements, element)
+ }
+
+ return elements
+}
+
func executor(s string) {
- fmt.Println("You printed: " + s)
+ fmt.Println("Your input: " + s)
}
diff --git a/readme/automatic-indentation.gif b/readme/automatic-indentation.gif
new file mode 100644
index 00000000..eb204d33
Binary files /dev/null and b/readme/automatic-indentation.gif differ
diff --git a/readme/multiline-editing.gif b/readme/multiline-editing.gif
new file mode 100644
index 00000000..96a5071e
Binary files /dev/null and b/readme/multiline-editing.gif differ
diff --git a/readme/syntax-highlighting.gif b/readme/syntax-highlighting.gif
new file mode 100644
index 00000000..d358a62e
Binary files /dev/null and b/readme/syntax-highlighting.gif differ