Class: FancyBuff

Inherits:
Object
  • Object
show all
Defined in:
lib/fancy_buff.rb

Overview

a text buffer with marks, selections, and rudimentary editing

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(formatter, lexer) ⇒ FancyBuff

gives you a default, empty, zero slice

formatter - a Rouge formatter lexer - a Rouge lexer



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/fancy_buff.rb', line 18

def initialize(formatter, lexer)
  @formatter = formatter
  @lexer = lexer
  @win = [0, 0, 0, 0]    # the default slice is at the beginning of the buffer, and has a zero size
  @caret = [c, r]

  # size tracking
  @chars = 0        # the number of characters in the buffer (not the same as the number of bytes)
  @bytes = 0        # the number of bytes in the buffer (not the same as the number of characters)
  @lines = []
  @line_no_width = 1
  @rendered_lines = [] # fully formatted, syntax highlighted, and transformed
  @edited_since_last_render = true
  @max_char_width = 0
  @all_buff = @lines.join("\n")

  @marks = {}
  @selections = {}
end

Instance Attribute Details

#bytesObject (readonly)

Returns the value of attribute bytes.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def bytes
  @bytes
end

#caretObject (readonly)

Returns the value of attribute caret.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def caret
  @caret
end

#charsObject (readonly)

Returns the value of attribute chars.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def chars
  @chars
end

#lengthObject (readonly)

Returns the value of attribute length.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def length
  @length
end

#line_no_widthObject (readonly)

Returns the value of attribute line_no_width.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def line_no_width
  @line_no_width
end

#linesObject (readonly)

Returns the value of attribute lines.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def lines
  @lines
end

#marksObject (readonly)

Returns the value of attribute marks.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def marks
  @marks
end

#max_char_widthObject (readonly)

Returns the value of attribute max_char_width.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def max_char_width
  @max_char_width
end

#selectionsObject (readonly)

Returns the value of attribute selections.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def selections
  @selections
end

#winObject

Returns the value of attribute win.



3
4
5
# File 'lib/fancy_buff.rb', line 3

def win
  @win
end

Instance Method Details

#<<(line) ⇒ Object

line: the line to add to the end of the buffer



224
225
226
227
228
229
230
231
232
233
# File 'lib/fancy_buff.rb', line 224

def <<(line)
  line.chomp!
  @lines << line
  @bytes += line.length
  @chars += line.chars.length
  @max_char_width = line.chars.length if line.chars.length > @max_char_width

  @edited_since_last_render = true
  nil
end

#blank_linesObject

the number of blank lines in the buffer after showing all visible lines



151
152
153
# File 'lib/fancy_buff.rb', line 151

def blank_lines
  [@win[3] - visible_lines, 0].max
end

#cObject

index of first visible column



75
76
77
# File 'lib/fancy_buff.rb', line 75

def c
  @win[0]
end

#hObject

height of the buffer window



90
91
92
# File 'lib/fancy_buff.rb', line 90

def h
  @win[3]
end

#mark(sym, char_num) ⇒ Object

set a mark, as in the Vim sense

sym: the name of the mark char_num: the number of characters from the top of the buffer to set the

mark


184
185
186
187
188
# File 'lib/fancy_buff.rb', line 184

def mark(sym, char_num)
  @marks[sym] = [@chars, char_num].min

  nil
end

#rObject

index of first visible row



80
81
82
# File 'lib/fancy_buff.rb', line 80

def r
  @win[1]
end

#reset_caret!Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/fancy_buff.rb', line 46

def reset_caret!
  cx, cy = @caret
  new_cx = if cx < c
             c
           elsif cx > c + w
             w
           else
             cx
           end

  new_cy = if cy < r
             r
           elsif cy > (r + h - 1)
             r + h - 1
           else
             cy
           end

  @caret = [new_cx, new_cy]
end

#select(sym, char_range) ⇒ Object

selects a named range of characters. selections are used to highlight chunks of text that you can refer to later. by giving them a name it’s like having a clipboard with multiple clips on it.

