Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions bin/rbindkeys
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding:utf-8; mode:ruby; -*-
#!/usr/bin/env ruby
# -*- coding: utf-8; mode:ruby; -*-

require "rbindkeys"

Rbindkeys::CLI::main ARGV
require 'rbindkeys'
Rbindkeys::CLI.main ARGV
14 changes: 0 additions & 14 deletions lib/rbindkeys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,6 @@
require 'rbindkeys/cli'

module Rbindkeys

class BindTree; end
class Observer; end
class Devicie; end
class VirtualDevice; end

class DeviceOperator; end
class WindowMatcher; end
class KeyEventHandler; end
class BindResolver; end
class FixResolver; end

class CLI; end

class DuplicateNodeError < ArgumentError; end
class UnknownKeyValue < Exception; end
end
22 changes: 10 additions & 12 deletions lib/rbindkeys/bind_resolver.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# -*- coding:utf-8; mode:ruby; -*-

module Rbindkeys

class BindResolver

LOG = LogUtils.get_logger name
DEFAULT_VALUE = :through

Expand All @@ -15,43 +13,43 @@ class BindResolver
# if this resolver is set by prefix key, then true
# else, false
attr_reader :two_stroke
alias :two_stroke? :two_stroke
alias two_stroke? two_stroke

def initialize upper_resolver=:through, two_stroke=false
def initialize(upper_resolver=:through, two_stroke=false)
@tree = {}
if upper_resolver.kind_of? Symbol
if upper_resolver.is_a? Symbol
upper_resolver = FixResolver.instance upper_resolver
end
@upper_resolver = upper_resolver
@two_stroke = two_stroke
end

def bind input, output
def bind(input, output)
@tree[input.last] ||= []
@tree[input.last].each do |b|
if b.input == input
raise DuplicateNodeError, "already this input(#{input.inspect}) was binded"
fail DuplicateNodeError, "already this input(#{input.inspect}) was binded"
end
end

kb = KeyBind.new input, output
@tree[input.last] << kb # TODO implement a bubble insertion
@tree[input.last].sort!{|a,b| b.input.length <=> a.input.length}
@tree[input.last] << kb # TODO: implement a bubble insertion
@tree[input.last].sort! {|a, b| b.input.length <=> a.input.length }
kb
end

def resolve key_code, key_code_set
def resolve(key_code, key_code_set)
just_resolve(key_code, key_code_set) or
@upper_resolver.resolve(key_code, key_code_set)
end

def just_resolve key_code, key_code_set
def just_resolve(key_code, key_code_set)
arr = @tree[key_code]
arr.each do |kb|
sub = kb.input - key_code_set
sub.first == kb.input.last and
return kb
end if not arr.nil?
end unless arr.nil?
nil
end
end
Expand Down
1 change: 0 additions & 1 deletion lib/rbindkeys/bind_set.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding:utf-8; mode:ruby; -*-

module Rbindkeys

# BindSet is a implementation for replace with BindTree
# using Array#& (set intersection).
# because BindTree drop bind order infomation.
Expand Down
57 changes: 26 additions & 31 deletions lib/rbindkeys/bind_tree.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

module Rbindkeys
class BindTree

DEFAULT_DEFAULT_VALUE = :through
AVAIVABLE_DEFAULT_VALUE = [:through, :ignore]
AVAIVABLE_DEFAULT_VALUE = [:through, :ignore].freeze

# a tree structure which that nodes are Fixnum(keycode) and
# leaves are Leaf
Expand All @@ -20,24 +19,24 @@ class BindTree
# a value if no binds hit
attr_reader :default_value

def initialize default_value=DEFAULT_DEFAULT_VALUE
def initialize(default_value=DEFAULT_DEFAULT_VALUE)
@tree = {}
@active_key_binds = []
if AVAIVABLE_DEFAULT_VALUE.include? default_value
@default_value = default_value
else
raise ArgumentError, "expect #{AVAIVABLE_DEFAULT_VALUE.join('/')}"
fail ArgumentError, "expect #{AVAIVABLE_DEFAULT_VALUE.join('/')}"
end
end

