niklas-vimmate 0.8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest +10 -0
- data/CHANGELOG +108 -0
- data/COPYING +20 -0
- data/README +221 -0
- data/Rakefile +97 -0
- data/TODO +21 -0
- data/bin/vimmate +95 -0
- data/config/environment.rb +33 -0
- data/controllers/file_filter_controller.rb +85 -0
- data/controllers/file_popup_menu_controller.rb +40 -0
- data/controllers/vim_controller.rb +28 -0
- data/controllers/vim_mate_controller.rb +76 -0
- data/images/file.png +0 -0
- data/images/file_green.png +0 -0
- data/images/file_orange.png +0 -0
- data/images/file_red.png +0 -0
- data/images/folder.png +0 -0
- data/images/folder_green.png +0 -0
- data/images/folder_orange.png +0 -0
- data/images/folder_red.png +0 -0
- data/images/processing.png +0 -0
- data/images/svn_added.png +0 -0
- data/images/svn_conflict.png +0 -0
- data/images/svn_deleted.png +0 -0
- data/images/svn_locked.png +0 -0
- data/images/svn_modified.png +0 -0
- data/images/svn_normal.png +0 -0
- data/images/svn_readonly.png +0 -0
- data/images/vimmate16.png +0 -0
- data/images/vimmate32.png +0 -0
- data/images/vimmate48.png +0 -0
- data/lib/active_window.rb +8 -0
- data/lib/active_window/active_column.rb +218 -0
- data/lib/active_window/active_tree_store.rb +13 -0
- data/lib/active_window/active_tree_store/columns.rb +88 -0
- data/lib/active_window/active_tree_store/extentions.rb +81 -0
- data/lib/active_window/active_tree_store/index.rb +53 -0
- data/lib/active_window/application.rb +133 -0
- data/lib/active_window/controller.rb +58 -0
- data/lib/active_window/dot_file.rb +29 -0
- data/lib/active_window/filtered_active_tree_store.rb +114 -0
- data/lib/active_window/listed_item.rb +127 -0
- data/lib/active_window/signal.rb +46 -0
- data/lib/config_window.rb +90 -0
- data/lib/file_tree_store.rb +73 -0
- data/lib/filtered_file_tree_store.rb +34 -0
- data/lib/gtk_thread_helper.rb +73 -0
- data/lib/listed_directory.rb +43 -0
- data/lib/listed_file.rb +67 -0
- data/lib/try.rb +9 -0
- data/lib/vim/buffers.rb +18 -0
- data/lib/vim/integration.rb +36 -0
- data/lib/vim/netbeans.rb +156 -0
- data/lib/vim/source.vim +18 -0
- data/lib/vim_mate/config.rb +132 -0
- data/lib/vim_mate/dummy_window.rb +14 -0
- data/lib/vim_mate/files_menu.rb +110 -0
- data/lib/vim_mate/icons.rb +156 -0
- data/lib/vim_mate/nice_singleton.rb +53 -0
- data/lib/vim_mate/plugins.rb +6 -0
- data/lib/vim_mate/plugins/inotify/init.rb +4 -0
- data/lib/vim_mate/plugins/inotify/lib/INotify.rb +206 -0
- data/lib/vim_mate/plugins/inotify/lib/directory.rb +58 -0
- data/lib/vim_mate/plugins/subversion/init.rb +7 -0
- data/lib/vim_mate/plugins/subversion/lib/file.rb +59 -0
- data/lib/vim_mate/plugins/subversion/lib/menu.rb +96 -0
- data/lib/vim_mate/plugins/subversion/lib/subversion.rb +157 -0
- data/lib/vim_mate/requirer.rb +68 -0
- data/lib/vim_mate/search_window.rb +227 -0
- data/lib/vim_mate/tags_window.rb +167 -0
- data/lib/vim_mate/terminals_window.rb +163 -0
- data/lib/vim_mate/version.rb +29 -0
- data/lib/vim_mate/vim_widget.rb +150 -0
- data/spec/active_window/active_column_spec.rb +41 -0
- data/spec/active_window/active_tree_store_spec.rb +312 -0
- data/spec/active_window/controller_spec.rb +6 -0
- data/spec/lib/file_tree_store_spec.rb +40 -0
- data/spec/lib/listed_directory_spec.rb +26 -0
- data/spec/lib/listed_file_spec.rb +53 -0
- data/spec/nice_singleton_spec.rb +23 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +10 -0
- data/views/vim_mate.glade +308 -0
- data/vimmate.gemspec +131 -0
- metadata +168 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
class ActiveTreeStore < Gtk::TreeStore
|
3
|
+
include TreeStoreExtentions
|
4
|
+
virtual_column :visible, TrueClass, :visible => false
|
5
|
+
virtual_column :object, Object, :visible => false
|
6
|
+
define_callbacks :after_add
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
super(*self.class.column_classes)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
module ActiveTreeStoreColumns
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
class_inheritable_accessor :column_id
|
6
|
+
write_inheritable_attribute :column_id, {}
|
7
|
+
class_inheritable_accessor :columns
|
8
|
+
write_inheritable_attribute :columns, []
|
9
|
+
include InstanceMethods
|
10
|
+
extend ClassMethods
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def columns
|
16
|
+
self.class.columns
|
17
|
+
end
|
18
|
+
|
19
|
+
def data_columns
|
20
|
+
self.class.data_columns
|
21
|
+
end
|
22
|
+
|
23
|
+
def visible_columns
|
24
|
+
self.class.visible_columns
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
# options:
|
31
|
+
# :virtual: (bool )does not take actual values
|
32
|
+
# :visible: (bool) should be shown in the view
|
33
|
+
def column(label,type, opts={})
|
34
|
+
return columns[column_id[label.to_sym]] if column_id.has_key?(label.to_sym) # do not double-define
|
35
|
+
opts.reverse_merge!(:visible => true, :virtual => false)
|
36
|
+
index = column_count
|
37
|
+
column_id[label.to_sym] = index
|
38
|
+
col = ActiveColumn.create(index, label, type, opts)
|
39
|
+
columns << col
|
40
|
+
const_set label.to_s.upcase, index
|
41
|
+
class_eval <<-EOCODE
|
42
|
+
def self.#{label}_column
|
43
|
+
#{index}
|
44
|
+
end
|
45
|
+
EOCODE
|
46
|
+
return col
|
47
|
+
end
|
48
|
+
|
49
|
+
def composite_column(label)
|
50
|
+
col = ActiveCompositeColumn.new(label)
|
51
|
+
yield col
|
52
|
+
columns << col
|
53
|
+
return col
|
54
|
+
end
|
55
|
+
|
56
|
+
def virtual_column(label, type, opts={})
|
57
|
+
column label, type, opts.merge(:virtual => true)
|
58
|
+
end
|
59
|
+
|
60
|
+
# visible vs. virtual
|
61
|
+
def data_columns
|
62
|
+
columns.reject(&:virtual?)
|
63
|
+
end
|
64
|
+
|
65
|
+
def visible_columns
|
66
|
+
columns.select(&:visible?)
|
67
|
+
end
|
68
|
+
|
69
|
+
def invisible_columns
|
70
|
+
columns.reject(&:visible?)
|
71
|
+
end
|
72
|
+
|
73
|
+
def column_count
|
74
|
+
columns.size
|
75
|
+
end
|
76
|
+
|
77
|
+
def column_classes
|
78
|
+
columns.map(&:data_class)
|
79
|
+
end
|
80
|
+
|
81
|
+
def setup_column_id_constants
|
82
|
+
column_id.each do |sym, index|
|
83
|
+
const_set sym.to_s.upcase, index
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
module TreeStoreExtentions
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
include ActiveSupport::Callbacks
|
7
|
+
include ActiveTreeStoreColumns
|
8
|
+
include ActiveTreeStoreIndex
|
9
|
+
end
|
10
|
+
end
|
11
|
+
## associates a Gtk::TreeView widget with self (a tree model).
|
12
|
+
def apply_to_tree(treeview, opts={})
|
13
|
+
raise ArgumentError, "please provide a Gtk::TreeView" unless treeview.is_a?(Gtk::TreeView)
|
14
|
+
treeview.model = self
|
15
|
+
cols = self.class.visible_columns
|
16
|
+
cols = cols.except(opts[:except]) if opts.has_key?(:except)
|
17
|
+
cols = cols.slice(opts[:only]) if opts.has_key?(:only)
|
18
|
+
cols.map(&:view).each do |column|
|
19
|
+
treeview.append_column(column)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Populare the Tree with an array of objects. The Tree gets cleared first.
|
24
|
+
def populate(array)
|
25
|
+
clear
|
26
|
+
array.each do |element|
|
27
|
+
self.add element
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# The original object for +iter+.
|
32
|
+
# FIXME remove
|
33
|
+
def get_object(iter)
|
34
|
+
raise "depricated - please use iter[OBJECT]"
|
35
|
+
iter[ self.class.column_id[:object] ]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add +object+ to tree, give optional +parent+
|
39
|
+
def add(object, parent=nil)
|
40
|
+
iter = self.append parent
|
41
|
+
case object
|
42
|
+
when Hash
|
43
|
+
update_iter_from_hash iter, object
|
44
|
+
else
|
45
|
+
update_iter_from_object iter, object
|
46
|
+
end
|
47
|
+
iter[ self.class.column_id[:object] ] = object
|
48
|
+
iter
|
49
|
+
end
|
50
|
+
|
51
|
+
# Updates the display in the tree/list of the given object
|
52
|
+
def refresh(object)
|
53
|
+
each do |model,path,iter|
|
54
|
+
if iter[OBJECT] == object
|
55
|
+
update_iter_from_object(iter, object)
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def update_iter_from_object(iter, object)
|
63
|
+
data_columns.each do |column|
|
64
|
+
iter[column.id] = column.data_value(object)
|
65
|
+
end
|
66
|
+
iter
|
67
|
+
end
|
68
|
+
def update_iter_from_hash(iter, hash = {})
|
69
|
+
hash.symbolize_keys.each do |key,value|
|
70
|
+
if id = self.class.column_id[key]
|
71
|
+
iter[ id ] = value
|
72
|
+
end
|
73
|
+
end
|
74
|
+
iter
|
75
|
+
end
|
76
|
+
|
77
|
+
def reference_for(iter)
|
78
|
+
Gtk::TreeRowReference.new(self, iter.path)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
module ActiveTreeStoreIndex
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
include InstanceMethods
|
6
|
+
extend ClassMethods
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def index_by(column)
|
15
|
+
by = %Q~by_#{column}~
|
16
|
+
raise "cannot index by #{column}, it is already applied" if public_instance_methods.include?("find_#{by}")
|
17
|
+
class_eval <<-EOCODE
|
18
|
+
def find_#{by}!(val)
|
19
|
+
find_#{by}(val) || raise("cannot find by #{column}: '\#{val}'")
|
20
|
+
end
|
21
|
+
def find_#{by}(val)
|
22
|
+
if ref = has_#{column}?(val)
|
23
|
+
self.get_iter(ref.path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def has_#{column}?(val)
|
27
|
+
index_#{by}[val]
|
28
|
+
end
|
29
|
+
def remember_iter_#{by}(iter)
|
30
|
+
val = iter[ self.class.column_id[:#{column}] ]
|
31
|
+
index_#{by}[val] = reference_for(iter)
|
32
|
+
end
|
33
|
+
def index_#{by}
|
34
|
+
@index_#{by} ||= {}
|
35
|
+
end
|
36
|
+
def add_with_index_#{by}(*args)
|
37
|
+
iter = add_without_index_#{by}(*args)
|
38
|
+
remember_iter_#{by}(iter)
|
39
|
+
iter
|
40
|
+
end
|
41
|
+
alias_method_chain :add, :index_#{by}
|
42
|
+
def remove_with_index_#{by}(iter)
|
43
|
+
index_#{by}.delete iter[ self.class.column_id[:#{column}] ]
|
44
|
+
remove_without_index_#{by}(iter)
|
45
|
+
end
|
46
|
+
alias_method_chain :remove, :index_#{by}
|
47
|
+
EOCODE
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
class ActiveWindow::Application
|
2
|
+
include ActiveSupport::Callbacks
|
3
|
+
define_callbacks :after_initialize
|
4
|
+
|
5
|
+
attr_accessor :controller, :database, :glade, :window
|
6
|
+
|
7
|
+
def widget(name)
|
8
|
+
glade[name]
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@glade = GladeXML.new(find_glade, nil, options[:title] || 'application' )
|
13
|
+
@window = widget(options[:main_window] || 'main_window')
|
14
|
+
@window.signal_connect("destroy") { Gtk.main_quit }
|
15
|
+
@dot_file_prefs = DotFile.read
|
16
|
+
@database = options[:database]
|
17
|
+
define_widget_readers
|
18
|
+
run_callbacks :after_initialize
|
19
|
+
end
|
20
|
+
|
21
|
+
def start
|
22
|
+
setup
|
23
|
+
post_setup
|
24
|
+
window.show
|
25
|
+
Gtk.main
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_database
|
29
|
+
@dot_file_prefs[:db]
|
30
|
+
end
|
31
|
+
|
32
|
+
def save_default_database(hash)
|
33
|
+
@dot_file_prefs[:db] = hash
|
34
|
+
@dot_file_prefs.save
|
35
|
+
end
|
36
|
+
|
37
|
+
# creates the controllers, connects the signals
|
38
|
+
# calls 'setup' on each controller
|
39
|
+
def setup
|
40
|
+
@controller = {}
|
41
|
+
|
42
|
+
Module.constants.grep(/.Controller$/).each do |klass|
|
43
|
+
ctrl = Kernel.const_get(klass).instance
|
44
|
+
ctrl.application = self
|
45
|
+
ctrl.setup
|
46
|
+
name = klass.to_s.sub('Controller','').underscore.to_sym # eg MyFirstController -> :my_first
|
47
|
+
controller[name] = ctrl
|
48
|
+
end
|
49
|
+
|
50
|
+
glade.signal_autoconnect_full do |source, target, signal, handler, data|
|
51
|
+
# for example:
|
52
|
+
# source : instance of Gtk::ImageMenuItem
|
53
|
+
# target : nil
|
54
|
+
# signal : activate, clicked, pressed, etc.
|
55
|
+
# handler : window.close, which would call WindowController.close()
|
56
|
+
# data : nil
|
57
|
+
#puts [source, target, signal, handler, data].inspect
|
58
|
+
source.signal_connect(signal) { |widget,event| self.dispatch(handler, :source => source, :target => target, :signal => signal, :handler => handler, :data => data, :widget => widget, :event => event) }
|
59
|
+
#source.signal_connect(signal) { self.(handler, data) }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# calls post_setup on each controller
|
64
|
+
def post_setup
|
65
|
+
controller.each do |name,ctrl|
|
66
|
+
ctrl.post_setup
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
## dispatch a signal to the correct controller
|
72
|
+
##
|
73
|
+
def dispatch(handler, event)
|
74
|
+
controller_name,action = handler.to_s.split('.')
|
75
|
+
unless controller_name and action
|
76
|
+
return(error "cannot parse handler '%s'" % handler)
|
77
|
+
end
|
78
|
+
|
79
|
+
name = controller_name.to_sym
|
80
|
+
ctrl = controller[name]
|
81
|
+
unless ctrl
|
82
|
+
puts controller.inspect
|
83
|
+
return(error "no controller '%s' defined" % controller_name.camelize)
|
84
|
+
end
|
85
|
+
|
86
|
+
unless ctrl.respond_to? action
|
87
|
+
return(error "controller '%s' does not have a method '%s'" % [ctrl.class, action])
|
88
|
+
end
|
89
|
+
|
90
|
+
method = ctrl.method(action)
|
91
|
+
#puts "calling %s.%s" % [controller_name.camelize, action]
|
92
|
+
if method.arity == 0
|
93
|
+
method.call
|
94
|
+
else
|
95
|
+
method.call(event)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def class_exists?(classname)
|
103
|
+
return (Kernel::const_get(classname) rescue NameError) != NameError
|
104
|
+
end
|
105
|
+
|
106
|
+
def error(msg)
|
107
|
+
puts msg
|
108
|
+
end
|
109
|
+
|
110
|
+
def find_glade
|
111
|
+
Dir.glob("#{views_directory}/*.glade") do |f|
|
112
|
+
return f
|
113
|
+
end
|
114
|
+
raise "could not find a .glade file in #{views_directory}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def views_directory
|
118
|
+
File.join(APP_ROOT, 'views')
|
119
|
+
end
|
120
|
+
|
121
|
+
def define_widget_readers
|
122
|
+
glade.widget_names.each do |widget|
|
123
|
+
meth = widget.underscore
|
124
|
+
instance_eval <<-EOEVAL
|
125
|
+
@#{meth} = glade['#{widget}']
|
126
|
+
def #{meth}
|
127
|
+
@#{meth}
|
128
|
+
end
|
129
|
+
EOEVAL
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# require 'libglade2'
|
2
|
+
# require 'gtk2'
|
3
|
+
|
4
|
+
class ActiveWindow::Controller
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
attr_accessor :application
|
8
|
+
|
9
|
+
def app
|
10
|
+
application
|
11
|
+
end
|
12
|
+
|
13
|
+
def widget(name)
|
14
|
+
application.widget(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def controller
|
18
|
+
application.controller
|
19
|
+
end
|
20
|
+
|
21
|
+
def window
|
22
|
+
application.window
|
23
|
+
end
|
24
|
+
|
25
|
+
def database
|
26
|
+
application.database
|
27
|
+
end
|
28
|
+
|
29
|
+
# called on startup
|
30
|
+
def setup
|
31
|
+
end
|
32
|
+
|
33
|
+
# called on startup, after setup has been called for all controllers
|
34
|
+
def post_setup
|
35
|
+
end
|
36
|
+
|
37
|
+
def pref_set(key,value)
|
38
|
+
Preference.delete_all ['pref = ?', key]
|
39
|
+
Preference.create(:pref => key, :value => value)
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def pref_get(key)
|
44
|
+
pref = Preference.find_by_pref(key)
|
45
|
+
return pref.value if pref
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def pref_get_or_set(key,value)
|
50
|
+
pref_get(key) || pref_set(key,value)
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(name, *args, &block)
|
54
|
+
application.send name, *args, &block
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
A simple class for reading and writing settings information
|
4
|
+
to a dot file (~/.appname.yml)
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
8
|
+
module ActiveWindow
|
9
|
+
class DotFile < ::Hash
|
10
|
+
def self.read(fname=nil)
|
11
|
+
fname ||= filename
|
12
|
+
unless File.exists? fname
|
13
|
+
new.save(fname)
|
14
|
+
end
|
15
|
+
YAML.load_file( fname )
|
16
|
+
end
|
17
|
+
|
18
|
+
def save(fname=nil)
|
19
|
+
fname ||= self.class.filename
|
20
|
+
File.open( fname, 'w+' ) do |out|
|
21
|
+
YAML.dump( self, out )
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.filename
|
26
|
+
File.join ENV['HOME'], ".#{PROGRAM_NAME}.yml"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|