twterm 1.3.0 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -18
  3. data/bin/twterm +1 -1
  4. data/lib/twterm/app.rb +120 -30
  5. data/lib/twterm/client.rb +10 -13
  6. data/lib/twterm/completion_mamanger.rb +11 -6
  7. data/lib/twterm/direct_message.rb +6 -28
  8. data/lib/twterm/direct_message_composer.rb +10 -5
  9. data/lib/twterm/direct_message_manager.rb +5 -6
  10. data/lib/twterm/event/notification/abstract_notification.rb +27 -0
  11. data/lib/twterm/event/notification/error.rb +13 -0
  12. data/lib/twterm/event/notification/info.rb +13 -0
  13. data/lib/twterm/event/notification/success.rb +13 -0
  14. data/lib/twterm/event/notification/warning.rb +13 -0
  15. data/lib/twterm/event_dispatcher.rb +1 -1
  16. data/lib/twterm/extensions/array.rb +5 -0
  17. data/lib/twterm/extensions/enumerator/lazy.rb +3 -0
  18. data/lib/twterm/extensions/string.rb +0 -4
  19. data/lib/twterm/friendship.rb +1 -85
  20. data/lib/twterm/image/between.rb +31 -0
  21. data/lib/twterm/image/blank_line.rb +21 -0
  22. data/lib/twterm/image/bold.rb +31 -0
  23. data/lib/twterm/image/brackets.rb +21 -0
  24. data/lib/twterm/image/color.rb +45 -0
  25. data/lib/twterm/image/empty.rb +21 -0
  26. data/lib/twterm/image/horizontal_sequential_image.rb +48 -0
  27. data/lib/twterm/image/parens.rb +21 -0
  28. data/lib/twterm/image/string_image.rb +38 -0
  29. data/lib/twterm/image/vertical_sequential_image.rb +43 -0
  30. data/lib/twterm/image.rb +107 -0
  31. data/lib/twterm/key_mapper/abstract_key_mapper.rb +51 -0
  32. data/lib/twterm/key_mapper/app_key_mapper.rb +13 -0
  33. data/lib/twterm/key_mapper/cursor_key_mapper.rb +13 -0
  34. data/lib/twterm/key_mapper/general_key_mapper.rb +18 -0
  35. data/lib/twterm/key_mapper/no_such_command.rb +20 -0
  36. data/lib/twterm/key_mapper/no_such_key.rb +16 -0
  37. data/lib/twterm/key_mapper/status_key_mapper.rb +18 -0
  38. data/lib/twterm/key_mapper/tab_key_mapper.rb +31 -0
  39. data/lib/twterm/key_mapper.rb +127 -0
  40. data/lib/twterm/list.rb +0 -31
  41. data/lib/twterm/notifier.rb +7 -7
  42. data/lib/twterm/repository/abstract_entity_repository.rb +41 -0
  43. data/lib/twterm/repository/abstract_expirable_entity_repository.rb +35 -0
  44. data/lib/twterm/repository/abstract_repository.rb +64 -0
  45. data/lib/twterm/repository/direct_message_repository.rb +14 -0
  46. data/lib/twterm/repository/friendship_repository.rb +108 -0
  47. data/lib/twterm/repository/hashtag_repository.rb +39 -0
  48. data/lib/twterm/repository/list_repository.rb +14 -0
  49. data/lib/twterm/repository/status_repository.rb +36 -0
  50. data/lib/twterm/repository/user_repository.rb +22 -0
  51. data/lib/twterm/rest_client.rb +107 -63
  52. data/lib/twterm/screen.rb +21 -15
  53. data/lib/twterm/search_query_window.rb +139 -0
  54. data/lib/twterm/status.rb +14 -108
  55. data/lib/twterm/streaming_client.rb +13 -12
  56. data/lib/twterm/tab/base.rb +48 -8
  57. data/lib/twterm/tab/direct_message/conversation.rb +53 -52
  58. data/lib/twterm/tab/direct_message/conversation_list.rb +46 -45
  59. data/lib/twterm/tab/dumpable.rb +3 -3
  60. data/lib/twterm/tab/key_assignments_cheatsheet.rb +58 -57
  61. data/lib/twterm/tab/loadable.rb +20 -0
  62. data/lib/twterm/tab/new/list.rb +32 -43
  63. data/lib/twterm/tab/new/search.rb +31 -44
  64. data/lib/twterm/tab/new/start.rb +44 -55
  65. data/lib/twterm/tab/new/user.rb +15 -12
  66. data/lib/twterm/tab/rate_limit_status.rb +84 -0
  67. data/lib/twterm/tab/scrollable.rb +39 -19
  68. data/lib/twterm/tab/searchable.rb +133 -0
  69. data/lib/twterm/tab/statuses/base.rb +139 -129
  70. data/lib/twterm/tab/statuses/conversation.rb +26 -15
  71. data/lib/twterm/tab/statuses/favorites.rb +10 -8
  72. data/lib/twterm/tab/statuses/home.rb +10 -9
  73. data/lib/twterm/tab/statuses/list_timeline.rb +12 -8
  74. data/lib/twterm/tab/statuses/mentions.rb +17 -11
  75. data/lib/twterm/tab/statuses/search.rb +8 -5
  76. data/lib/twterm/tab/statuses/user_timeline.rb +11 -8
  77. data/lib/twterm/tab/user_list_management.rb +109 -0
  78. data/lib/twterm/tab/user_tab.rb +125 -126
  79. data/lib/twterm/tab/users/base.rb +39 -41
  80. data/lib/twterm/tab/users/followers.rb +9 -6
  81. data/lib/twterm/tab/users/friends.rb +9 -6
  82. data/lib/twterm/tab_manager.rb +64 -40
  83. data/lib/twterm/tweetbox.rb +18 -13
  84. data/lib/twterm/uri_opener.rb +2 -1
  85. data/lib/twterm/user.rb +2 -110
  86. data/lib/twterm/version.rb +1 -1
  87. data/lib/twterm/view.rb +30 -0
  88. data/lib/twterm.rb +3 -9
  89. data/spec/fixtures/status.json +107 -0
  90. data/spec/fixtures/user.json +102 -0
  91. data/spec/spec_helper.rb +7 -0
  92. data/spec/supports/shared_examples/abstract_key_mapper.rb +17 -0
  93. data/spec/twterm/extension/enumerator/lazy_spec.rb +11 -0
  94. data/spec/twterm/friendship_spec.rb +0 -102
  95. data/spec/twterm/image/blank_line_spec.rb +11 -0
  96. data/spec/twterm/image/brackets_spec.rb +12 -0
  97. data/spec/twterm/image/color_spec.rb +22 -0
  98. data/spec/twterm/image/empry_spec.rb +11 -0
  99. data/spec/twterm/image/horizontal_sequential_image_spec.rb +15 -0
  100. data/spec/twterm/image/parens_spec.rb +12 -0
  101. data/spec/twterm/image/string_image_spec.rb +12 -0
  102. data/spec/twterm/image/vertical_sequential_image_spec.rb +14 -0
  103. data/spec/twterm/image_spec.rb +65 -0
  104. data/spec/twterm/key_mapper/abstract_key_mapper_spec.rb +21 -0
  105. data/spec/twterm/key_mapper/app_key_mapper_spec.rb +7 -0
  106. data/spec/twterm/key_mapper/status_key_mapper_spec.rb +7 -0
  107. data/spec/twterm/key_mapper/tab_key_mapper_spec.rb +7 -0
  108. data/spec/twterm/repository/friendship_repository_spec.rb +108 -0
  109. data/spec/twterm/status_spec.rb +58 -0
  110. data/spec/twterm/user_spec.rb +94 -0
  111. data/twterm.gemspec +13 -10
  112. metadata +129 -35
  113. data/lib/twterm/event/notification.rb +0 -33
  114. data/lib/twterm/extensions/integer.rb +0 -5
  115. data/lib/twterm/filter_query_window.rb +0 -91
  116. data/lib/twterm/filterable_list.rb +0 -41
  117. data/lib/twterm/history/base.rb +0 -21
  118. data/lib/twterm/history/hashtag.rb +0 -13
  119. data/lib/twterm/history/savable.rb +0 -37
  120. data/lib/twterm/history/screen_name.rb +0 -11
  121. data/lib/twterm/promise.rb +0 -143