# register an input-output pair
# _input_: Array of (Array of) input keycodes
# _output_: Array of send keycodes or Proc
def bind input, output=nil
def bind(input, output=nil)
input = input.clone
new_input = []

if input.kind_of? Array and input[0].kind_of? Array
if input.is_a? Array and input[0].is_a? Array
new_input = input
input = new_input.shift
end
Expand All @@ -47,37 +46,35 @@ def bind input, output=nil

subtree = @tree
input.each do |code|
if subtree.has_key? code and (not subtree[code].kind_of? Hash)
raise DuplicateNodeError, "already register an input:#{input}"
if subtree.key? code and (not subtree[code].is_a? Hash)
fail DuplicateNodeError, "already register an input:#{input}"
end
subtree[code] ||= {}
subtree = subtree[code]
end

if not new_input.empty?
if subtree.has_key?(tail_code) and
not (subtree[tail_code].kind_of?(Leaf) and
subtree[tail_code].payload.kind_of?(BindTree))
raise DuplicateNodeError, "already register an input:#{input}"
if subtree.key?(tail_code) and
not (subtree[tail_code].is_a? Leaf and
subtree[tail_code].payload.is_a? BindTree)
fail DuplicateNodeError, "already register an input:#{input}"
end

if new_input.length == 1
new_input = new_input.first
end
new_input = new_input.first if new_input.length == 1

subtree[tail_code] ||= Leaf.new BindTree.new :ignore
subtree[tail_code].payload.bind new_input, output

elsif subtree.has_key? tail_code
raise DuplicateNodeError, "already register an input:#{input}"
elsif subtree.key? tail_code
fail DuplicateNodeError, "already register an input:#{input}"

else
subtree[tail_code] = Leaf.new KeyBind.new input.push(tail_code), output
end
end

# called when event.value == 0
def resolve_for_released_event event, pressed_keys
def resolve_for_released_event(event, _pressed_keys)
release_binds = []
@active_key_binds.reject! do |key_bind|
if key_bind.input.include? event.code
Expand All @@ -96,38 +93,36 @@ def resolve_for_released_event event, pressed_keys
end

# called when event.value == 1
def resolve_for_pressed_event event, pressed_keys
def resolve_for_pressed_event(event, pressed_keys)
subtree = @tree
last_code = -1
pressed_keys.each do |code|
if last_code >= code
raise ArgumentError, "expect a sorted Array for 2nd arg (pressed_keys)"
fail ArgumentError, 'expect a sorted Array for 2nd arg (pressed_keys)'
end
last_code = code

if subtree.has_key? code
subtree = subtree[code]
end
subtree = subtree[code] if subtree.key? code
end

subtree = (subtree.kind_of?(Hash) and subtree[event.code])
subtree = (subtree.is_a? Hash and subtree[event.code])

if not subtree or subtree.kind_of? Hash
if not subtree or subtree.is_a? Hash
return @default_value
elsif subtree.kind_of? Leaf
if subtree.payload.kind_of? KeyBind
elsif subtree.is_a? Leaf
if subtree.payload.is_a? KeyBind
@active_key_binds << subtree.payload
return subtree.payload
elsif subtree.payload.kind_of? BindTree
elsif subtree.payload.is_a? BindTree
return subtree.payload
end
else
raise UnexpecedLeafError, "unexpeced Leaf: #{subtree.inspect}"
fail UnexpecedLeafError, "unexpeced Leaf: #{subtree.inspect}"
end
end

# called when event.value == 2
def resolve_for_pressing_event event, pressed_keys
def resolve_for_pressing_event(_event, _pressed_keys)
if @active_key_binds.empty?
@default_value
else
Expand All @@ -138,7 +133,7 @@ def resolve_for_pressing_event event, pressed_keys
class Leaf
attr_reader :payload

