Class: VER::MajorMode

Inherits:
Struct
  • Object
show all
Includes:
Keymap::Results
Defined in:
lib/ver/major_mode.rb

Overview

This mode is responsible for maintaining a keymap of its own and a list of minor modes that are immediately queried. A major mode can inherit the keymap of another major mode in order to specialize it. The inherited keymap is duplicated upon inheritance and the original will not be modified, the duplicate is merged in a manner that will not replace existing sequences.

The bound_keys property acts as a cache of the keys bound to the tag, so we don’t have to query the tag, as the bound proc is the same for all keys.

Constant Summary collapse

MODES =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ MajorMode

Returns a new instance of MajorMode.



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ver/major_mode.rb', line 38

def initialize(name)
  self.name = name.to_sym
  self.minors = []
  self.keymap = Keymap.new
  self.bound_keys = Set.new
  self.tag = Tk::BindTag.new("#{name}-mode")

  KEYSYMS.each{|key, sym| bind_key(sym) }
  bind_key('<Escape>')

  MODES[self.name] = self
end

Instance Attribute Details

#bound_keysObject

Returns the value of attribute bound_keys

Returns:

  • (Object)

    the current value of bound_keys



18
19
20
# File 'lib/ver/major_mode.rb', line 18

def bound_keys
  @bound_keys
end

#fallback_actionObject

Returns the value of attribute fallback_action

Returns:

  • (Object)

    the current value of fallback_action



18
19
20
# File 'lib/ver/major_mode.rb', line 18

def fallback_action
  @fallback_action
end

#keymapObject

Returns the value of attribute keymap

Returns:

  • (Object)

    the current value of keymap



18
19
20
# File 'lib/ver/major_mode.rb', line 18

def keymap
  @keymap
end

#minorsObject

Returns the value of attribute minors

Returns:

  • (Object)

    the current value of minors



18
19
20
# File 'lib/ver/major_mode.rb', line 18

def minors
  @minors
end

#nameObject

Returns the value of attribute name

Returns:

  • (Object)

    the current value of name



18
19
20
# File 'lib/ver/major_mode.rb', line 18

def name
  @name
end

#receiverObject

Returns the value of attribute receiver

Returns:

  • (Object)

    the current value of receiver



18
19
20
# File 'lib/ver/major_mode.rb', line 18

def receiver
  @receiver
end

#tagObject

Returns the value of attribute tag

Returns:

  • (Object)

    the current value of tag



18
19
20
# File 'lib/ver/major_mode.rb', line 18

def tag
  @tag
end

Class Method Details

.[](name) ⇒ Object



24
25
26
27
28
29
30
31
32
# File 'lib/ver/major_mode.rb', line 24

def self.[](name)
  name = name.to_sym

  if MODES.key?(name)
    MODES[name]
  else
    new(name)
  end
end

.clearObject



34
35
36
# File 'lib/ver/major_mode.rb', line 34

def self.clear
  MODES.each_value(&:destroy)
end

Instance Method Details

#actionsObject



150
151
152
# File 'lib/ver/major_mode.rb', line 150

def actions
  keymap.actions
end

#bind_key(key) ⇒ Object



139
140
141
142
143
144
145
146
147
148
# File 'lib/ver/major_mode.rb', line 139

def bind_key(key)
  return if bound_keys.include?(key)

  tag.bind(key) do |event|
    event.widget.major_mode.on_event(event)
    Tk.callback_break
  end

  bound_keys << key
end

#destroyObject



51
52
53
54
# File 'lib/ver/major_mode.rb', line 51

def destroy
  tag.bind.each{|key| tag.unbind(key) }
  MODES.delete(name)
end

#enter(invocation, &block) ⇒ Object



74
75
76
77
78
79
# File 'lib/ver/major_mode.rb', line 74

def enter(invocation, &block)
  action = Action.new(receiver, *invocation, &block)
  tag.bind "<<EnterMajorMode#{to_camel_case}>>" do |event|
    action.call(WidgetEvent.new(event.widget, event))
  end
end

#forget(*minors) ⇒ Object



102
103
104
# File 'lib/ver/major_mode.rb', line 102

def forget(*minors)
  self.minors -= minors.map{|name| MinorMode[name] }
end

#handler(object) ⇒ Object



56
57
58
# File 'lib/ver/major_mode.rb', line 56

def handler(object)
  self.receiver = object
end

#inherits(name) ⇒ Object



88
89
90
91
# File 'lib/ver/major_mode.rb', line 88

def inherits(name)
  mode = self.class[name]
  keymap.merge!(mode.keymap)
end

#inspectObject



158
159
160
# File 'lib/ver/major_mode.rb', line 158

def inspect
  "#<VER::MajorMode name=%p>" % [name]
end

#leave(invocation, &block) ⇒ Object



81
82
83
84
85
86
# File 'lib/ver/major_mode.rb', line 81

def leave(invocation, &block)
  action = Action.new(receiver, *invocation, &block)
  tag.bind "<<LeaveMajorMode#{to_camel_case}>>" do |event|
    action.call(WidgetEvent.new(event.widget, event))
  end
end

#map(invocation, *sequences, &block) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/ver/major_mode.rb', line 60

def map(invocation, *sequences, &block)
  action = Action.new(receiver, *invocation, &block)

  sequences.each do |sequence|
    keymap[sequence] = action
  end
end

#missing(invocation, &block) ⇒ Object



68
69
70
71
72
# File 'lib/ver/major_mode.rb', line 68

def missing(invocation, &block)
  action = Action.new(receiver, *invocation, &block)
  self.fallback_action = action
  keymap['<Key>'] = action
end

#replace_minor(old, new) ⇒ Object



133
134
135
136
137
# File 'lib/ver/major_mode.rb', line 133

def replace_minor(old, new)
  minors.each do |minor|
    minor.replace_parent(self, MinorMode[old], MinorMode[new])
  end
end

#resolve(sequence, minors = []) ⇒ Object

recursively try to find the sequence in the major mode and its minor modes.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/ver/major_mode.rb', line 108

def resolve(sequence, minors = [])
  case found = keymap[sequence]
  when Incomplete
    minors.each do |minor|
      case resolved = minor.resolve(sequence)
      when Incomplete
        found.merge!(resolved)
      end
    end
  when Impossible
    minors.find do |minor|
      found = minor.resolve(sequence)
      !found.kind_of?(Impossible)
    end
  else
    found = [self, found]
  end

  if found.kind_of?(Impossible) && fa = self.fallback_action
    return self, fa
  else
    return found
  end
end

#to_symObject



154
155
156
# File 'lib/ver/major_mode.rb', line 154

def to_sym
  name
end

#use(*minors) ⇒ Object



93
94
95
96
97
98
99
100
# File 'lib/ver/major_mode.rb', line 93

def use(*minors)
  minors.each do |name|
    minor = MinorMode[name]
    self.minors << minor
  end

  self.minors.uniq!
end