Class: VER::MinorMode

Inherits:
Struct
  • Object
show all
Includes:
Keymap::Results, ModeResolving, Platform
Defined in:
lib/ver/minor_mode.rb

Overview

A minor mode contains modifications for major modes. It supports unidirectional inheritance to form a tree-like structure together with other instance of MinorMode. Every minor mode maintains its own keymap and performs lookup within that. When no match can be found, the parents will be asked until a definite result is returned.

A MinorMode is expected to interact with the WidgetMajorMode only, not with MajorMode directly.

Modification of a MinorMode will not be fully reflected until the

WidgetMajorMode#synchronize

method has been called and the minor mode is

part of the tree of minors of this major mode.

Constant Summary collapse

MODES =
{}

Constants inherited from Struct

Struct::CACHE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ModeResolving

#resolve_impossible, #resolve_incomplete

Methods included from Platform

aqua?, bsd?, mac?, operatingsystem, unix?, win32?, windowingsystem, windows?, x11?

Methods inherited from Struct

new

Constructor Details

#initialize(name) ⇒ MinorMode

Returns a new instance of MinorMode.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/ver/minor_mode.rb', line 46

def initialize(name)
  self.name = name = name.to_sym

  if MODES.key?(name)
    raise ArgumentError, "Duplicate #{self.class}: %p" % [name]
  else
    MODES[name] = self
  end

  self.parents = []
  self.keymap = Keymap.new
  self.receiver = nil

  MODES[self.name] = self
end

Instance Attribute Details

#enter_actionObject

Returns the value of attribute enter_action

Returns:

  • (Object)

    the current value of enter_action



22
23
24
# File 'lib/ver/minor_mode.rb', line 22

def enter_action
  @enter_action
end

#fallback_actionObject

Returns the value of attribute fallback_action

Returns:

  • (Object)

    the current value of fallback_action



22
23
24
# File 'lib/ver/minor_mode.rb', line 22

def fallback_action
  @fallback_action
end

#keymapObject

Returns the value of attribute keymap

Returns:

  • (Object)

    the current value of keymap



22
23
24
# File 'lib/ver/minor_mode.rb', line 22

def keymap
  @keymap
end

#leave_actionObject

Returns the value of attribute leave_action

Returns:

  • (Object)

    the current value of leave_action



22
23
24
# File 'lib/ver/minor_mode.rb', line 22

def leave_action
  @leave_action
end

#nameObject

Returns the value of attribute name

Returns:

  • (Object)

    the current value of name



22
23
24
# File 'lib/ver/minor_mode.rb', line 22

def name
  @name
end

#parentsObject

Returns the value of attribute parents

Returns:

  • (Object)

    the current value of parents



22
23
24
# File 'lib/ver/minor_mode.rb', line 22

def parents
  @parents
end

#receiverObject

Returns the value of attribute receiver

Returns:

  • (Object)

    the current value of receiver



22
23
24
# File 'lib/ver/minor_mode.rb', line 22

def receiver
  @receiver
end

Class Method Details

.[](name) ⇒ Object

Find or create the minor mode for the given name.



31
32
33
34
35
36
37
38
39
# File 'lib/ver/minor_mode.rb', line 31

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

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

.clearObject

Delete all minor modes.



42
43
44
# File 'lib/ver/minor_mode.rb', line 42

def self.clear
  MODES.clear
end

Instance Method Details

#actionsObject



172
173
174
# File 'lib/ver/minor_mode.rb', line 172

def actions
  unfold.map{|minor| minor.keymap.actions }
end

#become(other, *patterns) ⇒ Object



78
79
80
81
# File 'lib/ver/minor_mode.rb', line 78

def become(other, *patterns)
  action = Action.new([:minor_mode, self, other], receiver, self)
  patterns.each{|pattern| keymap[pattern] = action }
end

#enter(invocation, &block) ⇒ Object



93
94
95
96
# File 'lib/ver/minor_mode.rb', line 93

def enter(invocation, &block)
  action = Action.new(invocation, receiver, self)
  self.enter_action = action
end

#eql?(other) ⇒ Boolean

we assume that name is unique

Returns:

  • (Boolean)


189
190
191
# File 'lib/ver/minor_mode.rb', line 189

def eql?(other)
  other.class == self.class && other.name == self.name
end

#handler(object) ⇒ Object



103
104
105
# File 'lib/ver/minor_mode.rb', line 103