def initialize payload
def initialize(payload)
@payload = payload
end
end
Expand Down
60 changes: 28 additions & 32 deletions lib/rbindkeys/cli.rb
Original file line number Diff line number Diff line change
@@ -1,79 +1,76 @@
# -*- coding:utf-8; mode:ruby; -*-

module Rbindkeys

SUMMARY = 'key remapper for Linux which is configured in ruby'
SUMMARY = 'key remapper for Linux which is configured in ruby'.freeze

# a class is executed by bin/rbindkeys
class CLI
EVDEVS = '/dev/input/event*'.freeze

EVDEVS = '/dev/input/event*'

class << self
require 'optparse'
# if @cmd == :observe then CLI execute to observe a given event device
# else if @cmd == :ls then CLI list event devices
# (default: :observe)
@cmd = :observe

# if @@cmd == :observe then CLI excecute to observe a given event device
# else if @@cmd == :ls then CLI list event devices
# (default: :observe)
@@cmd = :observe
def cmd; @@cmd end
# a location of a config file (default: "~/.rbindkeys.rb")
@config = "#{ENV['HOME']}/.rbindkeys.rb"

# a location of a config file (default: "~/.rbindkeys.rb")
@@config = "#{ENV['HOME']}/.rbindkeys.rb"
def config; @@config end
@usage = SUMMARY

@@usage = SUMMARY
class << self
require 'optparse'
attr_reader :cmd, :config

def main args
def main(args)
begin
parse_opt args
rescue OptionParser::ParseError => e
puts "ERROR #{e.to_s}"
puts "ERROR #{e}"
err
end

method(@@cmd).call(args)
method(@cmd).call(args)
end

def err code=1
puts @@usage
def err(code=1)
puts @usage
exit code
end

def parse_opt args
def parse_opt(args)
opt = OptionParser.new <<BANNER
#{SUMMARY}
Usage: sudo #{$0} [--config file] #{EVDEVS}
or: sudo #{$0} --evdev-list
BANNER
opt.version = VERSION
opt.on '-l', '--evdev-list', 'a list of event devices' do
@@cmd = :ls
@cmd = :ls
end
opt.on '-c VAL', '--config VAL', 'specifying your configure file' do |v|
@@config = v
@config = v
end
opt.on '-e', '--print-example', 'print an example config' do |v|
@@cmd = :print_example
opt.on '-e', '--print-example', 'print an example config' do |_v|
@cmd = :print_example
end

opt.parse! args

@@usage = opt.help
@usage = opt.help
end

def observe args
def observe(args)
if args.length != 1
puts 'ERROR invalid arguments'
err
end
evdev = args.first
Observer.new(@@config, evdev).start
Observer.new(@config, evdev).start
end

def ls args
def ls(_args)
require 'revdev'
Dir::glob(EVDEVS).sort do |a,b|
Dir.glob(EVDEVS).sort do |a, b|
am = a.match(/[0-9]+$/)
bm = b.match(/[0-9]+$/)
ai = am[0] ? am[0].to_i : 0
Expand All @@ -89,15 +86,14 @@ def ls args
end
end

def print_example args
def print_example(_args)
dir = File.dirname File.expand_path __FILE__
dir = File.expand_path File.join dir, '..', '..', 'sample'
file = File.join dir, 'emacs.rb'
IO.foreach file do |line|
puts "# #{line}"
end
end

end
end # of class Runner
end
9 changes: 3 additions & 6 deletions lib/rbindkeys/device.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
# -*- coding:utf-8; mode:ruby; -*-

require "revdev"
require 'revdev'

module Rbindkeys

class Device < Revdev::EventDevice

def release_all_key
ie = Revdev::InputEvent.new nil, 0, 0, 0
Revdev.constants.select{|c| c.match(/^(?:KEY|BTN)/)}.each do |c|

Revdev.constants.grep(/^KEY|^BTN/).each do |c|
ie.type = Revdev::EV_KEY
ie.code = Revdev.const_get c
ie.value = 0
Expand All @@ -19,7 +18,5 @@ def release_all_key
write_input_event ie
end
end

end

end
Loading