src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

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 }