mirror of
https://github.com/EnumeratedDev/typer.git
synced 2026-09-20 23:26:11 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3025fee2bb | ||
|
|
fe16b5c067 | ||
|
|
d69aba5c1a | ||
|
|
8d24988057 | ||
|
|
6cbe0e8ab2 | ||
|
|
f31650e67a | ||
|
|
a3138a9e86 | ||
|
|
e25916228c | ||
|
|
de19696b35 | ||
|
|
f30eb3c46f | ||
|
|
ab19981179 | ||
|
|
7af696cc20 |
@@ -6,6 +6,10 @@
|
||||
|  |  |
|
||||
|
||||
### Installation
|
||||
#### From a package manager:
|
||||
| Distribution | Package name |
|
||||
|:----------------------:|:---------------------|
|
||||
| Arch Linux/Artix Linux | `typer` from the AUR |
|
||||
#### From source:
|
||||
- Download `go` from your package manager or from the go website
|
||||
- Downlaod `which` from your package manager
|
||||
|
||||
@@ -5,5 +5,6 @@ selected_style_fallback: "default-fallback" # Style for 8-color capable terminal
|
||||
# Other
|
||||
show_top_menu: true
|
||||
show_line_index: true
|
||||
extend_line_index: false # Extend line index to the bottom of the screen
|
||||
buffer_info_message: "File: %f Cursor: (%x, %y, %p) Chars: %c"
|
||||
tab_indentation: 4 # Length of tab characters
|
||||
+14
-2
@@ -2,6 +2,9 @@ keybindings:
|
||||
- keybinding: "Ctrl-Q"
|
||||
cursor_modes: ["buffer"]
|
||||
command: "quit"
|
||||
- keybinding: "Ctrl-X"
|
||||
cursor_modes: ["buffer"]
|
||||
command: "cut"
|
||||
- keybinding: "Ctrl-C"
|
||||
cursor_modes: ["buffer"]
|
||||
command: "copy"
|
||||
@@ -14,9 +17,15 @@ keybindings:
|
||||
- keybinding: "Ctrl-O"
|
||||
cursor_modes: ["buffer"]
|
||||
command: "open"
|
||||
- keybinding: "Ctrl-R"
|
||||
- keybinding: "Ctrl-L"
|
||||
cursor_modes: ["buffer"]
|
||||
command: "reload"
|
||||
- keybinding: "Ctrl-F"
|
||||
cursor_modes: [ "buffer" ]
|
||||
command: "find"
|
||||
- keybinding: "Ctrl-R"
|
||||
cursor_modes: [ "buffer" ]
|
||||
command: "replace"
|
||||
- keybinding: "PgUp"
|
||||
cursor_modes: ["buffer"]
|
||||
command: "prev-buffer"
|
||||
@@ -37,4 +46,7 @@ keybindings:
|
||||
command: "menu-edit"
|
||||
- keybinding: "F3"
|
||||
cursor_modes: ["buffer","dropdown"]
|
||||
command: "menu-buffers"
|
||||
command: "menu-buffers"
|
||||
- keybinding: "Ctrl-E"
|
||||
cursor_modes: ["buffer"]
|
||||
command: "execute"
|
||||
+185
@@ -98,6 +98,16 @@ func (buffer *Buffer) Load() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Replace tilde with home directory
|
||||
if strings.HasPrefix(buffer.filename, "~/") {
|
||||
homedir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buffer.filename = filepath.Join(homedir, buffer.filename[2:])
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(buffer.filename)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -113,6 +123,16 @@ func (buffer *Buffer) Save() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Replace tilde with home directory
|
||||
if strings.HasPrefix(buffer.filename, "~/") {
|
||||
homedir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buffer.filename = filepath.Join(homedir, buffer.filename[2:])
|
||||
}
|
||||
|
||||
// Append new line character at end of buffer contents if not present
|
||||
if buffer.Contents[len(buffer.Contents)-1] != '\n' {
|
||||
buffer.Contents += "\n"
|
||||
@@ -164,6 +184,171 @@ func (buffer *Buffer) GetSelectedText() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (buffer *Buffer) CutText(window *Window) (string, int) {
|
||||
if buffer.Selection == nil {
|
||||
// Copy line
|
||||
copiedText := ""
|
||||
startOfLine := window.CurrentBuffer.CursorPos
|
||||
endOfLine := window.CurrentBuffer.CursorPos
|
||||
|
||||
// Add current letter to copied text
|
||||
if buffer.CursorPos < len(buffer.Contents) {
|
||||
copiedText = string(buffer.Contents[buffer.CursorPos])
|
||||
}
|
||||
|
||||
// Find end of line
|
||||
for i := buffer.CursorPos + 1; i < len(buffer.Contents); i++ {
|
||||
currentLetter := buffer.Contents[i]
|
||||
|
||||
endOfLine++
|
||||
copiedText += string(currentLetter)
|
||||
if currentLetter == '\n' {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find start of line
|
||||
for i := buffer.CursorPos - 1; i >= 0; i-- {
|
||||
currentLetter := buffer.Contents[i]
|
||||
if currentLetter != '\n' {
|
||||
startOfLine--
|
||||
copiedText = string(currentLetter) + copiedText
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Remove line from buffer contents
|
||||
buffer.Contents = buffer.Contents[:startOfLine] + buffer.Contents[endOfLine+1:]
|
||||
|
||||
return copiedText, 0
|
||||
} else {
|
||||
// Copy selection
|
||||
copiedText := buffer.GetSelectedText()
|
||||
|
||||
// Remove selected text
|
||||
edge1, edge2 := buffer.GetSelectionEdges()
|
||||
if edge2 == len(buffer.Contents) {
|
||||
edge2 = len(buffer.Contents) - 1
|
||||
}
|
||||
|
||||
buffer.Contents = buffer.Contents[:edge1] + buffer.Contents[edge2+1:]
|
||||
window.SetCursorPos(edge1)
|
||||
buffer.Selection = nil
|
||||
|
||||
return copiedText, 1
|
||||
}
|
||||
}
|
||||
|
||||
func (buffer *Buffer) CopyText() (string, int) {
|
||||
if buffer.Selection == nil {
|
||||
// Copy line
|
||||
copiedText := ""
|
||||
|
||||
// Add current letter to copied text
|
||||
if buffer.CursorPos < len(buffer.Contents) {
|
||||
copiedText = string(buffer.Contents[buffer.CursorPos])
|
||||
}
|
||||
|
||||
// Find end of line
|
||||
for i := buffer.CursorPos + 1; i < len(buffer.Contents); i++ {
|
||||
currentLetter := buffer.Contents[i]
|
||||
|
||||
copiedText += string(currentLetter)
|
||||
if currentLetter == '\n' {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find start of line
|
||||
for i := buffer.CursorPos - 1; i >= 0; i-- {
|
||||
currentLetter := buffer.Contents[i]
|
||||
if currentLetter != '\n' {
|
||||
copiedText = string(currentLetter) + copiedText
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return copiedText, 0
|
||||
} else {
|
||||
// Copy selection
|
||||
return buffer.GetSelectedText(), 1
|
||||
}
|
||||
}
|
||||
|
||||
func (buffer *Buffer) PasteText(window *Window, text string) {
|
||||
str := buffer.Contents
|
||||
|
||||
// Remove selected text
|
||||
if buffer.Selection != nil {
|
||||
edge1, edge2 := buffer.GetSelectionEdges()
|
||||
if edge2 == len(buffer.Contents) {
|
||||
edge2 = len(buffer.Contents) - 1
|
||||
}
|
||||
|
||||
str = str[:edge1] + str[edge2+1:]
|
||||
buffer.Contents = str
|
||||
window.SetCursorPos(edge1)
|
||||
buffer.Selection = nil
|
||||
}
|
||||
|
||||
index := buffer.CursorPos
|
||||
|
||||
if index == len(str) {
|
||||
str += text
|
||||
} else {
|
||||
str = str[:index] + text + str[index:]
|
||||
}
|
||||
buffer.Contents = str
|
||||
window.SetCursorPos(buffer.CursorPos + len(text))
|
||||
}
|
||||
|
||||
func (buffer *Buffer) FindSubstring(substring string, afterPos int) int {
|
||||
// Return no match if afterPos is larger than the buffer contents size
|
||||
if afterPos >= len(buffer.Contents) {
|
||||
return -1
|
||||
}
|
||||
|
||||
index := strings.Index(buffer.Contents[afterPos+1:], substring)
|
||||
|
||||
if index != -1 {
|
||||
index += afterPos + 1
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
func (buffer *Buffer) FindAndReplaceSubstring(substring, replacement string, afterPos int) int {
|
||||
index := buffer.FindSubstring(substring, afterPos)
|
||||
|
||||
// Return if substring isn't found
|
||||
if index == -1 {
|
||||
return -1
|
||||
}
|
||||
|
||||
// Replace substring with replacement string
|
||||
buffer.Contents = buffer.Contents[:index] + replacement + buffer.Contents[index+len(substring):]
|
||||
|
||||
return index
|
||||
}
|
||||
|
||||
func (buffer *Buffer) FindAndReplaceAll(substring, replacement string) int {
|
||||
replacements := 0
|
||||
index := 0
|
||||
for index != -1 {
|
||||
index = buffer.FindAndReplaceSubstring(substring, replacement, index)
|
||||
if index != -1 {
|
||||
replacements++
|
||||
}
|
||||
|
||||
if index == 0 {
|
||||
index++
|
||||
}
|
||||
}
|
||||
|
||||
return replacements
|
||||
}
|
||||
|
||||
func GetOpenFileBuffer(filename string) *Buffer {
|
||||
// Replace tilde with home directory
|
||||
if filename != "~" && strings.HasPrefix(filename, "~/") {
|
||||
|
||||
+264
-15
@@ -18,17 +18,37 @@ var commands = make(map[string]*Command)
|
||||
|
||||
func initCommands() {
|
||||
// Setup commands
|
||||
cutCmd := Command{
|
||||
cmd: "cut",
|
||||
run: func(window *Window, args ...string) {
|
||||
// Cut text from buffer
|
||||
copiedText, copyingMethod := window.CurrentBuffer.CutText(window)
|
||||
|
||||
// Put cut text to clipboard
|
||||
window.Clipboard = copiedText
|
||||
|
||||
// Send appropriate message and remove text depending on copying method
|
||||
if copyingMethod == 0 {
|
||||
PrintMessage(window, "Copied line to clipboard.")
|
||||
} else {
|
||||
PrintMessage(window, "Copied selection to clipboard.")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
copyCmd := Command{
|
||||
cmd: "copy",
|
||||
run: func(window *Window, args ...string) {
|
||||
if window.CurrentBuffer.Selection == nil {
|
||||
// Copy line
|
||||
_, line := window.GetCursorPos2D()
|
||||
window.Clipboard = strings.SplitAfter(window.CurrentBuffer.Contents, "\n")[line]
|
||||
// Copy text from buffer
|
||||
copiedText, copyingMethod := window.CurrentBuffer.CopyText()
|
||||
|
||||
// Put copied text to clipboard
|
||||
window.Clipboard = copiedText
|
||||
|
||||
// Send appropriate message depending on copying method
|
||||
if copyingMethod == 0 {
|
||||
PrintMessage(window, "Copied line to clipboard.")
|
||||
} else {
|
||||
// Copy selection
|
||||
window.Clipboard = window.CurrentBuffer.GetSelectedText()
|
||||
PrintMessage(window, "Copied selection to clipboard.")
|
||||
}
|
||||
},
|
||||
@@ -37,16 +57,10 @@ func initCommands() {
|
||||
pasteCmd := Command{
|
||||
cmd: "paste",
|
||||
run: func(window *Window, args ...string) {
|
||||
str := window.CurrentBuffer.Contents
|
||||
index := window.CurrentBuffer.CursorPos
|
||||
|
||||
if index == len(str) {
|
||||
str += window.Clipboard
|
||||
} else {
|
||||
str = str[:index] + window.Clipboard + str[index:]
|
||||
if window.Clipboard != "" {
|
||||
window.CurrentBuffer.PasteText(window, window.Clipboard)
|
||||
PrintMessage(window, "Pasted text to buffer.")
|
||||
}
|
||||
window.CurrentBuffer.Contents = str
|
||||
window.SetCursorPos(window.CurrentBuffer.CursorPos + len(window.Clipboard))
|
||||
},
|
||||
}
|
||||
|
||||
@@ -133,6 +147,132 @@ func initCommands() {
|
||||
},
|
||||
}
|
||||
|
||||
findCmd := Command{
|
||||
cmd: "find",
|
||||
run: func(window *Window, args ...string) {
|
||||
if len(args) >= 1 {
|
||||
input := args[0]
|
||||
|
||||
if input == "" {
|
||||
return
|
||||
}
|
||||
|
||||
pos := window.CurrentBuffer.FindSubstring(input, window.CurrentBuffer.CursorPos)
|
||||
if pos >= 0 {
|
||||
window.SetCursorPos(pos)
|
||||
PrintMessage(window, "Match found.")
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", input))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
inputChannel := RequestInput(window, "Substring to search for:", "")
|
||||
go func() {
|
||||
input := <-inputChannel
|
||||
|
||||
if input == "" {
|
||||
return
|
||||
}
|
||||
|
||||
pos := window.CurrentBuffer.FindSubstring(input, window.CurrentBuffer.CursorPos)
|
||||
if pos >= 0 {
|
||||
window.SetCursorPos(pos)
|
||||
PrintMessage(window, "Match found.")
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", input))
|
||||
}
|
||||
}()
|
||||
},
|
||||
}
|
||||
|
||||
replaceCmd := Command{
|
||||
cmd: "replace",
|
||||
run: func(window *Window, args ...string) {
|
||||
if len(args) >= 2 {
|
||||
findStr := args[0]
|
||||
replaceStr := args[1]
|
||||
|
||||
if findStr == "" {
|
||||
return
|
||||
}
|
||||
|
||||
pos := window.CurrentBuffer.FindAndReplaceSubstring(findStr, replaceStr, window.CurrentBuffer.CursorPos)
|
||||
if pos >= 0 {
|
||||
window.SetCursorPos(pos)
|
||||
PrintMessage(window, "Match replaced successfully.")
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
inputChannel := RequestInput(window, "Substring to search for:", "")
|
||||
findStr := <-inputChannel
|
||||
if findStr == "" {
|
||||
return
|
||||
}
|
||||
|
||||
inputChannel = RequestInput(window, "String to replace with:", "")
|
||||
replaceStr := <-inputChannel
|
||||
|
||||
pos := window.CurrentBuffer.FindAndReplaceSubstring(findStr, replaceStr, window.CurrentBuffer.CursorPos)
|
||||
if pos >= 0 {
|
||||
window.SetCursorPos(pos)
|
||||
PrintMessage(window, "Match replaced successfully.")
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
|
||||
}
|
||||
}()
|
||||
},
|
||||
}
|
||||
|
||||
replaceAllCmd := Command{
|
||||
cmd: "replace-all",
|
||||
run: func(window *Window, args ...string) {
|
||||
if len(args) >= 2 {
|
||||
findStr := args[0]
|
||||
replaceStr := args[1]
|
||||
|
||||
if findStr == "" {
|
||||
return
|
||||
}
|
||||
|
||||
replacements := window.CurrentBuffer.FindAndReplaceAll(findStr, replaceStr)
|
||||
if replacements > 0 {
|
||||
window.SetCursorPos(window.CurrentBuffer.CursorPos)
|
||||
PrintMessage(window, fmt.Sprintf("Replaced all %d matches successfully.", replacements))
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
inputChannel := RequestInput(window, "Substring to search for:", "")
|
||||
findStr := <-inputChannel
|
||||
if findStr == "" {
|
||||
return
|
||||
}
|
||||
|
||||
inputChannel = RequestInput(window, "String to replace with:", "")
|
||||
replaceStr := <-inputChannel
|
||||
|
||||
replacements := window.CurrentBuffer.FindAndReplaceAll(findStr, replaceStr)
|
||||
if replacements > 0 {
|
||||
window.SetCursorPos(window.CurrentBuffer.CursorPos)
|
||||
PrintMessage(window, fmt.Sprintf("Replaced all %d matches successfully.", replacements))
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
|
||||
}
|
||||
}()
|
||||
},
|
||||
}
|
||||
|
||||
prevBufferCmd := Command{
|
||||
cmd: "prev-buffer",
|
||||
run: func(window *Window, args ...string) {
|
||||
@@ -206,6 +346,66 @@ func initCommands() {
|
||||
},
|
||||
}
|
||||
|
||||
toggleTopBar := Command{
|
||||
cmd: "toggle-top-bar",
|
||||
run: func(window *Window, args ...string) {
|
||||
window.ShowTopMenu = !window.ShowTopMenu
|
||||
},
|
||||
}
|
||||
|
||||
toggleLineIndex := Command{
|
||||
cmd: "toggle-line-index",
|
||||
run: func(window *Window, args ...string) {
|
||||
window.ShowLineIndex = !window.ShowLineIndex
|
||||
},
|
||||
}
|
||||
|
||||
setStyleCmd := Command{
|
||||
cmd: "set-style",
|
||||
run: func(window *Window, args ...string) {
|
||||
if len(args) >= 1 {
|
||||
input := args[0]
|
||||
|
||||
if input == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if _, ok := AvailableStyles[input]; !ok {
|
||||
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
|
||||
return
|
||||
}
|
||||
|
||||
if ok := SetCurrentStyle(window.screen, input); ok {
|
||||
PrintMessage(window, fmt.Sprintf("Setting style to '%s'", input))
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
inputChannel := RequestInput(window, "Style to switch to:", "")
|
||||
go func() {
|
||||
input := <-inputChannel
|
||||
|
||||
if input == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if _, ok := AvailableStyles[input]; !ok {
|
||||
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
|
||||
return
|
||||
}
|
||||
|
||||
if ok := SetCurrentStyle(window.screen, input); ok {
|
||||
PrintMessage(window, fmt.Sprintf("Setting style to '%s'", input))
|
||||
} else {
|
||||
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
|
||||
}
|
||||
}()
|
||||
},
|
||||
}
|
||||
|
||||
menuFileCmd := Command{
|
||||
cmd: "menu-file",
|
||||
run: func(window *Window, args ...string) {
|
||||
@@ -250,20 +450,69 @@ func initCommands() {
|
||||
},
|
||||
}
|
||||
|
||||
executeCmd := Command{
|
||||
cmd: "execute",
|
||||
run: func(window *Window, args ...string) {
|
||||
inputChannel := RequestInput(window, "Run:", "")
|
||||
|
||||
go func() {
|
||||
input := strings.TrimSpace(<-inputChannel)
|
||||
|
||||
if input == "" {
|
||||
return
|
||||
}
|
||||
|
||||
var arguments []string
|
||||
|
||||
builder := &strings.Builder{}
|
||||
quoted := false
|
||||
for _, r := range input {
|
||||
if r == '"' {
|
||||
quoted = !quoted
|
||||
} else if !quoted && r == ' ' {
|
||||
arguments = append(arguments, builder.String())
|
||||
builder.Reset()
|
||||
} else {
|
||||
builder.WriteRune(r)
|
||||
}
|
||||
}
|
||||
if builder.Len() > 0 {
|
||||
arguments = append(arguments, builder.String())
|
||||
}
|
||||
|
||||
window.CursorMode = CursorModeBuffer
|
||||
|
||||
if len(arguments) == 1 {
|
||||
RunCommand(window, arguments[0])
|
||||
} else {
|
||||
RunCommand(window, arguments[0], arguments[1:]...)
|
||||
}
|
||||
}()
|
||||
},
|
||||
}
|
||||
|
||||
// Register commands
|
||||
commands["cut"] = &cutCmd
|
||||
commands["copy"] = ©Cmd
|
||||
commands["paste"] = &pasteCmd
|
||||
commands["save"] = &saveCmd
|
||||
commands["open"] = &openCmd
|
||||
commands["reload"] = &reloadCmd
|
||||
commands["find"] = &findCmd
|
||||
commands["replace"] = &replaceCmd
|
||||
commands["replace-all"] = &replaceAllCmd
|
||||
commands["prev-buffer"] = &prevBufferCmd
|
||||
commands["next-buffer"] = &nextBufferCmd
|
||||
commands["new-buffer"] = &newBufferCmd
|
||||
commands["close-buffer"] = &closeBufferCmd
|
||||
commands["toggle-top-bar"] = &toggleTopBar
|
||||
commands["toggle-line-index"] = &toggleLineIndex
|
||||
commands["set-style"] = &setStyleCmd
|
||||
commands["menu-file"] = &menuFileCmd
|
||||
commands["menu-edit"] = &menuEditCmd
|
||||
commands["menu-buffers"] = &menuBuffersCmd
|
||||
commands["quit"] = &quitCmd
|
||||
commands["execute"] = &executeCmd
|
||||
}
|
||||
|
||||
func RunCommand(window *Window, cmd string, args ...string) bool {
|
||||
|
||||
@@ -12,6 +12,7 @@ type TyperConfig struct {
|
||||
FallbackStyle string `yaml:"fallback_style,omitempty"`
|
||||
ShowTopMenu bool `yaml:"show_top_menu,omitempty"`
|
||||
ShowLineIndex bool `yaml:"show_line_index,omitempty"`
|
||||
ExtendLineIndex bool `yaml:"extend_line_index,omitempty"`
|
||||
BufferInfoMessage string `yaml:"buffer_info_message,omitempty"`
|
||||
TabIndentation int `yaml:"tab_indentation,omitempty"`
|
||||
}
|
||||
@@ -24,6 +25,7 @@ func readConfig() {
|
||||
FallbackStyle: "default-fallback",
|
||||
ShowTopMenu: true,
|
||||
ShowLineIndex: true,
|
||||
ExtendLineIndex: false,
|
||||
BufferInfoMessage: "File: %f Cursor: (%x, %y, %p) Chars: %c",
|
||||
TabIndentation: 4,
|
||||
}
|
||||
|
||||
+16
-9
@@ -12,16 +12,22 @@ func drawLineIndex(window *Window) {
|
||||
|
||||
lineIndexStyle := tcell.StyleDefault.Background(CurrentStyle.LineIndexBg).Foreground(CurrentStyle.LineIndexFg)
|
||||
|
||||
_, sizeY := screen.Size()
|
||||
|
||||
y := 0
|
||||
if window.ShowTopMenu {
|
||||
y = 1
|
||||
}
|
||||
|
||||
lineIndexSize := getLineIndexSize(window)
|
||||
|
||||
for lineIndex := 1 + buffer.OffsetY; lineIndex <= strings.Count(buffer.Contents, "\n")+1 && lineIndex < sizeY+buffer.OffsetY; lineIndex++ {
|
||||
_, bufferY1, _, bufferY2 := window.GetTextAreaDimensions()
|
||||
|
||||
lineIndex := 1 + buffer.OffsetY
|
||||
for y := bufferY1; y <= bufferY2; y++ {
|
||||
if lineIndex > strings.Count(buffer.Contents, "\n")+1 {
|
||||
if Config.ExtendLineIndex {
|
||||
for x := 0; x < lineIndexSize; x++ {
|
||||
screen.SetContent(x, y, ' ', nil, lineIndexStyle)
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for x := 0; x < lineIndexSize; x++ {
|
||||
screen.SetContent(x, y, ' ', nil, lineIndexStyle)
|
||||
@@ -30,7 +36,8 @@ func drawLineIndex(window *Window) {
|
||||
text := strconv.Itoa(lineIndex)
|
||||
|
||||
drawText(screen, lineIndexSize-len(text)-1, y, lineIndexSize, y, lineIndexStyle, text)
|
||||
y++
|
||||
|
||||
lineIndex++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -38,8 +38,11 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
for window.screen != nil {
|
||||
for !window.closed {
|
||||
window.Draw()
|
||||
window.ProcessEvents()
|
||||
}
|
||||
|
||||
window.screen.Fini()
|
||||
window.screen = nil
|
||||
}
|
||||
|
||||
+29
-25
@@ -46,8 +46,29 @@ type typerStyleYaml struct {
|
||||
Colors map[string]string `yaml:"colors"`
|
||||
}
|
||||
|
||||
var FallbackStyle = TyperStyle{
|
||||
Name: "fallback",
|
||||
Description: "Fallback style",
|
||||
StyleType: "8-color",
|
||||
|
||||
BufferAreaBg: tcell.ColorBlack,
|
||||
BufferAreaFg: tcell.ColorWhite,
|
||||
BufferAreaSel: tcell.ColorNavy,
|
||||
TopMenuBg: tcell.ColorWhite,
|
||||
TopMenuFg: tcell.ColorBlack,
|
||||
DropdownBg: tcell.ColorWhite,
|
||||
DropdownFg: tcell.ColorBlack,
|
||||
DropdownSel: tcell.ColorNavy,
|
||||
LineIndexBg: tcell.ColorWhite,
|
||||
LineIndexFg: tcell.ColorBlack,
|
||||
MessageBarBg: tcell.ColorWhite,
|
||||
MessageBarFg: tcell.ColorBlack,
|
||||
InputBarBg: tcell.ColorWhite,
|
||||
InputBarFg: tcell.ColorBlack,
|
||||
}
|
||||
|
||||
var AvailableStyles = make(map[string]TyperStyle)
|
||||
var CurrentStyle TyperStyle
|
||||
var CurrentStyle = FallbackStyle
|
||||
|
||||
func readStyles() {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
@@ -145,7 +166,7 @@ func readStyleYamlFile(filepath string) (TyperStyle, error) {
|
||||
return style, nil
|
||||
}
|
||||
|
||||
func SetCurrentStyle(screen tcell.Screen) {
|
||||
func SetCurrentStyle(screen tcell.Screen, styleName string) bool {
|
||||
availableTypes := make([]string, 1)
|
||||
availableTypes[0] = "8-color"
|
||||
if screen.Colors() >= 16 {
|
||||
@@ -158,30 +179,13 @@ func SetCurrentStyle(screen tcell.Screen) {
|
||||
availableTypes = append(availableTypes, "true-color")
|
||||
}
|
||||
|
||||
if style, ok := AvailableStyles[Config.SelectedStyle]; ok && slices.Index(availableTypes, style.StyleType) != -1 {
|
||||
if style, ok := AvailableStyles[styleName]; ok && slices.Index(availableTypes, style.StyleType) != -1 {
|
||||
CurrentStyle = style
|
||||
} else if style, ok := AvailableStyles[Config.FallbackStyle]; ok {
|
||||
CurrentStyle = style
|
||||
} else {
|
||||
CurrentStyle = TyperStyle{
|
||||
Name: "fallback",
|
||||
Description: "Fallback style",
|
||||
StyleType: "8-color",
|
||||
|
||||
BufferAreaBg: tcell.ColorBlack,
|
||||
BufferAreaFg: tcell.ColorWhite,
|
||||
BufferAreaSel: tcell.ColorNavy,
|
||||
TopMenuBg: tcell.ColorWhite,
|
||||
TopMenuFg: tcell.ColorBlack,
|
||||
DropdownBg: tcell.ColorWhite,
|
||||
DropdownFg: tcell.ColorBlack,
|
||||
DropdownSel: tcell.ColorNavy,
|
||||
LineIndexBg: tcell.ColorWhite,
|
||||
LineIndexFg: tcell.ColorBlack,
|
||||
MessageBarBg: tcell.ColorWhite,
|
||||
MessageBarFg: tcell.ColorBlack,
|
||||
InputBarBg: tcell.ColorWhite,
|
||||
InputBarFg: tcell.ColorBlack,
|
||||
}
|
||||
screen.SetStyle(tcell.StyleDefault.Foreground(CurrentStyle.BufferAreaFg).Background(CurrentStyle.BufferAreaBg))
|
||||
screen.Sync()
|
||||
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+7
-3
@@ -56,11 +56,13 @@ func initTopMenu() {
|
||||
y++
|
||||
}
|
||||
|
||||
d := CreateDropdownMenu([]string{"Copy", "Paste"}, 0, y, 0, func(i int) {
|
||||
d := CreateDropdownMenu([]string{"Cut", "Copy", "Paste"}, 0, y, 0, func(i int) {
|
||||
switch i {
|
||||
case 0:
|
||||
RunCommand(window, "copy")
|
||||
RunCommand(window, "cut")
|
||||
case 1:
|
||||
RunCommand(window, "copy")
|
||||
case 2:
|
||||
RunCommand(window, "paste")
|
||||
}
|
||||
ClearDropdowns()
|
||||
@@ -123,7 +125,9 @@ func drawTopMenu(window *Window) {
|
||||
|
||||
// Draw buffer info
|
||||
bufferInfoMsg := getBufferInfoMsg(window)
|
||||
drawText(screen, sizeX-len(bufferInfoMsg)-1, 0, sizeX-1, 0, topMenuStyle, bufferInfoMsg)
|
||||
if sizeX-len(bufferInfoMsg)-1 > currentX+2 {
|
||||
drawText(screen, sizeX-len(bufferInfoMsg)-1, 0, sizeX-1, 0, topMenuStyle, bufferInfoMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func getBufferInfoMsg(window *Window) string {
|
||||
|
||||
+23
-10
@@ -36,6 +36,8 @@ type Window struct {
|
||||
CurrentBuffer *Buffer
|
||||
|
||||
screen tcell.Screen
|
||||
|
||||
closed bool
|
||||
}
|
||||
|
||||
var mouseHeld = false
|
||||
@@ -70,16 +72,22 @@ func CreateWindow() (*Window, error) {
|
||||
log.Fatalf("Failed to initialize screen: %s", err)
|
||||
}
|
||||
|
||||
// Set screen style
|
||||
SetCurrentStyle(screen)
|
||||
screen.SetStyle(tcell.StyleDefault.Foreground(CurrentStyle.BufferAreaFg).Background(CurrentStyle.BufferAreaBg))
|
||||
|
||||
// Enable mouse
|
||||
screen.EnableMouse()
|
||||
|
||||
// Set window screen field
|
||||
window.screen = screen
|
||||
|
||||
// Try to set screen style to selected one
|
||||
if ok := SetCurrentStyle(screen, Config.SelectedStyle); !ok {
|
||||
// Try to set screen style to selected fallback one
|
||||
if ok := SetCurrentStyle(screen, Config.FallbackStyle); !ok {
|
||||
// Use hard-coded fallback style
|
||||
screen.SetStyle(tcell.StyleDefault.Foreground(CurrentStyle.BufferAreaFg).Background(CurrentStyle.BufferAreaBg))
|
||||
PrintMessage(&window, "Could not set style either to selected one nor to fallback one!")
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize top menu
|
||||
initTopMenu()
|
||||
|
||||
@@ -126,7 +134,9 @@ func (window *Window) Draw() {
|
||||
|
||||
// Update screen
|
||||
window.screen.Show()
|
||||
}
|
||||
|
||||
func (window *Window) ProcessEvents() {
|
||||
// Poll event
|
||||
ev := window.screen.PollEvent()
|
||||
|
||||
@@ -136,13 +146,13 @@ func (window *Window) Draw() {
|
||||
window.screen.Sync()
|
||||
window.SyncBufferOffset()
|
||||
case *tcell.EventMouse:
|
||||
window.mouseInput(ev)
|
||||
window.handleMouseInput(ev)
|
||||
case *tcell.EventKey:
|
||||
window.input(ev)
|
||||
window.handleKeyInput(ev)
|
||||
}
|
||||
}
|
||||
|
||||
func (window *Window) input(ev *tcell.EventKey) {
|
||||
func (window *Window) handleKeyInput(ev *tcell.EventKey) {
|
||||
if ev.Key() == tcell.KeyRight { // Navigation Keys
|
||||
if window.CursorMode == CursorModeBuffer {
|
||||
// Get original cursor position
|
||||
@@ -515,7 +525,7 @@ func (window *Window) input(ev *tcell.EventKey) {
|
||||
}
|
||||
}
|
||||
|
||||
func (window *Window) mouseInput(ev *tcell.EventMouse) {
|
||||
func (window *Window) handleMouseInput(ev *tcell.EventMouse) {
|
||||
mouseX, mouseY := ev.Position()
|
||||
|
||||
// Left click was pressed
|
||||
@@ -635,8 +645,11 @@ func (window *Window) mouseInput(ev *tcell.EventMouse) {
|
||||
}
|
||||
|
||||
func (window *Window) Close() {
|
||||
window.screen.Fini()
|
||||
window.screen = nil
|
||||
window.closed = true
|
||||
err := window.screen.PostEvent(tcell.NewEventInterrupt(nil))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (window *Window) GetTextAreaDimensions() (int, int, int, int) {
|
||||
|
||||
Reference in New Issue
Block a user