vimmate 0.8.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.
Files changed (85) hide show
  1. data/.autotest +10 -0
  2. data/CHANGELOG +108 -0
  3. data/COPYING +20 -0
  4. data/README +221 -0
  5. data/Rakefile +31 -0
  6. data/TODO +21 -0
  7. data/bin/vimmate +105 -0
  8. data/config/environment.rb +35 -0
  9. data/controllers/file_filter_controller.rb +101 -0
  10. data/controllers/file_popup_menu_controller.rb +40 -0
  11. data/controllers/vim_controller.rb +28 -0
  12. data/controllers/vim_mate_controller.rb +76 -0
  13. data/images/file.png +0 -0
  14. data/images/file_green.png +0 -0
  15. data/images/file_orange.png +0 -0
  16. data/images/file_red.png +0 -0
  17. data/images/folder.png +0 -0
  18. data/images/folder_green.png +0 -0
  19. data/images/folder_orange.png +0 -0
  20. data/images/folder_red.png +0 -0
  21. data/images/processing.png +0 -0
  22. data/images/svn_added.png +0 -0
  23. data/images/svn_conflict.png +0 -0
  24. data/images/svn_deleted.png +0 -0
  25. data/images/svn_locked.png +0 -0
  26. data/images/svn_modified.png +0 -0
  27. data/images/svn_normal.png +0 -0
  28. data/images/svn_readonly.png +0 -0
  29. data/images/vimmate16.png +0 -0
  30. data/images/vimmate32.png +0 -0
  31. data/images/vimmate48.png +0 -0
  32. data/lib/active_window/active_column.rb +218 -0
  33. data/lib/active_window/active_tree_store/columns.rb +88 -0
  34. data/lib/active_window/active_tree_store/extentions.rb +81 -0
  35. data/lib/active_window/active_tree_store/index.rb +53 -0
  36. data/lib/active_window/active_tree_store.rb +26 -0
  37. data/lib/active_window/application.rb +137 -0
  38. data/lib/active_window/controller.rb +58 -0
  39. data/lib/active_window/dot_file.rb +29 -0
  40. data/lib/active_window/filtered_active_tree_store.rb +113 -0
  41. data/lib/active_window/listed_item.rb +127 -0
  42. data/lib/active_window/signal.rb +46 -0
  43. data/lib/active_window.rb +8 -0
  44. data/lib/config_window.rb +90 -0
  45. data/lib/file_tree_store.rb +74 -0
  46. data/lib/filtered_file_tree_store.rb +34 -0
  47. data/lib/gtk_thread_helper.rb +73 -0
  48. data/lib/listed_directory.rb +45 -0
  49. data/lib/listed_file.rb +67 -0
  50. data/lib/try.rb +9 -0
  51. data/lib/vim/buffers.rb +18 -0
  52. data/lib/vim/integration.rb +38 -0
  53. data/lib/vim/netbeans.rb +154 -0
  54. data/lib/vim/source.vim +18 -0
  55. data/lib/vim_mate/config.rb +132 -0
  56. data/lib/vim_mate/dummy_window.rb +14 -0
  57. data/lib/vim_mate/files_menu.rb +110 -0
  58. data/lib/vim_mate/icons.rb +156 -0
  59. data/lib/vim_mate/nice_singleton.rb +53 -0
  60. data/lib/vim_mate/plugins/inotify/init.rb +4 -0
  61. data/lib/vim_mate/plugins/inotify/lib/INotify.rb +208 -0
  62. data/lib/vim_mate/plugins/inotify/lib/directory.rb +58 -0
  63. data/lib/vim_mate/plugins/subversion/init.rb +7 -0
  64. data/lib/vim_mate/plugins/subversion/lib/file.rb +59 -0
  65. data/lib/vim_mate/plugins/subversion/lib/menu.rb +96 -0
  66. data/lib/vim_mate/plugins/subversion/lib/subversion.rb +157 -0
  67. data/lib/vim_mate/plugins.rb +6 -0
  68. data/lib/vim_mate/requirer.rb +68 -0
  69. data/lib/vim_mate/search_window.rb +227 -0
  70. data/lib/vim_mate/tags_window.rb +167 -0
  71. data/lib/vim_mate/terminals_window.rb +163 -0
  72. data/lib/vim_mate/version.rb +29 -0
  73. data/lib/vim_mate/vim_widget.rb +143 -0
  74. data/spec/active_window/active_column_spec.rb +41 -0
  75. data/spec/active_window/active_tree_store_spec.rb +312 -0
  76. data/spec/active_window/controller_spec.rb +6 -0
  77. data/spec/lib/file_tree_store_spec.rb +40 -0
  78. data/spec/lib/listed_directory_spec.rb +26 -0
  79. data/spec/lib/listed_file_spec.rb +53 -0
  80. data/spec/nice_singleton_spec.rb +23 -0
  81. data/spec/spec.opts +6 -0
  82. data/spec/spec_helper.rb +10 -0
  83. data/views/vim_mate.glade +500 -0
  84. data/vimmate.gemspec +138 -0
  85. metadata +146 -0
