Class: HackerTerm::UI

Inherits:
Object
  • Object
show all
Includes:
Curses
Defined in:
lib/hacker_term/ui.rb

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ UI

Returns a new instance of UI.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/hacker_term/ui.rb', line 7

def initialize(opts={})

  opts = defaults.merge(opts) # Ununsed for now

  raw # Intercept everything
  noecho # Do not echo user input to stdout
  stdscr.keypad(true) # Enable arrows

  if can_change_color?
    start_color
    # foreground / background colours
    init_pair(0, COLOR_WHITE, COLOR_BLACK)
    init_pair(1, COLOR_WHITE, COLOR_BLUE)
    init_pair(2, COLOR_WHITE, COLOR_RED)
    init_pair(3, COLOR_BLACK, COLOR_GREEN)
  end

  @total_width = cols
  @total_height = lines
  @padding_left = 2
  @title_width = 0
  @cols  = ['rank', 'title', 'score', 'comments']
  @line_num = -1

  clear!
end

Instance Method Details

#<<(str) ⇒ Object



51
52
53
54
# File 'lib/hacker_term/ui.rb', line 51

def <<(str)
  throw 'invalid type' unless str.is_a? String
  output_line(next_line_num, str) 
end

#clear!Object



153
154
155
156
# File 'lib/hacker_term/ui.rb', line 153

def clear!
  setpos(0, 0)
  clear
end

#closeObject



149
150
151
# File 'lib/hacker_term/ui.rb', line 149

def close
  close_screen
end

#dividerObject



56
57
58
# File 'lib/hacker_term/ui.rb', line 56

def divider
  output_divider(next_line_num) 
end


88
89
90
91
92
93
94
95
96
# File 'lib/hacker_term/ui.rb', line 88

def draw_footer(sorted_by, mean, median, mode)
  output do |buff|
    buff.divider
    attrset color_pair(1)
    buff << sprintf("Sorted by: %7s | Scores: Mean: %4.2f | Median: %4.2f | Mode: %4.2f", 
      sorted_by, mean, median, mode)
    buff.divider
  end
end

#draw_headerObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/hacker_term/ui.rb', line 64

def draw_header
  output do |buff|
    buff.divider
    attrset color_pair(1)
    buff << "HACKER NEWS TERMINAL - thanks to http://hndroidapi.appspot.com"
    buff << "CMDS: Select (Arrows), Open Item (O), Open Item Discussion (D), Refresh (A)"
    buff << "CMDS CONT: Sort by Rank (R), Score (S), Comments (C), Title (T) | Quit (Q)"
    buff.divider

    # Get width_excl_title, i.e. width of all columns + some extra for |'s and spacing.
    # Once obtained, pad out the title column with the any width remaining
    # A nicer way to do this is always put the title last, and assume last column gets
    # remaining width. That way we can just loop through our cols, rather than hardcoding
    # them as per example below. I'm sticking to this because I want the title listed second.
    width_excl_title = @cols.inject(0) do |width, col| 
      width += (3 + col.length)
    end
    attrset color_pair(2)
    @title_width = @total_width - width_excl_title + 'title'.length
    buff << "RANK | TITLE " + " " * (@total_width - width_excl_title) + "| SCORE | COMMENTS"
    buff.divider
  end
end

#draw_item_line(rank, data, selected) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/hacker_term/ui.rb', line 98

def draw_item_line(rank, data, selected)
  # Truncate if too long
  title = truncate_line! data

  # Format and output
  if selected
    rank = '> ' + rank
    attrset color_pair(3)
  else
    attrset color_pair(0)
  end

  self << sprintf("%4s | %-#{@title_width}s | %5s | %8s", 
    rank, title, data['score'], data['comments'])
end

#get_charObject



134
135
136
# File 'lib/hacker_term/ui.rb', line 134

def get_char
  interpret_char(getch)
end

#interpret_char(c) ⇒ Object



138
139
140
141
142
143
144
145
146
147
# File 'lib/hacker_term/ui.rb', line 138

def interpret_char(c)
  case c
  when Curses::Key::UP
    'up'
  when Curses::Key::DOWN
    'down'
  else
    c
  end
end

#next_line_numObject



34
35
36
# File 'lib/hacker_term/ui.rb', line 34

def next_line_num
  @line_num += 1
end

#output(&blk) ⇒ Object



60
61
62
# File 'lib/hacker_term/ui.rb', line 60

def output(&blk)
  blk.call self if block_given?
end

#output_divider(line_num) ⇒ Object



45
46
47
48
49
# File 'lib/hacker_term/ui.rb', line 45

def output_divider(line_num)
  setpos(line_num, 0)
  attrset color_pair(0)
  addstr('-' * @total_width)
end

#output_line(line_num, data) ⇒ Object



38
39
40
41
42
43
# File 'lib/hacker_term/ui.rb', line 38

def output_line(line_num, data)
  setpos(line_num, 0)
  padding_right = @total_width - data.length - @padding_left
  padding_right = 0 if padding_right < 0  
  addstr((" " * @padding_left) + data + (" " * padding_right))
end

#show(page_data) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/hacker_term/ui.rb', line 119

def show(page_data)
  draw_header

  page_data.data.each_index do |i| 
    line_data = page_data.data.fetch(i)
    draw_item_line(line_data['rank'], line_data, page_data.line_pos == i + 1) 
  end

  draw_footer(page_data.sorted_by, 
    page_data.mean_score, 
    page_data.median_score, 
    page_data.mode_score
  )
end

#truncate_line!(data) ⇒ Object



114
115
116
117
# File 'lib/hacker_term/ui.rb', line 114

def truncate_line!(data)
  return data['title'][0, @title_width - 3] + '...' if data['title'].length >= @title_width
  data['title']
end