def handler(object)
  self.receiver = object
end

#hashObject



184
185
186
# File 'lib/ver/minor_mode.rb', line 184

def hash
  name.hash
end

#inherits(*names) ⇒ Object

Add a parent for this minor mode.



68
69
70
71
72
73
74
75
76
# File 'lib/ver/minor_mode.rb', line 68

def inherits(*names)
  names.each do |name|
    minor = self.class[name]
    next if minor == self
    parents << minor
  end

  parents.uniq!
end

#inspectObject



180
181
182
# File 'lib/ver/minor_mode.rb', line 180

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

#leave(invocation, &block) ⇒ Object



98
99
100
101
# File 'lib/ver/minor_mode.rb', line 98

def leave(invocation, &block)
  action = Action.new(invocation, receiver, self)
  self.leave_action = action
end

#map(invocation, *patterns) ⇒ Object



83
84
85
86
# File 'lib/ver/minor_mode.rb', line 83

def map(invocation, *patterns)
  action = Action.new(invocation, receiver, self)
  patterns.each{|pattern| keymap[pattern] = action }
end

#missing(invocation, &block) ⇒ Object



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

def missing(invocation, &block)
  action = Fallback.new(invocation, receiver, self)
  self.fallback_action = action
end

#replace_parent(widget_major, old, new) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
# File 'lib/ver/minor_mode.rb', line 107

def replace_parent(widget_major, old, new)
  parents.dup.each do |parent|
    if parent == old
      new.replaces widget_major, old do
        parents[parents.index(old)] = new
      end
    else
      parent.replace_parent(widget_major, old, new)
    end
  end
end

#replaced_by(widget_major, other) ⇒ Object



125
126
127
128
129
130
131
132
# File 'lib/ver/minor_mode.rb', line 125

def replaced_by(widget_major, other)
  return unless widget_major.respond_to?(:widget)
  widget = widget_major.widget
  leave_action.call(widget, self, other) if leave_action
  Tk::Event.generate(widget, "<<LeaveMode>>", data: name)
  Tk::Event.generate(widget, "<<LeaveMinorMode>>", data: name)
  Tk::Event.generate(widget, "<<LeaveMinorMode#{to_camel_case}>>", data: name)
end

#replaces(widget_major, other) ⇒ Object



119
120
121
122
123
# File 'lib/ver/minor_mode.rb', line 119

def replaces(widget_major, other)
  other.replaced_by(widget_major, self) if other
  yield if block_given?
  self.replacing(widget_major, other)
end

#replacing(widget_major, other) ⇒ Object



134
135
136
137
138
139
140
141
# File 'lib/ver/minor_mode.rb', line 134

def replacing(widget_major, other)
  return unless widget_major.respond_to?(:widget)
  widget = widget_major.widget
  enter_action.call(widget, other, self) if enter_action
  Tk::Event.generate(widget, "<<EnterMinorMode#{to_camel_case}>>", data: name)
  Tk::Event.generate(widget, "<<EnterMinorMode>>", data: name)
  Tk::Event.generate(widget, "<<EnterMode>>", data: name)
end

#resolve(pattern) ⇒ Object

recursively try to find the pattern in the minor mode and its parents.



63
64
65
# File 'lib/ver/minor_mode.rb', line 63

def resolve(pattern)
  super(pattern, parents)
end

#synchronize(widget_major) ⇒ Object



149
150
151
152
153
# File 'lib/ver/minor_mode.rb', line 149

def synchronize(widget_major)
  keymap.keys.each do |key|
    widget_major.bind_key(key)
  end
end

#synchronize_recursively(widget_major) ⇒ Object



143
144
145
146
147
# File 'lib/ver/minor_mode.rb', line 143

def synchronize_recursively(widget_major)
  unfold.each do |minor|
    minor.synchronize(widget_major)
  end
end

#to_camel_caseObject



168
169
170
# File 'lib/ver/minor_mode.rb', line 168

def to_camel_case
  name.to_s.split('_').map{|e| e.capitalize}.join
end

#to_symObject



176
177
178
# File 'lib/ver/minor_mode.rb', line 176

def to_sym
  name
end

#unfold(all = [self]) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/ver/minor_mode.rb', line 155

def unfold(all = [self])
  pending = self.parents.dup

  while current = pending.shift
    unless all.include?(current)
      all << current
      pending.concat(current.unfold(all)).flatten!
    end
  end

  all
end