Class: Fatty::KeyEvent
- Inherits:
-
Object
- Object
- Fatty::KeyEvent
- Defined in:
- lib/fatty/key_event.rb
Overview
The KeyEvent class is a simple class to store a key with its modifiers. KeyMap will map a KeyEvent to an action (for a given context), and the KeyDecoder class is responsible for turning raw key inputs from curses into a KeyEvent. The CURSES_TO_EVENT constant is an initial map from known curses key codes to KeyEvents. These can be overriden for different terminals in Fatty::Config.keydefs.
Constant Summary collapse
- CTRL_PUNCT =
{ 27 => :'[', # ESC is also C-[ 28 => :'\\', # C-\ 29 => :']', # C-] 30 => :'^', # C-^ 31 => :'/', # C-_ }.freeze
Instance Attribute Summary collapse
-
#ctrl ⇒ Object
readonly
Returns the value of attribute ctrl.
-
#key ⇒ Object
readonly
Returns the value of attribute key.
-
#meta ⇒ Object
readonly
Returns the value of attribute meta.
-
#raw ⇒ Object
readonly
Returns the value of attribute raw.
-
#shift ⇒ Object
readonly
Returns the value of attribute shift.
-
#text ⇒ Object
readonly
Returns the value of attribute text.
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #action_owner_name(owner) ⇒ Object
- #action_target_text(action) ⇒ Object
- #binding_action(binding) ⇒ Object
- #binding_text(binding) ⇒ Object
- #bindings ⇒ Object
- #bindings_text ⇒ Object
- #bytes_from_raw(value) ⇒ Object
- #code ⇒ Object
- #coded? ⇒ Boolean
- #color ⇒ Object
- #colorize(text) ⇒ Object
- #ctrl? ⇒ Boolean
- #hash ⇒ Object
-
#initialize(key:, text: nil, raw: nil, ctrl: false, meta: false, shift: false) ⇒ KeyEvent
constructor
A new instance of KeyEvent.
- #key_name ⇒ Object
- #meta? ⇒ Boolean
- #modifier_text ⇒ Object
- #printable? ⇒ Boolean
- #raw_bytes ⇒ Object
- #report ⇒ Object
- #report_for_bound ⇒ Object
- #report_for_unbound ⇒ Object
- #report_for_uncoded ⇒ Object
- #shift? ⇒ Boolean
- #status_string ⇒ Object
- #suggested_keybinding ⇒ Object
- #suggested_keydef(terminal_name) ⇒ Object
- #suggested_snippet(terminal_name) ⇒ Object
- #to_s ⇒ Object
- #unbound? ⇒ Boolean
- #uncoded? ⇒ Boolean
- #yaml_desc ⇒ Object
Constructor Details
#initialize(key:, text: nil, raw: nil, ctrl: false, meta: false, shift: false) ⇒ KeyEvent
Returns a new instance of KeyEvent.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/fatty/key_event.rb', line 28 def initialize(key:, text: nil, raw: nil, ctrl: false, meta: false, shift: false) # If the decoder gives us a control character as an integer (1..26), # canonicalize it to ctrl+letter so keymaps and display behave nicely. if key.is_a?(Integer) if CTRL_CODE_TO_LETTER.key?(key) key = CTRL_CODE_TO_LETTER[key] ctrl = true elsif CTRL_PUNCT.key?(key) key = CTRL_PUNCT[key] ctrl = true end end @key = key # Symbol or named key @raw = raw # the key (or keys for escape sequences) as returned by Curses @ctrl = ctrl @meta = @shift = shift # invariant: chorded keys do not self-insert @text = ctrl || ? nil : text end |
Instance Attribute Details
#ctrl ⇒ Object (readonly)
Returns the value of attribute ctrl.
26 27 28 |
# File 'lib/fatty/key_event.rb', line 26 def ctrl @ctrl end |
#key ⇒ Object (readonly)
Returns the value of attribute key.
26 27 28 |
# File 'lib/fatty/key_event.rb', line 26 def key @key end |
#meta ⇒ Object (readonly)
Returns the value of attribute meta.
26 27 28 |
# File 'lib/fatty/key_event.rb', line 26 def @meta end |
#raw ⇒ Object (readonly)
Returns the value of attribute raw.
26 27 28 |
# File 'lib/fatty/key_event.rb', line 26 def raw @raw end |
#shift ⇒ Object (readonly)
Returns the value of attribute shift.
26 27 28 |
# File 'lib/fatty/key_event.rb', line 26 def shift @shift end |
#text ⇒ Object (readonly)
Returns the value of attribute text.
26 27 28 |
# File 'lib/fatty/key_event.rb', line 26 def text @text end |
Class Method Details
.key_to_str(key: "<?>", ctrl: false, meta: false, shift: false) ⇒ Object
49 50 51 52 53 54 55 56 |
# File 'lib/fatty/key_event.rb', line 49 def self.key_to_str(key: "<?>", ctrl: false, meta: false, shift: false) mods = [] mods << "C" if ctrl mods << "M" if mods << "S" if shift key_str = key.to_s mods.empty? ? key_str : "#{mods.join('-')}-#{key_str}" end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
62 63 64 65 66 67 68 |
# File 'lib/fatty/key_event.rb', line 62 def ==(other) other.is_a?(KeyEvent) && key == other.key && ctrl == other.ctrl && == other. && shift == other.shift end |
#action_owner_name(owner) ⇒ Object
174 175 176 177 178 179 180 181 182 |
# File 'lib/fatty/key_event.rb', line 174 def action_owner_name(owner) name = if owner.respond_to?(:name) && owner.name owner.name else owner.to_s end name.split("::").last end |
#action_target_text(action) ⇒ Object
165 166 167 168 169 170 171 172 |
# File 'lib/fatty/key_event.rb', line 165 def action_target_text(action) return "" unless action defn = Fatty::Actions.lookup(action) return " (unregistered action)" unless defn " (#{defn[:on]}: #{action_owner_name(defn[:owner])}##{defn[:method]})" end |
#binding_action(binding) ⇒ Object
143 144 145 146 147 148 149 150 |
# File 'lib/fatty/key_event.rb', line 143 def binding_action(binding) case binding when Array [binding[0], binding[1..] || []] else [binding, []] end end |
#binding_text(binding) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/fatty/key_event.rb', line 152 def binding_text(binding) case binding when nil "(none)" when Array action = binding[0] args = binding[1..] || [] args.empty? ? action.inspect : "#{action.inspect} #{args.inspect}" else binding.inspect end end |
#bindings ⇒ Object
87 88 89 |
# File 'lib/fatty/key_event.rb', line 87 def bindings Fatty::KeyMap.active.bindings_for(self) || {} end |
#bindings_text ⇒ Object
133 134 135 136 137 138 139 140 141 |
# File 'lib/fatty/key_event.rb', line 133 def bindings_text return "(none)" if bindings.empty? text = bindings.map { |context, binding| action, _args = binding_action(binding) " context: #{context}: #{binding_text(binding)}#{action_target_text(action)}" }.join("\n") text end |
#bytes_from_raw(value) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/fatty/key_event.rb', line 112 def bytes_from_raw(value) case value when Array value.flat_map { |item| bytes_from_raw(item) } when String value.bytes when Integer [value] else [] end end |
#code ⇒ Object
99 100 101 102 103 104 105 106 |
# File 'lib/fatty/key_event.rb', line 99 def code case raw when Integer raw when Array raw.reverse.find { |item| item.is_a?(Integer) } end end |
#coded? ⇒ Boolean
79 80 81 |
# File 'lib/fatty/key_event.rb', line 79 def coded? key.is_a?(Symbol) end |
#color ⇒ Object
184 185 186 187 188 189 190 191 192 |
# File 'lib/fatty/key_event.rb', line 184 def color if uncoded? :oops elsif unbound? :warn else :good end end |
#colorize(text) ⇒ Object
270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/fatty/key_event.rb', line 270 def colorize(text) case color when :good Rainbow(text).green when :warn Rainbow(text).yellow when :oops Rainbow(text).red else text end end |
#ctrl? ⇒ Boolean
204 205 206 |
# File 'lib/fatty/key_event.rb', line 204 def ctrl? @ctrl end |
#hash ⇒ Object
71 72 73 |
# File 'lib/fatty/key_event.rb', line 71 def hash [key, ctrl, , shift].hash end |
#key_name ⇒ Object
95 96 97 |
# File 'lib/fatty/key_event.rb', line 95 def key_name coded? ? to_s : "(none)" end |
#meta? ⇒ Boolean
208 209 210 |
# File 'lib/fatty/key_event.rb', line 208 def @meta end |
#modifier_text ⇒ Object
125 126 127 128 129 130 131 |
# File 'lib/fatty/key_event.rb', line 125 def modifier_text mods = [] mods << "ctrl" if ctrl? mods << "meta" if mods << "shift" if shift? mods.empty? ? "(none)" : mods.join(", ") end |
#printable? ⇒ Boolean
75 76 77 |
# File 'lib/fatty/key_event.rb', line 75 def printable? text && !text.empty? && text != "\n" && text != "\r" end |
#raw_bytes ⇒ Object
108 109 110 |
# File 'lib/fatty/key_event.rb', line 108 def raw_bytes bytes_from_raw(raw) end |
#report ⇒ Object
216 217 218 219 220 221 222 223 224 |
# File 'lib/fatty/key_event.rb', line 216 def report if uncoded? report_for_uncoded elsif unbound? report_for_unbound else report_for_bound end end |
#report_for_bound ⇒ Object
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/fatty/key_event.rb', line 253 def report_for_bound rule = colorize("=" * 55) + "\n" out = +"" out << rule out << colorize("Key report #{status_string}:\n") # out << " TERM: #{terminal_name}\n" out << " code: #{code.inspect}\n" out << " raw: #{raw.inspect}\n" out << " bytes: #{raw_bytes.inspect}\n" out << " key: #{key.inspect}\n" out << " name: #{key_name}\n" out << " text: #{text.inspect}\n" out << " modifiers: #{modifier_text}\n" out << " bindings:\n#{bindings_text}\n" out << "\n" end |
#report_for_unbound ⇒ Object
238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/fatty/key_event.rb', line 238 def report_for_unbound rule = colorize("=" * 55) + "\n" out = +"" out << rule out << colorize("Key report #{status_string}:\n") # out << " TERM: #{terminal_name}\n" out << " code: #{code.inspect}\n" out << " raw: #{raw.inspect}\n" out << " bytes: #{raw_bytes.inspect}\n" out << " key: #{key.inspect}\n" out << " name: #{key_name}\n" out << " text: #{text.inspect}\n" out << " modifiers: #{modifier_text}\n" end |
#report_for_uncoded ⇒ Object
226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/fatty/key_event.rb', line 226 def report_for_uncoded rule = colorize("=" * 55) + "\n" out = +"" out << rule out << colorize("Key report #{status_string}:\n") out << " code: #{code.inspect}\n" out << " raw: #{raw.inspect}\n" out << " bytes: #{raw_bytes.inspect}\n" out << " key: #{key.inspect}\n" out << "\n" end |
#shift? ⇒ Boolean
212 213 214 |
# File 'lib/fatty/key_event.rb', line 212 def shift? @shift end |
#status_string ⇒ Object
194 195 196 197 198 199 200 201 202 |
# File 'lib/fatty/key_event.rb', line 194 def status_string if uncoded? "(UNCODED)" elsif unbound? "(UNBOUND)" else "(BOUND)" end end |
#suggested_keybinding ⇒ Object
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/fatty/key_event.rb', line 314 def suggested_keybinding out = <<~TEXT No action is bound to #{key_name}. Suggested keybindings.yml entry: ............>8 snip here 8<.................... #{yaml_desc} ............>8 snip here 8<.................... TEXT out << <<~TEXT TEXT out end |
#suggested_keydef(terminal_name) ⇒ Object
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/fatty/key_event.rb', line 293 def suggested_keydef(terminal_name) return "" unless code <<~TEXT No key name is associated with keycode #{code}. Suggested keydefs.yml entry: ............>8 snip here 8<.................... #{terminal_name}: map: #{code}: key: key_name shift: <true/false> ctrl: <true/false> meta: <true/false> ............>8 snip here 8<.................... TEXT end |
#suggested_snippet(terminal_name) ⇒ Object
283 284 285 286 287 288 289 290 291 |
# File 'lib/fatty/key_event.rb', line 283 def suggested_snippet(terminal_name) if uncoded? suggested_keydef(terminal_name) elsif unbound? suggested_keybinding else '' end end |
#to_s ⇒ Object
58 59 60 |
# File 'lib/fatty/key_event.rb', line 58 def to_s self.class.key_to_str(key:, ctrl:, meta:, shift:) end |
#unbound? ⇒ Boolean
91 92 93 |
# File 'lib/fatty/key_event.rb', line 91 def unbound? coded? && bindings.empty? end |
#uncoded? ⇒ Boolean
83 84 85 |
# File 'lib/fatty/key_event.rb', line 83 def uncoded? !key.is_a?(Symbol) end |
#yaml_desc ⇒ Object
332 333 334 335 336 337 338 339 340 |
# File 'lib/fatty/key_event.rb', line 332 def yaml_desc lines = ["# #{key_name}", "- key: #{key}"] lines << " shift: true" if shift? lines << " ctrl: true" if ctrl? lines << " meta: true" if lines << " context: <valid_context>" lines << " action: <action_name>" lines.join("\n") end |