Class: View::WorkingSet

Inherits:
Base
  • Object
show all
Defined in:
lib/view/working_set.rb

Overview

-------------------------------------------------------------------------- | Search or Working Set Name + (indicates dirty/saved state) | -------------------------------------------------------------------------- | Note if present | -------------------------------------------------------------------------- | | | app/models/foo.rb | | 10 def foo | | > 11 puts “bar” (highlight match) | | 12 end | | | | app/models/bar.rb | | 10 def bar | | 11 puts “foo” (highlight match) | | 12 end | | | | 10 def bar | | 11 puts “foo” (highlight match) | | 12 end | -------------------------------------------------------------------------- | 1-10 of 16 items | --------------------------------------------------------------------------

  • Highlight “selected item” with colors.

Constant Summary collapse

TITLE_ROWS =
2
2

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(working_set) ⇒ WorkingSet

Returns a new instance of WorkingSet.



36
37
38
39
40
41
42
# File 'lib/view/working_set.rb', line 36

def initialize(working_set)
  self.working_set = working_set
  self.file_index = index_files(working_set)
  self.selected_item_index = 0
  self.scroll_top = 0
  self.show_match_lines = true
end

Instance Attribute Details

#file_indexObject

Returns the value of attribute file_index.



27
28
29
# File 'lib/view/working_set.rb', line 27

def file_index
  @file_index
end

#scroll_topObject

Returns the value of attribute scroll_top.



27
28
29
# File 'lib/view/working_set.rb', line 27

def scroll_top
  @scroll_top
end

#scrollable_heightObject

Returns the value of attribute scrollable_height.



27
28
29
# File 'lib/view/working_set.rb', line 27

def scrollable_height
  @scrollable_height
end

#selected_item_indexObject

Returns the value of attribute selected_item_index.



27
28
29
# File 'lib/view/working_set.rb', line 27

def selected_item_index
  @selected_item_index
end

#show_match_linesObject

Returns the value of attribute show_match_lines.



27
28
29
# File 'lib/view/working_set.rb', line 27

def show_match_lines
  @show_match_lines
end

#working_setObject

Returns the value of attribute working_set.



27
28
29
# File 'lib/view/working_set.rb', line 27

def working_set
  @working_set
end

Class Method Details

.render(working_set) ⇒ Object



32
33
34
# File 'lib/view/working_set.rb', line 32

def self.render(working_set)
  new(working_set).render
end

Instance Method Details

#calc_cols(percentage) ⇒ Object



309
310
311
# File 'lib/view/working_set.rb', line 309

def calc_cols(percentage)
  (Ncurses.COLS * percentage).to_i
end

#index_files(working_set) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/view/working_set.rb', line 44

def index_files(working_set)
  index = {}
  prev_file = nil
  sorted_items.each_with_index do |item, idx|
    if prev_file == nil
      # first item in set
      prev_file = index[item.file_path] = { file_path: item.file_path, item_index: idx, prev_file: nil }
    elsif item.file_path == prev_file[:file_path]
      # another match within file, ignore it.
    else
      # next file
      current_file = index[item.file_path] = { file_path: item.file_path, item_index: idx, prev_file: prev_file }
      prev_file[:next_file] = current_file
      prev_file = current_file
    end
  end
  index
end

#needs_save?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/view/working_set.rb', line 88

def needs_save?
  !working_set.saved
end

#noteObject



84
85
86
# File 'lib/view/working_set.rb', line 84

def note
  working_set.note
end


305
306
307
# File 'lib/view/working_set.rb', line 305

def print_field(window, align, width, content)
  window.printw "%#{align == :left ? "-" : ""}#{width}s", content
end


267
268
269
270
271
272
273
274
275
# File 'lib/view/working_set.rb', line 267

def print_scrollable_item(start_col, color_name, content, *color_content_pairs)
  if scrolled_into_view?(@scrollable_line_number)
    y = scrollable_item_line_number_to_screen_row(@scrollable_line_number)
    x = start_col
    with_color @item_win, color_name do
      @item_win.mvprintw y, x, "%-#{Ncurses.COLS - start_col}s", content
    end
  end
end

#puts_scrollable_item(start_col, color_name, content) ⇒ Object



262
263
264
265
# File 'lib/view/working_set.rb', line 262

