diff --git a/config/keybindings.yml b/config/keybindings.yml index f1be915..fc5b4c8 100644 --- a/config/keybindings.yml +++ b/config/keybindings.yml @@ -22,7 +22,7 @@ keybindings: command: "prev-buffer" - keybinding: "PgDn" cursor_modes: ["buffer"] - command: "prev-buffer" + command: "next-buffer" - keybinding: "Ctrl-N" cursor_modes: ["buffer"] command: "new-buffer" diff --git a/src/buffer.go b/src/buffer.go index ebaa248..c9abc29 100644 --- a/src/buffer.go +++ b/src/buffer.go @@ -9,7 +9,6 @@ import ( ) type Buffer struct { - Id int Name string Contents string @@ -27,8 +26,25 @@ type Selection struct { selectionEnd int } -var Buffers = make(map[int]*Buffer) -var LastBufferId int +var Buffers = make([]*Buffer, 0) + +func GetBufferByName(name string) *Buffer { + for _, buffer := range Buffers { + if buffer.Name == name { + return buffer + } + } + return nil +} + +func GetBufferByFilename(filename string) *Buffer { + for _, buffer := range Buffers { + if buffer.filename == filename { + return buffer + } + } + return nil +} func drawBuffer(window *Window) { buffer := window.CurrentBuffer @@ -204,8 +220,15 @@ func CreateFileBuffer(filename string, openNonExistentFile bool) (*Buffer, error } } + if GetBufferByName(filename) != nil { + return nil, fmt.Errorf("a buffer with the name (%s) is already open", filename) + } + + if GetBufferByFilename(abs) != nil { + return nil, fmt.Errorf("%s is already open in another buffer", filename) + } + buffer := Buffer{ - Id: LastBufferId + 1, Name: filename, Contents: "", CursorPos: 0, @@ -222,15 +245,13 @@ func CreateFileBuffer(filename string, openNonExistentFile bool) (*Buffer, error } } - Buffers[buffer.Id] = &buffer - LastBufferId++ + Buffers = append(Buffers, &buffer) return &buffer, nil } -func CreateBuffer(bufferName string) *Buffer { +func CreateBuffer(bufferName string) (*Buffer, error) { buffer := Buffer{ - Id: LastBufferId + 1, Name: bufferName, Contents: "", CursorPos: 0, @@ -238,8 +259,11 @@ func CreateBuffer(bufferName string) *Buffer { filename: "", } - Buffers[buffer.Id] = &buffer - LastBufferId++ + if GetBufferByName(bufferName) != nil { + return nil, fmt.Errorf("a buffer with the name (%s) is already open", bufferName) + } - return &buffer + Buffers = append(Buffers, &buffer) + + return &buffer, nil } diff --git a/src/command.go b/src/command.go index 4b8c457..30354b9 100644 --- a/src/command.go +++ b/src/command.go @@ -3,8 +3,8 @@ package main import ( "fmt" "log" - "maps" "slices" + "strconv" "strings" ) @@ -140,15 +140,14 @@ func initCommands() { return } - buffers := slices.Collect(maps.Values(Buffers)) - index := slices.Index(buffers, window.CurrentBuffer) + index := slices.Index(Buffers, window.CurrentBuffer) index-- if index < 0 { index = 0 } - window.CurrentBuffer = buffers[index] + window.CurrentBuffer = Buffers[index] }, } @@ -159,29 +158,28 @@ func initCommands() { return } - buffers := slices.Collect(maps.Values(Buffers)) - index := slices.Index(buffers, window.CurrentBuffer) + index := slices.Index(Buffers, window.CurrentBuffer) index++ - if index >= len(buffers) { - index = len(buffers) - 1 + if index >= len(Buffers) { + index = len(Buffers) - 1 } - window.CurrentBuffer = buffers[index] + window.CurrentBuffer = Buffers[index] }, } newBufferCmd := Command{ cmd: "new-buffer", run: func(window *Window, args ...string) { - number := 1 - for _, buffer := range Buffers { - if strings.HasPrefix(buffer.Name, "New File ") { - number++ + for i := 1; true; i++ { + buffer, err := CreateBuffer("New Buffer " + strconv.Itoa(i)) + if err == nil { + window.CurrentBuffer = buffer + break } } - buffer := CreateBuffer(fmt.Sprintf("New File %d", number)) - window.CurrentBuffer = buffer + window.CursorMode = CursorModeBuffer }, } @@ -189,13 +187,17 @@ func initCommands() { closeBufferCmd := Command{ cmd: "close-buffer", run: func(window *Window, args ...string) { - delete(Buffers, window.CurrentBuffer.Id) - buffersSlice := slices.Collect(maps.Values(Buffers)) - if len(buffersSlice) == 0 { + bufferIndex := slices.Index(Buffers, window.CurrentBuffer) + Buffers = DeleteFromSlice(Buffers, bufferIndex) + if len(Buffers) == 0 { window.Close() return } - window.CurrentBuffer = buffersSlice[0] + if bufferIndex >= len(Buffers) { + window.CurrentBuffer = Buffers[bufferIndex-1] + } else { + window.CurrentBuffer = Buffers[bufferIndex] + } window.CursorMode = CursorModeBuffer }, } diff --git a/src/main.go b/src/main.go index aec86da..b2bda33 100644 --- a/src/main.go +++ b/src/main.go @@ -24,16 +24,16 @@ func main() { } if len(os.Args) > 1 { - for _, file := range os.Args[1:] { + for i, file := range os.Args[1:] { b, err := CreateFileBuffer(file, true) if err != nil { PrintMessage(window, "Could not open file: "+file) continue } - if window.CurrentBuffer.Name == "New File 1" { - delete(Buffers, window.CurrentBuffer.Id) + if i == 0 { window.CurrentBuffer = b + Buffers = Buffers[1:] } } } diff --git a/src/top_menu.go b/src/top_menu.go index 842617b..78d2cbd 100644 --- a/src/top_menu.go +++ b/src/top_menu.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/gdamore/tcell/v2" "path/filepath" - "slices" "strconv" "strings" ) @@ -82,27 +81,16 @@ func initTopMenu() { } buffersSlice := make([]string, 0) - for _, buffer := range Buffers { + for i, buffer := range Buffers { if window.CurrentBuffer == buffer { - buffersSlice = append(buffersSlice, fmt.Sprintf("[%d] * %s", buffer.Id, buffer.Name)) + buffersSlice = append(buffersSlice, fmt.Sprintf("[%d] * %s", i+1, buffer.Name)) } else { - buffersSlice = append(buffersSlice, fmt.Sprintf("[%d] %s", buffer.Id, buffer.Name)) + buffersSlice = append(buffersSlice, fmt.Sprintf("[%d] %s", i+1, buffer.Name)) } } - slices.Sort(buffersSlice) - d := CreateDropdownMenu(buffersSlice, 0, y, 0, func(i int) { - start := strings.Index(buffersSlice[i], "[") - end := strings.Index(buffersSlice[i], "]") - - id, err := strconv.Atoi(buffersSlice[i][start+1 : end]) - if err != nil { - PrintMessage(window, fmt.Sprintf("Cannot convert buffer id '%s' to int", buffersSlice[i][start:end])) - return - } - - window.CurrentBuffer = Buffers[id] + window.CurrentBuffer = Buffers[i] ClearDropdowns() window.CursorMode = CursorModeBuffer }) diff --git a/src/utils.go b/src/utils.go index 9f7e274..d84a7ea 100644 --- a/src/utils.go +++ b/src/utils.go @@ -53,3 +53,15 @@ func drawBox(s tcell.Screen, x1, y1, x2, y2 int, style tcell.Style) { drawText(s, x1+1, y1+1, x2-1, y2-1, style, " ") } + +func DeleteFromSlice[T any](slice []T, i int) []T { + if i >= len(slice) { + return slice + } else if i < 0 { + return slice + } else if i == len(slice)-1 { + return slice[:len(slice)-1] + } else { + return append(slice[:i], slice[i+1:]...) + } +} diff --git a/src/window.go b/src/window.go index 16a4a31..177e4bc 100644 --- a/src/window.go +++ b/src/window.go @@ -4,6 +4,7 @@ import ( "github.com/gdamore/tcell/v2" "log" "slices" + "strconv" "strings" "time" "unicode" @@ -52,8 +53,11 @@ func CreateWindow() (*Window, error) { } // Create empty buffer if nil - if window.CurrentBuffer == nil { - window.CurrentBuffer = CreateBuffer("New File 1") + for i := 1; window.CurrentBuffer == nil; i++ { + buffer, err := CreateBuffer("New Buffer " + strconv.Itoa(i)) + if err == nil { + window.CurrentBuffer = buffer + } } // Create tcell screen