@@ -0,0 +1,110 @@
1
+ =begin
2
+ = VimMate: Vim graphical add-on
3
+ Copyright (c) 2006 Guillaume Benny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+ =end
23
+
24
+ require 'fileutils'
25
+ require 'set'
26
+ module VimMate
27
+
28
+ # The pop-up menu used in the file tree
29
+ class FilesMenu
30
+
31
+ # Open a dialog to enter a new folder name to create
32
+ def menu_new_folder
33
+ dialog = Gtk::FileChooserDialog.new("New folder",
34
+ @parent_window.gtk_window,
35
+ Gtk::FileChooser::ACTION_CREATE_FOLDER,
36
+ nil,
37
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
38
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
39
+ dialog.set_icon_list(Icons.window_icons)
40
+ dialog.current_folder = if File.directory? @last_path
41
+ @last_path
42
+ else
43
+ File.dirname(@last_path)
44
+ end
45
+ dialog.run
46
+ dialog.destroy
47
+ menu_refresh
48
+ end
49
+
50
+ # Open a dialog to enter a new name for a file or directory
51
+ def menu_rename
52
+ dialog = Gtk::FileChooserDialog.new("Rename #{File.basename(@last_path)}",
53
+ @parent_window.gtk_window,
54
+ Gtk::FileChooser::ACTION_SAVE,
55
+ nil,
56
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
57
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
58
+ dialog.set_icon_list(Icons.window_icons)
59
+ dialog.current_folder = File.dirname(@last_path)
60
+ if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
61
+ begin
62
+ File.rename(@last_path, dialog.filename)
63
+ rescue SystemCallError
64
+ $stderr.puts "Cannot rename from #{@last_path} to #{dialog.filename}"
65
+ end
66
+ end
67
+ dialog.destroy
68
+ menu_refresh
69
+ end
70
+
71
+ # Open a dialog and ask the user if he really wants to delete the target
72
+ # file or directory. Note that for safety, directories can only be removed
73
+ # if they are empty.
74
+ def menu_delete
75
+ name = File.basename(@last_path)
76
+ dialog = Gtk::MessageDialog.new(@parent_window.gtk_window,
77
+ Gtk::MessageDialog::Flags::MODAL,
78
+ Gtk::MessageDialog::Type::QUESTION,
79
+ Gtk::MessageDialog::ButtonsType::YES_NO,
80
+ if File.directory? @last_path
81
+ "Delete directory #{name} ?"
82
+ else
83
+ "Delete file #{name} ?"
84
+ end)
85
+ dialog.set_icon_list(Icons.window_icons)
86
+ if dialog.run == Gtk::Dialog::RESPONSE_YES
87
+ begin
88
+ if File.directory? @last_path
89
+ FileUtils.rmdir(@last_path)
90
+ else
91
+ FileUtils.rm(@last_path)
92
+ end
93
+ rescue
94
+ $stderr.puts "Cannot remove #{@last_path}"
95
+ end
96
+ end
97
+ dialog.destroy
98
+ menu_refresh
99
+ end
100
+
101
+ # Signals that the file tree must be refreshed
102
+ def menu_refresh
103
+ @refresh_signals.each do |signal|
104
+ signal.call
105
+ end
106
+ end
107
+
108
+ end
109
+ end
110
+
@@ -0,0 +1,156 @@
1
+ =begin
2
+ = VimMate: Vim graphical add-on
3
+ Copyright (c) 2006 Guillaume Benny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+ =end
23
+
24
+ module VimMate
25
+
26
+ # Manages the icons that can be loaded from the disk
27
+ class Icons
28
+ include NiceSingleton
29
+
30
+ # The filenames for the icons of the windows
31
+ WINDOW_ICON_FILENAME = 'vimmate%d.png'.freeze
32
+ # The size for the icons of the windows
33
+ WINDOW_ICON_SIZES = [16, 32, 48].freeze
34
+
35
+ Overlays = %w(scm progress type)
36
+
37
+ # Create the Icons class. Cannot be called directly
38
+ def initialize
39
+ @gtk_window_icons = []
40
+ end
41
+
42
+ # Get an array of icons for the windows
43
+ def window_icons
44
+ # Load them
45
+ load_window_icons
46
+ @gtk_window_icons.freeze
47
+ # Once loaded, we only need a reader
48
+ self.class.send(:define_method, :window_icons) do
49
+ @gtk_window_icons
50
+ end
51
+ # Return the value
52
+ window_icons
53
+ end
54
+
55
+ def method_missing(meth, *args, &block)
56
+ if meth.to_s =~ /_overlayed_with_/
57
+ overlay_icon(meth, *args)
58
+ elsif meth.to_s =~ /_icon$/
59
+ build_icon(meth)
60
+ else
61
+ raise NoMethodError, "method not found: #{meth}"
62
+ end
63
+ end
64
+
65
+ def free_position
66
+ @free_overlays ||= Overlays.dup
67
+ @free_overlays.pop
68
+ end
69
+
70
+ def by_name(icon_name)
71
+ send (icon_name =~ /_icon$/) ? icon_name : "#{icon_name}_icon"
72
+ end
73
+ private
74
+
75
+ # Auto-define a method with _icon for each icon's name
76
+ def build_icon(meth)
77
+ if meth.to_s =~ /^(.*)_icon$/
78
+ name = $1
79
+ path = File.join(Config.images_path, "#{name}.png")
80
+ if File.exists? path
81
+ begin
82
+ icon = Gdk::Pixbuf.new(path)
83
+ icon.freeze
84
+ # Once loaded, we only need a reader
85
+ self.class.send(:define_method, meth) do
86
+ icon
87
+ end
88
+ return icon
89
+ rescue StandardError => e
90
+ $stderr.puts e.to_s
91
+ $stderr.puts "Problem loading #{name} icon #{path}"
92
+ raise e
93
+ end
94
+ else
95
+ raise "Icon not found: #{path}"
96
+ end
97
+ end
98
+ end
99
+
100
+ def overlay_with(original_name,overlay_name=nil,position='south')
101
+ if overlay_name.nil?
102
+ original_name
103
+ else
104
+ "#{original_name}_#{position}_overlayed_with_#{overlay_name}"
105
+ end
106
+ end
107
+
108
+ def overlay_icon(meth)
109
+ if meth.to_s =~ /^(.*)_(#{Overlays.join('|')})_overlayed_with_(.*)$/
110
+ original = $1
111
+ original_icon = by_name original
112
+ where = $2
113
+ overlay = $3
114
+ overlay_icon = by_name overlay
115
+ case where
116
+ when 'progress'
117
+ x = y = 1
118
+ when 'tr'
119
+ x = 7; y = 1
120
+ when 'scm'
121
+ x = 1; y = 7
122
+ when 'br'
123
+ x = y = 7
124
+ end
125
+ overlayed = original_icon.dup
126
+ overlayed.composite!(
127
+ overlay_icon,
128
+ x, y, # start region to render
129
+ 8, 8, # width / height
130
+ x, y, # offset
131
+ 0.5, 0.5, # scale
132
+ Gdk::Pixbuf::INTERP_BILINEAR, # interpolation
133
+ 255 # alpha
134
+ )
135
+ self.class.send(:define_method, meth) do
136
+ overlayed
137
+ end
138
+ return overlayed
139
+ end
140
+ end
141
+
142
+ # Load the icons for the windows
143
+ def load_window_icons
144
+ WINDOW_ICON_SIZES.each do |size|
145
+ file = File.join(Config.lib_path, WINDOW_ICON_FILENAME % [size])
146
+ begin
147
+ @gtk_window_icons << Gdk::Pixbuf.new(file) if File.exist? file
148
+ rescue StandardError => e
149
+ $stderr.puts e.to_s
150
+ $stderr.puts "Problem loading window icon #{file}"
151
+ end
152
+ end
153
+ end
154
+
155
+ end
156
+ end
@@ -0,0 +1,53 @@
1
+ =begin
2
+ = VimMate: Vim graphical add-on
3
+ Copyright (c) 2006 Guillaume Benny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+ =end
23
+
24
+ require 'singleton'
25
+
26
+ module VimMate
27
+
28
+ # A nicer singleton implementation. When a class mixes this module,
29
+ # it becomes a singleton and you don't have to use 'instance' to
30
+ # access the singleton's class method. For example:
31
+ # class Hello
32
+ # include VimMate::NiceSingleton
33
+ #
34
+ # def hello
35
+ # "hello"
36
+ # end
37
+ # end
38
+ #
39
+ # Hello.hello # => "hello"
40
+ #
41
+ module NiceSingleton
42
+ def self.included(other)
43
+ if other.class == Class
44
+ other.send(:include, Singleton)
45
+ class << other
46
+ def method_missing(method, *args, &block)
47
+ self.instance.send(method, *args)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,4 @@
1
+ require_dependency 'lib/INotify'
2
+ require_dependency 'lib/directory'
3
+ ListedDirectory.class_eval { include VimMate::Plugin::INotifyDirectory }
4
+
@@ -0,0 +1,208 @@
1
+ # Version 0.3.0 (2005-09-27) by James Le Cuirot <chewi@ffaura.com>
2
+ # masks updated
3
+ # syscalls instead of /dev/inotify for linux-2.6.13 (are the archs correct?)
4
+ # start/stop methods added for threading
5
+ # ignore_dir_recursively method added
6
+ # Events class removed : not necessary
7
+ # (wd <=> dir) hashed both ways : needed for ignore
8
+ # default watch mask is IN_ALL_EVENTS
9
+ # UnsupportedPlatformError class added to deal with unsupported CPUs and OSes
10
+ #
11
+ # Version 0.2.3 (2005-01-18) by oxman
12
+ # function ignore_dir : was added
13
+ #
14
+ # Version 0.2.2 (2005-01-18) by oxman
15
+ # cleaning code (big thanks to gnome at #ruby-lang)
16
+ # rename next_event in each_event (thanks kig)
17
+ #
18
+ # Version 0.2.1 (2005-01-18) by oxman
19
+ # class Events : use real mask
20
+ #
21
+ # Version 0.2.0 (2005-01-18) by oxman
22
+ # function watch_dir : only watch
23
+ # function next_event : was added
24
+ # function watch_dir_recursively : was added
25
+ #
26
+ # Version 0.1.1 (2005-01-17) by oxman
27
+ # Correct IN_ var for inotify 0.18
28
+
29
+ module INotify
30
+ require 'rbconfig'
31
+
32
+ class UnsupportedPlatformError < RuntimeError
33
+ end
34
+
35
+ case Config::CONFIG["arch"]
36
+
37
+ when /i[3-6]86-linux/
38
+ INOTIFY_INIT = 291
39
+ INOTIFY_ADD_WATCH = 292
40
+ INOTIFY_RM_WATCH = 293
41
+
42
+ when /x86_64-linux/
43
+ INOTIFY_INIT = 253
44
+ INOTIFY_ADD_WATCH = 254
45
+ INOTIFY_RM_WATCH = 255
46
+
47
+ when /powerpc(64)?-linux/
48
+ INOTIFY_INIT = 275
49
+ INOTIFY_ADD_WATCH = 276
50
+ INOTIFY_RM_WATCH = 277
51
+
52
+ when /ia64-linux/
53
+ INOTIFY_INIT = 1277
54
+ INOTIFY_ADD_WATCH = 1278
55
+ INOTIFY_RM_WATCH = 1279
56
+
57
+ when /s390-linux/
58
+ INOTIFY_INIT = 284
59
+ INOTIFY_ADD_WATCH = 285
60
+ INOTIFY_RM_WATCH = 286
61
+
62
+ when /alpha-linux/
63
+ INOTIFY_INIT = 444
64
+ INOTIFY_ADD_WATCH = 445
65
+ INOTIFY_RM_WATCH = 446
66
+
67
+ when /sparc(64)?-linux/
68
+ INOTIFY_INIT = 151
69
+ INOTIFY_ADD_WATCH = 152
70
+ INOTIFY_RM_WATCH = 156
71
+
72
+ when /arm-linux/
73
+ INOTIFY_INIT = 316
74
+ INOTIFY_ADD_WATCH = 317
75
+ INOTIFY_RM_WATCH = 318
76
+
77
+ when /sh-linux/
78
+ INOTIFY_INIT = 290
79
+ INOTIFY_ADD_WATCH = 291
80
+ INOTIFY_RM_WATCH = 292
81
+
82
+ else raise UnsupportedPlatformError, Config::CONFIG["arch"]
83
+
84
+ end
85
+
86
+ Mask = Struct::new(:value, :name)
87
+
88
+ Masks = {
89
+ :IN_ACCESS => Mask::new(0x00000001, 'access'),
90
+ :IN_MODIFY => Mask::new(0x00000002, 'modify'),
91
+ :IN_ATTRIB => Mask::new(0x00000004, 'attrib'),
92
+ :IN_CLOSE_WRITE => Mask::new(0x00000008, 'close_write'),
93
+ :IN_CLOSE_NOWRITE => Mask::new(0x00000010, 'close_nowrite'),
94
+ :IN_OPEN => Mask::new(0x00000020, 'open'),
95
+ :IN_MOVED_FROM => Mask::new(0x00000040, 'moved_from'),
96
+ :IN_MOVED_TO => Mask::new(0x00000080, 'moved_to'),
97
+ :IN_CREATE => Mask::new(0x00000100, 'create'),
98
+ :IN_DELETE => Mask::new(0x00000200, 'delete'),
99
+ :IN_DELETE_SELF => Mask::new(0x00000400, 'delete_self'),
100
+ :IN_UNMOUNT => Mask::new(0x00002000, 'unmount'),
101
+ :IN_Q_OVERFLOW => Mask::new(0x00004000, 'q_overflow'),
102
+ :IN_IGNORED => Mask::new(0x00008000, 'ignored'),
103
+ }
104
+
105
+ Masks.each {|key, value|
106
+ const_set(key, value)
107
+ }
108
+
109
+ OrMasks = {
110
+ :IN_CLOSE => Mask::new(IN_CLOSE_WRITE.value | IN_CLOSE_NOWRITE.value, 'close'),
111
+ :IN_MOVE => Mask::new(IN_MOVED_FROM.value | IN_MOVED_TO.value, 'moved'),
112
+ :IN_ALL_EVENTS => Mask::new(IN_ACCESS.value | IN_MODIFY.value | IN_ATTRIB.value | IN_CLOSE_WRITE.value | IN_CLOSE_NOWRITE.value | IN_OPEN.value | IN_MOVED_FROM.value | IN_MOVED_TO.value | IN_DELETE.value | IN_CREATE.value | IN_DELETE_SELF.value, 'all_events')
113
+ }
114
+
115
+ OrMasks.each {|key, value|
116
+ const_set(key, value)
117
+ }
118
+
119
+ AllMasks = Masks.merge OrMasks
120
+
121
+ require 'find'
122
+
123
+ class INotify
124
+ def initialize
125
+ @wd_dir = Hash.new
126
+ @dir_wd = Hash.new
127
+ @io = IO.open(syscall(INOTIFY_INIT))
128
+ end
129
+
130
+ def close
131
+ @io.close
132
+ end
133
+
134
+ def watch_dir (dir, option = IN_ALL_EVENTS)
135
+ wd = syscall(INOTIFY_ADD_WATCH, @io.fileno, dir, option.value)
136
+
137
+ if wd >= 0
138
+ @dir_wd[dir] = wd
139
+ @wd_dir[wd] = dir
140
+ end
141
+
142
+ return wd
143
+ rescue Errno::EACCES => e
144
+ STDERR.puts e.message
145
+ end
146
+
147
+ def ignore_dir (dir)
148
+ syscall(INOTIFY_RM_WATCH, @io.fileno, @dir_wd[dir])
149
+ end
150
+
151
+ def watch_dir_recursively (dir, option = IN_ALL_EVENTS)
152
+ Find.find(dir) { |sub_dir| watch_dir(sub_dir, option) if (File::directory?(sub_dir) == true) }
153
+ end
154
+
155
+ def ignore_dir_recursively (dir)
156
+ Find.find(dir) { |sub_dir| ignore_dir(sub_dir) if (File::directory?(sub_dir) == true) }
157
+ end
158
+
159
+ def next_events
160
+ begin
161
+ read_cnt = @io.read(16)
162
+ wd, mask, cookie, len = read_cnt.unpack('lLLL')
163
+ read_cnt = @io.read(len)
164
+ filename = read_cnt.unpack('Z*')
165
+ end while (mask & IN_Q_OVERFLOW.value) != 0
166
+
167
+ events = Array.new
168
+
169
+ AllMasks.each_value do |m|
170
+ next if m.value == IN_ALL_EVENTS.value
171
+ events.push Event.new(@wd_dir[wd].to_s, filename.to_s, m.name.to_s, cookie) if (m.value & mask) != 0
172
+ end
173
+
174
+ return events
175
+ end
176
+
177
+ def each_event
178
+ loop { next_events.each { |event| yield event } }
179
+ end
180
+
181
+ def start
182
+ @thread = Thread.new { loop { next_events.each { |event| yield event } } }
183
+ end
184
+
185
+ def stop
186
+ @thread.exit
187
+ end
188
+ end
189
+
190
+ class Event
191
+ attr_reader :path, :filename, :type, :cookie
192
+
193
+ def initialize (path, filename, type, cookie)
194
+ @path = path
195
+ @filename = filename
196
+ @type = type
197
+ @cookie = cookie
198
+ end
199
+
200
+ def dump
201
+ "path: " + @path.to_s + ", filename: " + @filename.to_s + ", type: " + @type.to_s + ", cookie: " + @cookie.to_s
202
+ end
203
+
204
+ def to_s
205
+ dump
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,58 @@
1
+ module VimMate
2
+ module Plugin
3
+ module INotifyDirectory
4
+ Mask = INotify::Mask.new(
5
+ INotify::IN_MODIFY.value |
6
+ INotify::IN_DELETE.value |
7
+ INotify::IN_CREATE.value |
8
+ INotify::IN_MOVED_TO.value |
9
+ INotify::IN_MOVED_FROM.value |
10
+ 0, 'filechange')
11
+
12
+ Exclusions = [ /(swp|~|rej|orig)$/, /\/\.?#/, /^\./ ]
13
+ def self.included(base)
14
+ base.class_eval do
15
+ include InstanceMethods
16
+ extend ClassMethods
17
+ alias_method_chain :initialize, :inotify
18
+ start_inotify_watcher
19
+ end
20
+
21
+ end
22
+
23
+ module InstanceMethods
24
+ def initialize_with_inotify(*args)
25
+ initialize_without_inotify(*args)
26
+ if directory?
27
+ self.class.inotify_watcher.watch_dir(full_path, Mask)
28
+ end
29
+ end
30
+ end
31
+
32
+ module ClassMethods
33
+ def inotify_watcher
34
+ @@inotify_watcher ||= INotify::INotify.new
35
+ end
36
+
37
+ def start_inotify_watcher
38
+ inotify_watcher.start do |event|
39
+ next if ignore_file_changes? event.filename
40
+ path = File.join(event.path, event.filename)
41
+ case event.type
42
+ when 'modify'
43
+ ActiveWindow::Signal.emit_file_modified(path)
44
+ when /^delete|moved_from$/
45
+ ActiveWindow::Signal.emit_file_deleted(path)
46
+ when /^create|moved_to$/
47
+ ActiveWindow::Signal.emit_file_created(path)
48
+ end
49
+ end
50
+ end
51
+
52
+ def ignore_file_changes?(filename)
53
+ Exclusions.any? { |exclusion| filename =~ exclusion }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,7 @@
1
+ #VimMate::Requirer.require_if('lib/subversion') do
2
+ # require 'lib/file'
3
+ # require 'lib/menu'
4
+ # VimMate::ListedFile.class_eval { include VimMate::Plugin::SubversionFile }
5
+ # VimMate::ListedDirectory.class_eval { include VimMate::Plugin::SubversionFile }
6
+ # VimMate::FilesMenu.class_eval { include VimMate::Plugin::SubversionMenu }
7
+ #end
@@ -0,0 +1,59 @@
1
+ # All stuff for SVN handling of files
2
+
3
+ module VimMate
4
+ module Plugin
5
+ module SubversionFile
6
+ def self.included(base)
7
+ base.class_eval do
8
+ include InstanceMethods
9
+ modify_icon :svn do |file|
10
+ Icons.overlay_with file.icon_name_without_svn, file.svn_icon, 'scm'
11
+ end
12
+ end
13
+ end
14
+ module InstanceMethods
15
+ # Refresh the file. If the file status has changed, send a refresh
16
+ # signal
17
+ def refresh
18
+ status = Subversion.status(full_path)
19
+ if @last_status != status
20
+ @last_status = status
21
+ ListedTree.refreshed self
22
+ end
23
+ self
24
+ end
25
+
26
+
27
+ # Return the icon for this file depending on the file status
28
+ def svn_icon
29
+ status = Subversion.status(full_path)
30
+ if @last_status != status
31
+ @last_status = status
32
+ end
33
+ case status
34
+ when Subversion::UNVERSIONED, Subversion::EXTERNAL,
35
+ Subversion::IGNORED, Subversion::UNKNOWN
36
+ nil
37
+ when Subversion::NONE, Subversion::NORMAL
38
+ "svn_normal"
39
+ when Subversion::ADDED, Subversion::REPLACED
40
+ 'svn_added'
41
+ when Subversion::DELETED, Subversion::MISSING
42
+ 'svn_deleted'
43
+ when Subversion::MODIFIED
44
+ 'svn_modified'
45
+ when Subversion::CONFLICTED
46
+ 'svn_conflict'
47
+ when Subversion::MERGED, Subversion::OBSTRUCTED, Subversion::INCOMPLETE
48
+ 'svn_readonly' # FIXME for now, have no better
49
+ end
50
+ end
51
+
52
+ # Return the status text for this file depending on the file status
53
+ def status
54
+ Subversion.status_text(full_path)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end