diff --git a/src/input_bar.go b/src/input_bar.go new file mode 100644 index 0000000..b9170b9 --- /dev/null +++ b/src/input_bar.go @@ -0,0 +1,59 @@ +package main + +import ( + "github.com/gdamore/tcell" +) + +type TyperInputRequest struct { + Text string + input string + cursorPos int + inputChannel chan string +} + +var currentInputRequest *TyperInputRequest + +func RequestInput(window *Window, text string) chan string { + request := &TyperInputRequest{ + Text: text, + input: "", + cursorPos: 0, + inputChannel: make(chan string), + } + + currentInputRequest = request + + window.CursorMode = CursorModeInputBar + + return request.inputChannel +} + +func IsRequestingInput() bool { + return currentInputRequest != nil +} + +func drawInputBar(window *Window) { + if currentInputRequest == nil { + return + } + + screen := window.screen + + inputBarStyle := tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorWhite) + + sizeX, sizeY := screen.Size() + + // Draw bar + for x := 0; x < sizeX; x++ { + char := ' ' + screen.SetContent(x, sizeY-1, char, nil, inputBarStyle) + } + + // Write text + for x := 0; x < len(currentInputRequest.Text); x++ { + screen.SetContent(x, sizeY-1, rune(currentInputRequest.Text[x]), nil, inputBarStyle) + } + for x := 0; x < len(currentInputRequest.input); x++ { + screen.SetContent(x+len(currentInputRequest.Text)+1, sizeY-1, rune(currentInputRequest.input[x]), nil, inputBarStyle) + } +} diff --git a/src/message_bar.go b/src/message_bar.go index 0ad56c0..944087d 100644 --- a/src/message_bar.go +++ b/src/message_bar.go @@ -48,6 +48,11 @@ func drawMessageBar(window *Window) { char = int32(messageToPrint[x]) } - screen.SetContent(x, sizeY-1, char, nil, messageBarStyle) + if currentInputRequest == nil { + screen.SetContent(x, sizeY-1, char, nil, messageBarStyle) + } else { + screen.SetContent(x, sizeY-2, char, nil, messageBarStyle) + } + } } diff --git a/src/top_menu.go b/src/top_menu.go index 8dc8b64..aea80ca 100644 --- a/src/top_menu.go +++ b/src/top_menu.go @@ -36,8 +36,27 @@ func initTopMenu() { buffer := CreateBuffer(fmt.Sprintf("New File %d", number)) window.textArea.CurrentBuffer = buffer window.SetCursorPos(0) + window.CursorMode = CursorModeBuffer case 1: + _ = RequestInput(window, "Save buffer to:") + PrintMessage(window, "Input requested...") case 2: + inputChannel := RequestInput(window, "File to open:") + go func() { + input := <-inputChannel + + if input == "" { + return + } + + buffer, err := CreateFileBuffer(input) + if err != nil { + PrintMessage(window, fmt.Sprintf("Could not open file: %s", err.Error())) + return + } + PrintMessage(window, fmt.Sprintf("Opening file: %s", input)) + window.textArea.CurrentBuffer = buffer + }() case 3: delete(Buffers, window.textArea.CurrentBuffer.Id) buffersSlice := slices.Collect(maps.Values(Buffers)) @@ -47,11 +66,12 @@ func initTopMenu() { } window.textArea.CurrentBuffer = buffersSlice[0] window.SetCursorPos(0) + window.CursorMode = CursorModeBuffer case 4: window.Close() + window.CursorMode = CursorModeBuffer } ClearDropdowns() - window.CursorMode = CursorModeBuffer }) ActiveDropdown = d window.CursorMode = CursorModeDropdown diff --git a/src/window.go b/src/window.go index 6cfbe26..9a0193a 100644 --- a/src/window.go +++ b/src/window.go @@ -13,7 +13,7 @@ const ( CursorModeDisabled CursorMode = iota CursorModeBuffer CursorModeDropdown - CursorModeMessageBar + CursorModeInputBar ) type Window struct { @@ -122,6 +122,11 @@ func (window *Window) Draw() { window.drawCurrentBuffer() } + // Draw input bar + if currentInputRequest != nil { + drawInputBar(window) + } + // Draw message bar drawMessageBar(window) @@ -131,6 +136,9 @@ func (window *Window) Draw() { // Draw cursor if window.CursorMode == CursorModeBuffer { window.screen.ShowCursor(window.GetAbsoluteCursorPos()) + } else if window.CursorMode == CursorModeInputBar { + _, sizeY := window.screen.Size() + window.screen.ShowCursor(len(currentInputRequest.Text)+len(currentInputRequest.input)+1, sizeY-1) } else { window.screen.HideCursor() } @@ -184,8 +192,14 @@ func (window *Window) input(ev *tcell.EventKey) { } } } else if ev.Key() == tcell.KeyEscape { - ClearDropdowns() - window.CursorMode = CursorModeBuffer + if window.CursorMode == CursorModeInputBar { + currentInputRequest.inputChannel <- "" + currentInputRequest = nil + window.CursorMode = CursorModeBuffer + } else { + ClearDropdowns() + window.CursorMode = CursorModeBuffer + } } else if ev.Key() == tcell.KeyCtrlC { // Close buffer key delete(Buffers, window.textArea.CurrentBuffer.Id) buffersSlice := slices.Collect(maps.Values(Buffers)) @@ -207,34 +221,40 @@ func (window *Window) input(ev *tcell.EventKey) { } } } else if ev.Key() == tcell.KeyBackspace2 { // Typing - str := window.textArea.CurrentBuffer.Contents - index := window.textArea.CursorPos + if window.CursorMode == CursorModeBuffer { + str := window.textArea.CurrentBuffer.Contents + index := window.textArea.CursorPos - if index != 0 { - str = str[:index-1] + str[index:] - window.textArea.CursorPos-- - window.textArea.CurrentBuffer.Contents = str + if index != 0 { + str = str[:index-1] + str[index:] + window.textArea.CursorPos-- + window.textArea.CurrentBuffer.Contents = str + } + } else if window.CursorMode == CursorModeInputBar { + str := currentInputRequest.input + index := currentInputRequest.cursorPos + + if index != 0 { + str = str[:index-1] + str[index:] + currentInputRequest.cursorPos-- + currentInputRequest.input = str + } } } else if ev.Key() == tcell.KeyTab { - if ActiveDropdown != nil { - return - } + if window.CursorMode == CursorModeBuffer { + str := window.textArea.CurrentBuffer.Contents + index := window.textArea.CursorPos - str := window.textArea.CurrentBuffer.Contents - index := window.textArea.CursorPos - - if index == len(str) { - str += "\t" - } else { - str = str[:index] + "\t" + str[index:] + if index == len(str) { + str += "\t" + } else { + str = str[:index] + "\t" + str[index:] + } + window.textArea.CursorPos++ + window.textArea.CurrentBuffer.Contents = str } - window.textArea.CursorPos++ - window.textArea.CurrentBuffer.Contents = str } else if ev.Key() == tcell.KeyEnter { - if ActiveDropdown != nil { - d := ActiveDropdown - d.Action(d.Selected) - } else { + if window.CursorMode == CursorModeBuffer { str := window.textArea.CurrentBuffer.Contents index := window.textArea.CursorPos @@ -245,22 +265,39 @@ func (window *Window) input(ev *tcell.EventKey) { } window.textArea.CursorPos++ window.textArea.CurrentBuffer.Contents = str + } else if window.CursorMode == CursorModeInputBar { + currentInputRequest.inputChannel <- currentInputRequest.input + currentInputRequest = nil + window.CursorMode = CursorModeBuffer + } else if window.CursorMode == CursorModeDropdown { + d := ActiveDropdown + d.Action(d.Selected) } } else if ev.Key() == tcell.KeyRune { - if ActiveDropdown != nil { - return - } + if window.CursorMode == CursorModeBuffer { + str := window.textArea.CurrentBuffer.Contents + index := window.textArea.CursorPos - str := window.textArea.CurrentBuffer.Contents - index := window.textArea.CursorPos + if index == len(str) { + str += string(ev.Rune()) + } else { + str = str[:index] + string(ev.Rune()) + str[index:] + } + window.textArea.CursorPos++ + window.textArea.CurrentBuffer.Contents = str + } else if window.CursorMode == CursorModeInputBar { + str := currentInputRequest.input + index := currentInputRequest.cursorPos - if index == len(str) { - str += string(ev.Rune()) - } else { - str = str[:index] + string(ev.Rune()) + str[index:] + if index == len(str) { + str += string(ev.Rune()) + } else { + str = str[:index] + string(ev.Rune()) + str[index:] + } + + currentInputRequest.cursorPos++ + currentInputRequest.input = str } - window.textArea.CursorPos++ - window.textArea.CurrentBuffer.Contents = str } }