]> git.lizzy.rs Git - micro.git/blob - cmd/micro/buffer.go
da5e6757bbed9bd4230736d8a24b649e8cd40973
[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         // Stores the text of the buffer
14         r *rope.Rope
15
16         // Path to the file on disk
17         Path string
18         // Name of the buffer on the status line
19         Name string
20
21         IsModified bool
22
23         // Provide efficient and easy access to text and lines so the rope String does not
24         // need to be constantly recalculated
25         // These variables are updated in the update() function
26         Lines    []string
27         NumLines int
28
29         // Syntax highlighting rules
30         rules []SyntaxRule
31         // The buffer's filetype
32         FileType string
33 }
34
35 // NewBuffer creates a new buffer from `txt` with path and name `path`
36 func NewBuffer(txt, path string) *Buffer {
37         b := new(Buffer)
38         if txt == "" {
39                 b.r = new(rope.Rope)
40         } else {
41                 b.r = rope.New(txt)
42         }
43         b.Path = path
44         b.Name = path
45
46         b.Update()
47         b.UpdateRules()
48
49         return b
50 }
51
52 // UpdateRules updates the syntax rules and filetype for this buffer
53 // This is called when the colorscheme changes
54 func (b *Buffer) UpdateRules() {
55         b.rules, b.FileType = GetRules(b)
56 }
57
58 func (b *Buffer) String() string {
59         if b.r.Len() != 0 {
60                 return b.r.String()
61         }
62         return ""
63 }
64
65 // Update fetches the string from the rope and updates the `text` and `lines` in the buffer
66 func (b *Buffer) Update() {
67         b.Lines = strings.Split(b.String(), "\n")
68         b.NumLines = len(b.Lines)
69 }
70
71 // Save saves the buffer to its default path
72 func (b *Buffer) Save() error {
73         return b.SaveAs(b.Path)
74 }
75
76 // SaveAs saves the buffer to a specified path (filename), creating the file if it does not exist
77 func (b *Buffer) SaveAs(filename string) error {
78         b.UpdateRules()
79         data := []byte(b.String())
80         err := ioutil.WriteFile(filename, data, 0644)
81         if err == nil {
82                 b.IsModified = false
83         }
84         return err
85 }
86
87 // Insert a string into the rope
88 func (b *Buffer) Insert(idx int, value string) {
89         b.IsModified = true
90         b.r = b.r.Insert(idx, value)
91         b.Update()
92 }
93
94 // Remove a slice of the rope from start to end (exclusive)
95 // Returns the string that was removed
96 func (b *Buffer) Remove(start, end int) string {
97         b.IsModified = true
98         if start < 0 {
99                 start = 0
100         }
101         if end > b.Len() {
102                 end = b.Len()
103         }
104         if start == end {
105                 return ""
106         }
107         removed := b.Substr(start, end)
108         // The rope implenentation I am using wants indicies starting at 1 instead of 0
109         start++
110         end++
111         b.r = b.r.Delete(start, end-start)
112         b.Update()
113         return removed
114 }
115
116 // Substr returns the substring of the rope from start to end
117 func (b *Buffer) Substr(start, end int) string {
118         return b.r.Substr(start+1, end-start).String()
119 }
120
121 // Len gives the length of the buffer
122 func (b *Buffer) Len() int {
123         return b.r.Len()
124 }