def puts_scrollable_item(start_col, color_name, content)
  print_scrollable_item(start_col, color_name, content)
  @scrollable_line_number += 1
end

#renderObject



96
97
98
99
100
101
102
103
# File 'lib/view/working_set.rb', line 96

def render
  UserInputActor.set_user_input_mode :working_set
  stdscr.clear
  stdscr.refresh
  render_title.refresh
  render_items.refresh
  render_footer.refresh
end


188
189
190
191
192
193
194
195
196
# File 'lib/view/working_set.rb', line 188

def render_footer
  # Height, Width, Y, X   note: (0 width == full width)
  @footer_win ||= Ncurses.newwin(1, 0, Ncurses.LINES - 1, 0)
  @footer_win.move 0, 0
  with_color @footer_win, :blue do
    print_field @footer_win, :right, calc_cols(1), "#{selected_item_index + 1} of #{sorted_items.size} (#{file_index.keys.size} files)"
  end
  @footer_win
end

#render_itemsObject



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/view/working_set.rb', line 198

def render_items

  # Height, Width, Y, X   note: (0 width == full width)
  @item_win ||= Ncurses.newwin(scrollable_height, 0, TITLE_ROWS, 0)

  previous_file_path      = nil
  previous_row            = 0
  @scrollable_line_number = 0
  @scrollable_line_count  = 0

  sorted_items.each do |item|

    if !show_match_lines
      if item.file_path != previous_file_path
        color = item.file_path == selected_item.file_path ? :cyan : :green
        puts_scrollable_item 0, color, item.file_path
      end
    else
      # Print file name if it's a new file, a "--" separator if it's the same
      # file but non-consecutive lines, otherwise just nothing.
      if item.file_path == previous_file_path
        if item.row > previous_row + 1
          puts_scrollable_item 0, :white, "  --"
        end
      else
        if previous_file_path
          puts_scrollable_item 0, :white, ""
        end
        color = item.file_path == selected_item.file_path ? :cyan : :green
        puts_scrollable_item 0, color, item.file_path
      end

      # Print pre-match lines.
      item.pre_match_lines.each_with_index do |line, i|
        print_scrollable_item 0, :white, "  #{item.row - item.pre_match_lines.size + i}"
        puts_scrollable_item 5, :white, line
      end

      # Record match line number
      if item == selected_item
        @selected_item_line_number = @scrollable_line_number
      end

      # Print match line.
      print_scrollable_item 0, :blue, "#{item == selected_item ? ">" : " "}"
      print_scrollable_item 2, :yellow, item.row
      puts_scrollable_item 5, :yellow, item.match_line

      # Print post-match lines.
      item.post_match_lines.each_with_index do |line, i|
        print_scrollable_item 0, :white, "  #{item.row + 1 + i}"
        puts_scrollable_item 5, :white, line
      end
    end

    previous_file_path = item.file_path
    previous_row       = item.row + item.post_match_lines.size
  end

  @scrollable_line_count = @scrollable_line_number

  @item_win
end


112
113
114
115
# File 'lib/view/working_set.rb', line 112

def render_items_and_footer
  render_items.refresh
  render_footer.refresh
end

#render_titleObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/view/working_set.rb', line 166

def render_title
  # Height, Width, Y, X   note: (0 width == full width)
  @title_win ||= Ncurses.newwin(1, 0, 0, 0)
  @title_win.move 0, 0
  print_field @title_win, :left, calc_cols(1), " "
  @title_win.move 0, 0
  with_color @title_win, :blue do
    @title_win.printw title
  end
  if working_set.options["whole_word"]
    with_color @title_win, :red do
      @title_win.printw " [w]"
    end
  end
  # if needs_save?
  #   with_color @title_win, :red do
  #     @title_win.printw " +"
  #   end
  # end
  @title_win
end

#restore_selection_state(from_working_set_view) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/view/working_set.rb', line 67

def restore_selection_state(from_working_set_view)
  if idx = sorted_items.find_index(from_working_set_view.selected_item)
    self.selected_item_index = idx
    self.show_match_lines    = from_working_set_view.show_match_lines
    render_items_and_footer # have to render to set @scrollable_line_count or the next call won't work
    set_scroll_top(from_working_set_view.scroll_top)
  end
end

#scroll(delta) ⇒ Object



