]> git.lizzy.rs Git - micro.git/blob - cmd/micro/buffer.go
Rename to tabstospaces for consistency
[micro.git] / cmd / micro / buffer.go
1 package main
2
3 import (
4         "github.com/vinzmay/go-rope"
5         "io/ioutil"
6         "strings"
7 )
8
9 // Buffer stores the text for files that are loaded into the text editor
10 // It uses a rope to efficiently store the string and contains some
11 // simple functions for saving and wrapper functions for modifying the rope
12 type Buffer struct {
13         // The eventhandler for undo/redo
14         *EventHandler
15
16         // Stores the text of the buffer
17         r *rope.Rope
18
19         Cursor Cursor
20
21         // Path to the file on disk
22         Path string
23         // Name of the buffer on the status line
24         Name string
25
26         IsModified bool
27
28         // Provide efficient and easy access to text and lines so the rope String does not
29         // need to be constantly recalculated
30         // These variables are updated in the update() function
31         Lines    []string
32         NumLines int
33
34         // Syntax highlighting rules
35         rules []SyntaxRule
36         // The buffer's filetype
37         FileType string
38 }
39
40 // NewBuffer creates a new buffer from `txt` with path and name `path`
41 func NewBuffer(txt, path string) *Buffer {
42         b := new(Buffer)
43         if txt == "" {
44                 b.r = new(rope.Rope)
45         } else {
46                 b.r = rope.New(txt)
47         }
48         b.Path = path
49         b.Name = path
50
51         // Put the cursor at the first spot
52         b.Cursor = Cursor{
53                 x:   0,
54                 y:   0,
55                 Buf: b,
56         }
57
58         b.EventHandler = NewEventHandler(b)
59
60         b.Update()
61         b.UpdateRules()
62
63         return b
64 }
65
66 // UpdateRules updates the syntax rules and filetype for this buffer
67 // This is called when the colorscheme changes
68 func (b *Buffer) UpdateRules() {
69         b.rules, b.FileType = GetRules(b)
70 }
71
72 func (b *Buffer) String() string {
73         if b.r.Len() != 0 {
74                 return b.r.String()
75         }
76         return ""
77 }
78
79 // Update fetches the string from the rope and updates the `text` and `lines` in the buffer
80 func (b *Buffer) Update() {
81         b.Lines = strings.Split(b.String(), "\n")
82         b.NumLines = len(b.Lines)
83 }
84
85 // Save saves the buffer to its default path
86 func (b *Buffer) Save() error {
87         return b.SaveAs(b.Path)
88 }
89
90 // SaveAs saves the buffer to a specified path (filename), creating the file if it does not exist
91 func (b *Buffer) SaveAs(filename string) error {
92         b.UpdateRules()
93         data := []byte(b.String())
94         err := ioutil.WriteFile(filename, data, 0644)
95         if err == nil {
96                 b.IsModified = false
97         }
98         return err
99 }
100
101 // This directly inserts value at idx, bypassing all undo/redo
102 func (b *Buffer) insert(idx int, value string) {
103         b.IsModified = true
104         b.r = b.r.Insert(idx, value)
105         b.Update()
106 }
107
108 // Remove a slice of the rope from start to end (exclusive)
109 // Returns the string that was removed
110 // This directly removes from start to end from the buffer, bypassing all undo/redo
111 func (b *Buffer) remove(start, end int) string {
112         b.IsModified = true
113         if start < 0 {
114                 start = 0
115         }
116         if end > b.Len() {
117                 end = b.Len()
118         }
119         if start == end {
120                 return ""
121         }
122         removed := b.Substr(start, end)
123         // The rope implenentation I am using wants indicies starting at 1 instead of 0
124         start++
125         end++
126         b.r = b.r.Delete(start, end-start)
127         b.Update()
128         return removed
129 }
130
131 // Substr returns the substring of the rope from start to end
132 func (b *Buffer) Substr(start, end int) string {
133         return b.r.Substr(start+1, end-start).String()
134 }
135
136 // Len gives the length of the buffer
137 func (b *Buffer) Len() int {
138         return b.r.Len()
139 }