@@ -9,15 +9,10 @@ module Twterm
9
9
 
10
10
  attr_reader :status, :from, :to
11
11
 
12
- @@instances = []
13
- @@user_ids = Set.new
14
-
15
12
  def initialize(status, from, to)
16
- fail ArgumentError,
17
- '' unless STATUSES.include? status
13
+ fail ArgumentError, '`status` must be one of the following: :blocking, :follwing, :following_requested, or :muting' unless STATUSES.include? status
18
14
 
19
15
  @status, @from, @to = status, from, to
20
- @@instances << self
21
16
  end
22
17
 
23
18
  def blocking?
@@ -36,85 +31,6 @@ module Twterm
36
31
  status?(:muting)
37
32
  end
38
33
 
39
- def self.already_looked_up?(user_id)
40
- @@user_ids.include?(user_id)
41
- end
42
-
43
- def self.block(from, to)
44
- new(:blocking, from, to)
45
- end
46
-
47
- def self.blocking?(from, to)
48
- !find(:blocking, from, to).nil?
49
- end
50
-
51
- def self.cancel_follow_request(from, to)
52
- new(:following_requested, from, to)
53
- end
54
-
55
- def self.delete(status, from, to)
56
- cond = -> f { f.status == status && f.from == from && f.to == to }
57
- @@instances.delete_if(&cond)
58
- end
59
- private_class_method :delete
60
-
61
- def self.find(status, from, to)
62
- cond = -> f { f.status == status && f.from == from && f.to == to }
63
- @@instances.find(&cond)
64
- end
65
- private_class_method :find
66
-
67
- def self.follow(from, to)
68
- new(:following, from, to)
69
- end
70
-
71
- def self.following?(from, to)
72
- !find(:following, from, to).nil?
73
- end
74
-
75
- def self.following_not_requested(from, to)
76
- delete(:following_requested, from, to)
77
- end
78
-
79
- def self.following_requested(from, to)
80
- new(:following_requested, from, to)
81
- end
82
-
83
- def self.following_requested?(from, to)
84
- !find(:following_requested, from, to).nil?
85
- end
86
-
87
- def self.looked_up!(user_id)
88
- @@user_ids << user_id
89
- user_id
90
- end
91
-
92
- def self.mute(from, to)
93
- new(:muting, from, to)
94
- end
95
-
96
- def self.muting?(from, to)
97
- !find(:muting, from, to).nil?
98
- end
99
-
100
- def self.new(status, from, to)
101
- instance = find(status, from, to)
102
- instance.nil? ? super : instance
103
- end
104
- private_class_method :new
105
-
106
- def self.unblock(from, to)
107
- delete(:blocking, from, to)
108
- end
109
-
110
- def self.unfollow(from, to)
111
- delete(:following, from, to)
112
- end
113
-
114
- def self.unmute(from, to)
115
- delete(:muting, from, to)
116
- end
117
-
118
34
  private
