buffer.go (2278B)
1 package buffer 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "time" 8 9 "code.dwrz.net/src/pkg/editor/buffer/line" 10 "code.dwrz.net/src/pkg/log" 11 ) 12 13 type Buffer struct { 14 cursor *Cursor 15 lines []*line.Line 16 log *log.Logger 17 file *os.File 18 name string 19 offset *offset 20 stat os.FileInfo 21 saved time.Time 22 } 23 24 // Offset is the first visible column and row of the buffer. 25 type offset struct { 26 glyph int 27 line int 28 } 29 30 // TODO: return true if the underlying file has changed. 31 // Use file size and mod time. 32 // Need to distinguish underlying file changes from changes made via edits. 33 func (b *Buffer) Changed() { 34 return 35 } 36 37 func (b *Buffer) Close() error { 38 return b.file.Close() 39 } 40 41 func (b *Buffer) CursorLine() *line.Line { 42 return b.lines[b.cursor.line] 43 } 44 45 func (b *Buffer) Line(i int) *line.Line { 46 return b.lines[i] 47 } 48 49 func (b *Buffer) Name() string { 50 return b.name 51 } 52 53 type NewBufferParams struct { 54 Name string 55 Log *log.Logger 56 } 57 58 func Create(p NewBufferParams) (*Buffer, error) { 59 var b = &Buffer{ 60 cursor: &Cursor{}, 61 lines: []*line.Line{}, 62 log: p.Log, 63 name: p.Name, 64 offset: &offset{}, 65 } 66 67 // Create the file. 68 f, err := os.Create(b.name) 69 if err != nil { 70 return nil, fmt.Errorf("failed to create file: %w", err) 71 } 72 b.file = f 73 74 // Scan the lines. 75 scanner := bufio.NewScanner(f) 76 for scanner.Scan() { 77 b.lines = append(b.lines, line.New(scanner.Text())) 78 } 79 if err := scanner.Err(); err != nil { 80 return nil, fmt.Errorf("failed to scan: %v", err) 81 } 82 83 // Add a line to write in, if the file is empty. 84 if len(b.lines) == 0 { 85 b.lines = append(b.lines, &line.Line{}) 86 } 87 88 return b, nil 89 } 90 91 func Open(p NewBufferParams) (*Buffer, error) { 92 var b = &Buffer{ 93 cursor: &Cursor{}, 94 lines: []*line.Line{}, 95 log: p.Log, 96 name: p.Name, 97 offset: &offset{}, 98 } 99 100 // Open the file. 101 f, err := os.Open(b.name) 102 if err != nil { 103 return nil, fmt.Errorf("failed to open file: %w", err) 104 } 105 b.file = f 106 107 // Scan the lines. 108 scanner := bufio.NewScanner(f) 109 for scanner.Scan() { 110 b.lines = append(b.lines, line.New(scanner.Text())) 111 } 112 if err := scanner.Err(); err != nil { 113 return nil, fmt.Errorf("failed to scan: %v", err) 114 } 115 116 // Add a line to write in, if the file is empty. 117 if len(b.lines) == 0 { 118 b.lines = append(b.lines, &line.Line{}) 119 } 120 121 return b, nil 122 }