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



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

def initialize(formatter, lexer)
  @formatter = formatter
  @lexer = lexer

  # 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 = []
  @rendered_lines = [] # fully formatted, syntax highlighted, and transformed
  @edited_since_last_render = true
  @max_char_width = 0
  @all_buff = @lines.join("\n")

  @marks = {}
  @selections = {}
  @win = [0, 0, 0, 0]    # the default slice is at the beginning of the buffer, and has a zero size
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

#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

#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

allows the consuming application to set the window size, since that application is probably mananging the other buffers in use



13
14
15
# File 'lib/fancy_buff.rb', line 13

def win
  @win
end

Instance Method Details

#<<(line) ⇒ Object

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



185
186
187
188
189
190
191
192
193
194
# File 'lib/fancy_buff.rb', line 185

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



116
117
118
# File 'lib/fancy_buff.rb', line 116

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

#cObject

index of first visible column



43
44
45
# File 'lib/fancy_buff.rb', line 43

def c
  @win[1]
end

#hObject

height of the buffer window



53
54
55
# File 'lib/fancy_buff.rb', line 53

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


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

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

  nil
end

#rObject

index of first visible row



38
39
40
# File 'lib/fancy_buff.rb', line 38

def r
  @win[0]
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


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

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



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/fancy_buff.rb', line 87

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



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

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


178
179
180
181
182
# File 'lib/fancy_buff.rb', line 178

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

  nil
end

#visible_linesObject

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



111
112
113
# File 'lib/fancy_buff.rb', line 111

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

#wObject

width of the buffer window



48
49
50
# File 'lib/fancy_buff.rb', line 48

def w
  @win[2]
end

#win_down(n = 1) ⇒ Object

scrolls the visible window down



126
127
128
# File 'lib/fancy_buff.rb', line 126

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

#win_left(n = 1) ⇒ Object

scrolls the visible window left



131
132
133
# File 'lib/fancy_buff.rb', line 131

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

#win_right(n = 1) ⇒ Object

scrolls the visible window right



136
137
138
# File 'lib/fancy_buff.rb', line 136

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

#win_sObject

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



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/fancy_buff.rb', line 59

def win_s
  r, c, w, h = @win

  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



121
122
123
# File 'lib/fancy_buff.rb', line 121

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