139
140
141
142
143
# File 'lib/view/working_set.rb', line 139

def scroll(delta)
  return if @scrollable_line_count <= scrollable_height
  set_scroll_top(scroll_top + delta)
  render_items_and_footer
end

#scroll_bottomObject



162
163
164
# File 'lib/view/working_set.rb', line 162

def scroll_bottom
  scroll_top + scrollable_height
end

#scrollable_item_line_number_to_screen_row(line_number) ⇒ Object



277
278
279
# File 'lib/view/working_set.rb', line 277

def scrollable_item_line_number_to_screen_row(line_number)
  line_number - scroll_top
end

#scrolled_into_view?(line_number, context_lines: 0) ⇒ Boolean

Returns:

  • (Boolean)


281
282
283
284
285
# File 'lib/view/working_set.rb', line 281

def scrolled_into_view?(line_number, context_lines: 0)
  result = (line_number - context_lines) >= scroll_top && (line_number + context_lines) < scroll_bottom
  debug_message "scrolled_into_view line_number: #{line_number} context_lines: #{context_lines} result: #{result.inspect}"
  result
end

#select_next_fileObject



117
118
119
120
121
# File 'lib/view/working_set.rb', line 117

def select_next_file
  next_file = file_index[selected_item.file_path][:next_file]
  self.selected_item_index = next_file[:item_index] if next_file
  render_items_and_footer
end

#select_next_itemObject



129
130
131
132
# File 'lib/view/working_set.rb', line 129

def select_next_item
  self.selected_item_index += 1 unless selected_item_index >= sorted_items.size - 1
  render_items_and_footer
end

#select_prev_fileObject



123
124
125
126
127
# File 'lib/view/working_set.rb', line 123

def select_prev_file
  prev_file = file_index[selected_item.file_path][:prev_file]
  self.selected_item_index = prev_file[:item_index] if prev_file
  render_items_and_footer
end

#select_prev_itemObject



134
135
136
137
# File 'lib/view/working_set.rb', line 134

def select_prev_item
  self.selected_item_index -= 1 unless selected_item_index <= 0
  render_items_and_footer
end

#selected_itemObject



63
64
65
# File 'lib/view/working_set.rb', line 63

def selected_item
  sorted_items[selected_item_index]
end

#selected_item_in_view?Boolean

Returns:

  • (Boolean)


287
288
289
# File 'lib/view/working_set.rb', line 287

def selected_item_in_view?
  scrolled_into_view? @selected_item_line_number, context_lines: $CONTEXT_LINES
end

#selected_item_scroll_deltaObject



291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/view/working_set.rb', line 291

def selected_item_scroll_delta
  scroll_padding = 2 + $CONTEXT_LINES
  debug_message "scrolling #{@selected_item_line_number} | #{scroll_top} | #{scroll_bottom}"
  if scroll_top > (@selected_item_line_number - $CONTEXT_LINES)
    # scroll up
    ((scroll_top - @selected_item_line_number) * -1) - scroll_padding
  elsif scroll_bottom < (@selected_item_line_number + $CONTEXT_LINES)
    # scroll down
    @selected_item_line_number - scroll_bottom + scroll_padding
  else
    0
  end
end

#set_scroll_top(value) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/view/working_set.rb', line 145

def set_scroll_top(value)
  self.scroll_top = if value < 2
                      # Reached top
                      0
                    elsif (value + scrollable_height) > @scrollable_line_count
                      # Reached bottom
                      [@scrollable_line_count - scrollable_height, 0].max
                    else
                      # Normal scroll
                      value
                    end
end

#sorted_itemsObject



92
93
94
# File 'lib/view/working_set.rb', line 92

def sorted_items
  @_sorted_items ||= working_set.items.sort_by { |i| [i.file_path, i.row.to_i]  }
end

#titleObject



76
77
78
79
80
81
82
# File 'lib/view/working_set.rb', line 76

def title
  if working_set.name
    "Name: #{working_set.name}"
  else
    "Search: #{working_set.search}"
  end
end

#toggle_match_linesObject



105
106
107
108
109
110
# File 'lib/view/working_set.rb', line 105

def toggle_match_lines
  self.show_match_lines = !show_match_lines
  self.scroll_top = 0
  @item_win.clear
  render_items.refresh
end