sym: the name of the selection char_range: a Range representing the starting and ending char of the

selection


206
207
208
209
210
# File 'lib/fancy_buff.rb', line 206

def select(sym, char_range)
  @selections[sym] = char_range

  nil
end

#substr_with_color(input, start, finish) ⇒ Object

input - a String that may or may not contain ANSI color codes start - the starting index of printable characters to keep finish - the ending index of printable characters to keep

treats ‘input’ like a String that does



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/fancy_buff.rb', line 122

def substr_with_color(input, start, finish)
  ansi_pattern = /\A\e\[[0-9;]+m/
  printable_counter = 0
  remaining = input.clone.chomp
  result = ''

  loop do
    break if remaining.empty? || printable_counter > finish

    match = remaining.match(ansi_pattern)
    if match
      result += match[0]
      remaining = remaining.sub(match[0], '')
    else
      result += remaining[0] if printable_counter >= start
      remaining = remaining[1..-1]
      printable_counter += 1
    end
  end

  result + "\e[0m"
end

#unmark(sym) ⇒ Object

remote a mark by name

sym: the name of the mark to remove



193
194
195
196
197
# File 'lib/fancy_buff.rb', line 193

def unmark(sym)
  @marks.delete(sym)
  
  nil
end

#unselect(sym) ⇒ Object

deletes a named selection

sym: the name of the selection char_range: a Range representing the starting and ending char of the

selection


217
218
219
220
221
# File 'lib/fancy_buff.rb', line 217

def unselect(sym)
  @selections.delete(sym)

  nil
end

#visible_linesObject

the number of visible lines from @lines at any given time



146
147
148
# File 'lib/fancy_buff.rb', line 146

def visible_lines
  [h, @lines.length - r].min
end

#visual_caretObject



67
68
69
70
71
72
# File 'lib/fancy_buff.rb', line 67

def visual_caret
  [
    caret[0] - c + line_no_width + 1, # '+ 1' is to account for a space between line numbers and caret
    caret[1] - r
  ]
end

#wObject

width of the buffer window



85
86
87
# File 'lib/fancy_buff.rb', line 85

def w
  @win[2]
end

#win_down!(n = 1) ⇒ Object

scrolls the visible window down



162
163
164
165
# File 'lib/fancy_buff.rb', line 162

def win_down!(n=1)
  @win[1] = [@win[1] + n, @lines.length - 1].min
  reset_caret!
end

#win_left!(n = 1) ⇒ Object

scrolls the visible window left



168
169
170
171
# File 'lib/fancy_buff.rb', line 168

def win_left!(n=1)
  @win[0] = [@win[0] - n, 0].max
  reset_caret!
end

#win_right!(n = 1) ⇒ Object

scrolls the visible window right



174
175
176
177
# File 'lib/fancy_buff.rb', line 174

def win_right!(n=1)
  @win[0] = [@win[0] + n, max_char_width - 1].min
  reset_caret!
end

#win_sObject

returns an array of strings representing the visible characters from this FancyBuffer’s @rect



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/fancy_buff.rb', line 96

def win_s
  return [] if h == 0 || w == 0

  @line_no_width = @lines.length.to_s.length
  if @edited_since_last_render
    @rendered_lines = @formatter
      .format(@lexer.lex(@lines.join("\n")))
      .lines
      .map(&:chomp)

    @edited_since_last_render = false
  else
    @rendered_lines[r..(r + visible_lines - 1)]
  end

  @rendered_lines[r..(r + visible_lines - 1)]
    .map.with_index{|row, i| "#{(i + r + 1).to_s.rjust(@line_no_width)} #{substr_with_color(row, c,  c + w - @line_no_width - 2)}" }
    .map{|l| "#{l}\e[0K" } +
    Array.new(blank_lines) { "\e[0K" }
end

#win_up!(n = 1) ⇒ Object

scrolls the visible window up



156
157
158
159
# File 'lib/fancy_buff.rb', line 156

def win_up!(n=1)
  @win[1] = [@win[1] - n, 0].max
  reset_caret!
end