119
35
 
120
36
  def status?(status)
@@ -0,0 +1,31 @@
1
+ class Twterm::Image
2
+ class Between < Twterm::Image
3
+ def initialize(image, open, close)
4
+ @image, @open, @close = image, open, close
5
+ end
6
+
7
+ def height
8
+ 1
9
+ end
10
+
11
+ def render(window)
12
+ open.at(line, column).render(window)
13
+ image.at(line, column + open.width).render(window)
14
+ close.at(line, column + open.width + image.width).render(window)
15
+
16
+ self
17
+ end
18
+
19
+ def to_s
20
+ "#{open}#{image}#{close}"
21
+ end
22
+
23
+ def width
24
+ [open, image, close].map(&:width).reduce(0, :+)
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :open, :close, :image
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ module Twterm
2
+ class Image
3
+ class BlankLine < Twterm::Image
4
+ def height
5
+ 1
6
+ end
7
+
8
+ def render(_)
9
+ self
10
+ end
11
+
12
+ def to_s
13
+ "\n"
14
+ end
15
+
16
+ def width
17
+ 0
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ module Twterm
2
+ class Image
3
+ class Bold < Twterm::Image
4
+ def initialize(image)
5
+ @image = image
6
+ end
7
+
8
+ def height
9
+ image.height
10
+ end
11
+
12
+ def render(window)
13
+ window.attron(Curses::A_BOLD)
14
+ image.at(line, column).render(window)
15
+ window.attroff(Curses::A_BOLD)
16
+ end
17
+
18
+ def to_s
19
+ "\e[1m#{image}\e[0m"
20
+ end
21
+
22
+ def width
23
+ image.width
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :image
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'twterm/image/between'
2
+
3
+ module Twterm
4
+ class Image
5
+ class Brackets < Twterm::Image::Between
6
+ def initialize(image)
7
+ super(image, open, close)
8
+ end
9
+
10
+ private
11
+
12
+ def open
13
+ StringImage.new('[')
14
+ end
15
+
16
+ def close
17
+ StringImage.new(']')
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+ module Twterm
2
+ class Image
3
+ class Color < Twterm::Image
4
+ def initialize(image, fg, bg = :transparent)
5
+ @image, @fg, @bg = image, fg, bg
6
+ end
7
+
8
+ def height
9
+ image.height
10
+ end
11
+
12
+ def render(window)
13
+ window.attron(Curses.color_pair(color_pair_index))
14
+ image.at(line, column).render(window)
15
+ window.attroff(Curses.color_pair(color_pair_index))
16
+ end
17
+
18
+ def to_s
19
+ fg_colors = {
20
+ black: 30, red: 31, green: 32, yellow: 33,
21
+ blue: 34, magenta: 35, cyan: 36, white: 37
22
+ }
23
+ bg_colors = {
24
+ black: 40, red: 41, green: 42, yellow: 43,
25
+ blur: 44, magenta: 45, cyan: 46, white: 47
26
+ }
27
+
28
+ str = "\e[#{fg_colors[@fg]}m#{image}\e[0m"
29
+ @bg == :transparent ? str : "\e[#{bg_colors[@bg]}m#{str}"
30
+ end
31
+
32
+ def width
33
+ image.width
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :image
39
+
40
+ def color_pair_index
41
+ Twterm::ColorManager.instance.get_color_pair_index(@fg, @bg)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ module Twterm
2
+ class Image
3
+ class Empty < Twterm::Image
4
+ def height
5
+ 0
6
+ end
7
+
8
+ def render(_)
9
+ self
10
+ end
11
+
12
+ def to_s
13
+ ''
14
+ end
15
+
16
+ def width
17
+ 0
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ module Twterm
2
+ class Image
3
+ class HorizontalSequentialImage < Twterm::Image
4
+ def initialize(images)
5
+ @images = images
6
+ end
7
+
8
+ def -(other)
9
+ append(other)
10
+ end
11
+
12
+ def append(image)
13
+ if image.is_a?(self.class)
14
+ @images += image.images
15
+ else
16
+ images << image
17
+ end
18
+
19
+ self
20
+ end
21
+
22
+ def height
23
+ images.map(&:height).max
24
+ end
25
+
26
+ def render(window)
27
+ window.setpos(line, column)
28
+ images
29
+ .zip(images.lazy.map(&:width).scan(column, :+))
30
+ .each { |r, c| r.at(line, c).render(window) }
31
+
32
+ self
33
+ end
34
+
35
+ def to_s
36
+ images.map(&:to_s).join
37
+ end
38
+
39
+ def width
40
+ images.map(&:width).reduce(0, :+)
41
+ end
42
+
43
+ protected
44
+
45
+ attr_reader :images
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ require 'twterm/image/between'
2
+
3
+ module Twterm
4
+ class Image
5
+ class Parens < Twterm::Image::Between
6
+ def initialize(image)
7
+ super(image, open, close)
8
+ end
9
+
10
+ private
11
+
12
+ def open
13
+ StringImage.new('(')
14
+ end
15
+
16
+ def close
17
+ StringImage.new(')')
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module Twterm
2
+ class Image
3
+ class StringImage < Twterm::Image
4
+ def initialize(string)
5
+ @string = string
6
+ end
7
+
8
+ def -(other)
9
+ if other.is_a?(self.class)
10
+ self.class.new(string + other.string)
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def height
17
+ 1
18
+ end
19
+
20
+ def render(window)
21
+ window.setpos(line, column)
22
+ window.addstr(string)
23
+ end
24
+
25
+ def to_s
26
+ @string.dup
27
+ end
28
+
29
+ def width
30
+ string.width
31
+ end
32
+
33
+ protected
34
+
35
+ attr_reader :string
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,43 @@
1
+ module Twterm
2
+ class Image
3
+ class VerticalSequentialImage < Twterm::Image
4
+ def initialize(images)
5
+ @images = images
6
+ end
7
+
8
+ def |(other)
9
+ append(other)
10
+ end
11
+
12
+ def append(image)
13
+ images << image
14
+ self
15
+ end
16
+
17
+ def height
18
+ images.map(&:height).reduce(0, :+)
19
+ end
20
+
21
+ def render(window)
22
+ window.setpos(line, column)
23
+ images
24
+ .zip(images.lazy.map(&:height).scan(line, :+))
25
+ .each { |r, l| r.at(l, column).render(window) }
26
+
27
+ self
28
+ end
29
+
30
+ def to_s
31
+ images.map(&:to_s).join("\n")
32
+ end
33
+
34
+ def width
35
+ images.map(&:width).max
36
+ end
37
+
38
+ protected
39
+
40
+ attr_reader :images
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,107 @@
1
+ require 'twterm/image/between'
2
+ require 'twterm/image/blank_line'
3
+ require 'twterm/image/bold'
4
+ require 'twterm/image/brackets'
5
+ require 'twterm/image/color'
6
+ require 'twterm/image/empty'
7
+ require 'twterm/image/horizontal_sequential_image'
8
+ require 'twterm/image/parens'
9
+ require 'twterm/image/string_image'
10
+ require 'twterm/image/vertical_sequential_image'
11
+
12
+ class Twterm::Image
13
+ def initialize(column: 0, line: 0)
14
+ @column, @line = column, line
15
+ end
16
+
17
+ def !
18
+ bold
19
+ end
20
+
21
+ def |(other)
22
+ VerticalSequentialImage.new([self, other])
23
+ end
24
+
25
+ def -(other)
26
+ HorizontalSequentialImage.new([self, other])
27
+ end
28
+
29
+ def at(line, column)
30
+ @line, @column = line, column
31
+
32
+ self
33
+ end
34
+
35
+ def self.blank_line
36
+ BlankLine.new
37
+ end
38
+
39
+ def bold
40
+ Bold.new(self)
41
+ end
42
+
43
+ def brackets
44
+ Brackets.new(self)
45
+ end
46
+
47
+ def self.checkbox(checked)
48
+ string(checked ? 'x' : ' ').brackets
49
+ end
50
+
51
+ def color(fg, bg = :transparent)
52
+ Color.new(self, fg, bg)
53
+ end
54
+
55
+ def column
56
+ @column || 0
57
+ end
58
+
59
+ def self.cursor(height, current)
60
+ color = current ? [:black, :magenta] : [:black]
61
+ VerticalSequentialImage.new([whitespace] * height).color(*color)
62
+ end
63
+
64
+ def self.empty
65
+ Empty.new
66
+ end
67
+
68
+ def self.remaining_resource(remaining, total, length)
69
+ ratio = remaining * 100 / total
70
+ color =
71
+ if ratio >= 40
72
+ :green
73
+ elsif ratio >= 20
74
+ :yellow
75
+ else
76
+ :red
77
+ end
78
+
79
+ bars = string(('|' * (remaining * length / total)).ljust(length)).color(color)
80
+
81
+ Between.new(bars, !string('['), !string(']'))
82
+ end
83
+
84
+ def line
85
+ @line || 0
86
+ end
87
+
88
+ def self.number(n)
89
+ string(n.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, '\1,'))
90
+ end
91
+
92
+ def parens
93
+ Parens.new(self)
94
+ end
95
+
96
+ def self.plural(n, singular, plural = "#{singular}s")
97
+ string(n == 1 ? singular : plural)
98
+ end
99
+
100
+ def self.string(str)
101
+ StringImage.new(str)
102
+ end
103
+
104
+ def self.whitespace
105
+ string(' ')
106
+ end
107
+ end
@@ -0,0 +1,51 @@
1
+ require 'curses'
2
+ require 'twterm/key_mapper/no_such_command'
3
+ require 'twterm/key_mapper/no_such_key'
4
+
5
+ module Twterm
6
+ class KeyMapper
7
+ class AbstractKeyMapper
8
+ def initialize(mappings)
9
+ commands = self.class.commands
10
+
11
+ mappings.keys.each do |k|
12
+ raise NoSuchCommand.new(self.class.category, k) unless commands.include?(k)
13
+ end
14
+
15
+ @mappings = Hash[mappings.map { |k, v| [k, translate(v)] }]
16
+ end
17
+
18
+ def [](key)
19
+ raise NoSuchCommand.new(self.class.category, key) unless @mappings.keys.include?(key)
20
+ @mappings[key]
21
+ end
22
+
23
+ private
24
+
25
+ def translate(key)
26
+ case key
27
+ when '!'..'}' then key
28
+ when /\A\^([A-Z]?)\Z/ then $1.ord - 'A'.ord + 1
29
+ when 'F1' then Curses::Key::F1
30
+ when 'F2' then Curses::Key::F2
31
+ when 'F3' then Curses::Key::F3
32
+ when 'F4' then Curses::Key::F4
33
+ when 'F5' then Curses::Key::F5
34
+ when 'F6' then Curses::Key::F6
35
+ when 'F7' then Curses::Key::F7
36
+ when 'F8' then Curses::Key::F8
37
+ when 'F9' then Curses::Key::F9
38
+ when 'F10' then Curses::Key::F10
39
+ when 'F11' then Curses::Key::F11
40
+ when 'F12' then Curses::Key::F12
41
+ else
42
+ raise NoSuchKey.new(key)
43
+ end
44
+ end
45
+
46
+ def self.commands
47
+ self::DEFAULT_MAPPINGS.keys
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,13 @@
1
+ require 'twterm/key_mapper/abstract_key_mapper'
2
+
3
+ class Twterm::KeyMapper::AppKeyMapper < Twterm::KeyMapper::AbstractKeyMapper
4
+ DEFAULT_MAPPINGS = {
5
+ cheatsheet: 'F1',
6
+ me: 'm',
7
+ quit: 'F10',
8
+ }.freeze
9
+
10
+ def self.category
11
+ 'app'.freeze
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'twterm/key_mapper/abstract_key_mapper'
2
+
3
+ class Twterm::KeyMapper::CursorKeyMapper < Twterm::KeyMapper::AbstractKeyMapper
4
+ DEFAULT_MAPPINGS = {
5
+ bottom_of_window: 'L',
6
+ middle_of_window: 'M',
7
+ top_of_window: 'H',
8
+ }.freeze
9
+
10
+ def self.category
11
+ 'cursor'.freeze
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ require 'twterm/key_mapper/abstract_key_mapper'
2
+
3
+ class Twterm::KeyMapper::GeneralKeyMapper < Twterm::KeyMapper::AbstractKeyMapper
4
+ DEFAULT_MAPPINGS = {
5
+ bottom: 'G',
6
+ down: 'j',
7
+ left: 'h',
8
+ page_down: 'd',
9
+ page_up: 'u',
10
+ right: 'l',
11
+ top: 'g',
12
+ up: 'k',
13
+ }.freeze
14
+
15
+ def self.category
16
+ 'general'.freeze
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ module Twterm
2
+ class KeyMapper
3
+ class NoSuchCommand < StandardError
4
+ attr_reader :category, :command
5
+
6
+ def initialize(category, command)
7
+ @category, @command = category, command
8
+ super(message)
9
+ end
10
+
11
+ def full_command
12
+ "#{category}.#{command}"
13
+ end
14
+
15
+ def message
16
+ "No such command: #{full_command}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ module Twterm
2
+ class KeyMapper
3
+ class NoSuchKey < StandardError
4
+ attr_reader :key
5
+
6
+ def initialize(key)
7
+ @key = key
8
+ super(message)
9
+ end
10
+
11
+ def message
12
+ "No such key: #{key}"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'twterm/key_mapper/abstract_key_mapper'
2
+
3
+ class Twterm::KeyMapper::StatusKeyMapper < Twterm::KeyMapper::AbstractKeyMapper
4
+ DEFAULT_MAPPINGS = {
5
+ compose: '^N',
6
+ conversation: 'c',
7
+ destroy: 'D',
8
+ like: 'L',
9
+ open_link: 'o',
10
+ reply: 'r',
11
+ retweet: 'R',
12
+ user: 'U',
13
+ }.freeze
14
+
15
+ def self.category
16
+ 'status'.freeze
17
+ end
18
+ end