benatkin-vimilicious 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 ryan "remi" Taylor
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,26 @@
1
+ = Vimilicious
2
+
3
+ vimilicious is a gem/library that you can use on top of vim-ruby
4
+ for easier vim scripting, vim 'app' creation, or whatever you want
5
+
6
+ i love vim. i even love vim's built-in scripting ... sometimes.
7
+
8
+ vim's scripting is pretty shitty for making complex, maintainable applications
9
+ or complicated scripts, though. the perfect example is rails.vim.
10
+ as much as i love and adore rails.vim ... have you ever looked at the source? holy shit!
11
+
12
+ using ruby for some of your vim scripting or application creation can make your life much easier.
13
+ only those with vim compiled with ruby support will be able to take advantage of vimilicious or
14
+ Vimilicious based scripts/applications, but that's okay in my book.
15
+ we don't code in C just because not everyone has ruby installed, do we?
16
+
17
+ == Install
18
+
19
+ $ sudo gem install remi-vimilicious -s http://gems.github.com
20
+
21
+ == Usage
22
+
23
+ see Vimilicious RDoc or examples
24
+
25
+ documentation:: http://code.remi.org/vimilicious
26
+ example:: http://github.com/remi/vimilicious/tree/master/examples
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'rake'
2
+ require 'rubygems'
3
+ require 'rake/rdoctask'
4
+ require 'spec/rake/spectask'
5
+
6
+ Spec::Rake::SpecTask.new do |t|
7
+ t.spec_files = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ desc "Run all examples with RCov"
11
+ Spec::Rake::SpecTask.new('rcov') do |t|
12
+ t.spec_files = FileList['spec/**/*_spec.rb']
13
+ t.rcov = true
14
+ end
15
+
16
+ Rake::RDocTask.new do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'vimilicious'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README.rdoc')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+ desc 'Confirm that gemspec is $SAFE'
25
+ task :safe do
26
+ require 'yaml'
27
+ require 'rubygems/specification'
28
+ data = File.read('rackbox.gemspec')
29
+ spec = nil
30
+ if data !~ %r{!ruby/object:Gem::Specification}
31
+ Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
32
+ else
33
+ spec = YAML.load(data)
34
+ end
35
+ spec.validate
36
+ puts spec
37
+ puts "OK"
38
+ end
39
+
40
+ task :default => :spec
data/examples/vikir.rb ADDED
@@ -0,0 +1,110 @@
1
+ # vikir.rb
2
+ #
3
+ # VI Wiki In Ruby
4
+
5
+ # Usage: (assumes <Leader> is /, and all else is default)
6
+ #
7
+ # \v h goto HomePage
8
+ # \v i goto Index of all Wiki Pages
9
+ # \v r refresh highlighting (or apply to any file to see valid wiki pages)
10
+ # \v f follow word under cursor (regardless of whether or not it exists)
11
+ # \v o open word under cursor (same as follow but will open in window 2, if available)
12
+ # \v s follow in split (horizontal)
13
+ # \v v follow in split (vertical)
14
+ # \v e open explorer (vertical split with index on left)
15
+ # \v m render as markdown and preview in browser (requires 'markdown' in path to do the work)
16
+ #
17
+ # Highlights:
18
+ #
19
+ # SIMPLE
20
+ #
21
+ # \v r applies highlighting on *top* of any currently displayed highlighting
22
+ #
23
+
24
+ require 'rubygems'
25
+ require 'vimilicious'
26
+
27
+ ## -- CONSTANTS -- ##
28
+ WIKI_DIR = '~/wiki'.gsub '~', ENV['HOME']
29
+ HOME_PAGE = 'HomePage'
30
+ COMMAND_PREFIX = '<Leader>v'
31
+ HIGHLIGHT_AS = 'Identifier'
32
+ DEFAULT_FILETYPE = 'mkd'
33
+
34
+ ## -- HELPER METHODS -- ##
35
+ def page name
36
+ File.join WIKI_DIR, name
37
+ end
38
+ def in_wiki? location=current_file
39
+ location.include?WIKI_DIR if location
40
+ end
41
+ def pages
42
+ Dir[File.join(WIKI_DIR,'*')]
43
+ end
44
+
45
+ ## -- ACTION METHODS -- ##
46
+ def goto place
47
+ cmd "cd #{WIKI_DIR}"
48
+ cmd "e #{page place}"
49
+ highlight unless File.directory?page(place)
50
+ end
51
+ def index
52
+ goto ''
53
+ end
54
+ def home
55
+ goto HOME_PAGE
56
+ end
57
+ def follow place=current_word
58
+ goto place
59
+ end
60
+ def follow_in_split place=current_word, open_below=true
61
+ cmd 'sp'
62
+ exec '<C-w>' + (open_below ? 'j' : 'k')
63
+ follow place
64
+ end
65
+ def follow_in_vsplit place=current_word, open_right_of=true
66
+ cmd 'vsp'
67
+ exec '<C-w>' + (open_right_of ? 'l' : 'h')
68
+ follow place
69
+ end
70
+ def explorer
71
+ follow_in_vsplit '', false
72
+ exec '40<C-w><'
73
+ end
74
+ def open place=current_word
75
+ exec '<C-w>l' if VIM::Window.count > 1 # assume window is on right (for now)
76
+ follow place
77
+ exec '<C-w>h^' # more back to left (feels right)
78
+ end
79
+ def highlight
80
+ if File.directory?current_file # assume this is the wiki dir and simple reload it
81
+ goto ''; return
82
+ end
83
+ cmd "set ft=#{DEFAULT_FILETYPE}" unless DEFAULT_FILETYPE.empty?
84
+ pages.each do |file|
85
+ cmd "syntax match VikirPage '#{File.basename file}'"
86
+ end
87
+ end
88
+ def markdown
89
+ Thread.new { `markdown '#{current_file}'` }
90
+ end
91
+
92
+ ## -- COMMAND MAPPING -- ##
93
+ commands = {
94
+ :h => :home,
95
+ :i => :index,
96
+ :r => :highlight,
97
+ :f => :follow,
98
+ :s => :follow_in_split,
99
+ :v => :follow_in_vsplit,
100
+ :e => :explorer,
101
+ :o => :open,
102
+ :m => :markdown
103
+ }
104
+ commands.each do |command, method|
105
+ cmd %{ map #{COMMAND_PREFIX}#{command} :ruby #{method}<CR> }
106
+ end
107
+
108
+ ## -- SYNTAX HIGHLIGHTING -- ##
109
+ cmd "hi def link VikirPage #{HIGHLIGHT_AS}"
110
+ highlight if in_wiki?
@@ -0,0 +1,32 @@
1
+ " vikir.vim
2
+ """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
3
+ " Name: vikir
4
+ " Description: vi wiki in ruby
5
+ " Author: remi Taylor <remi@remitaylor.com>
6
+ " Maintainer: -- '' --
7
+ "
8
+ " Licence: This program is free software; you can redistribute it
9
+ " and/or modify it under the terms of the GNU General Public
10
+ " License. See http://www.gnu.org/copyleft/gpl.txt
11
+ "
12
+ " Credits:
13
+ "
14
+ """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
15
+
16
+ " hello angry vim hacker
17
+ "
18
+ " you wanna see lots and lots and lots and lots and lots
19
+ " of jazz here with things like <unique> <silent> <SID>
20
+ " all over the place
21
+ "
22
+ " well, sorry to disappoint you ...
23
+ "
24
+ " this and vikir.rb are all you'll find here!
25
+
26
+ if &cp || (exists("g:loaded_vikir") && g:loaded_vikir)
27
+ finish
28
+ endif
29
+
30
+ rubyf ~/.vim/plugin/vikir.rb
31
+
32
+ let g:loaded_vikir = 1
@@ -0,0 +1,330 @@
1
+ # common methods for vim-ruby scripts
2
+ module Vimilicious
3
+
4
+ # run vim command
5
+ #
6
+ # :ruby puts cmd("echo 'hello!'")
7
+ def cmd vim_ex_command
8
+ VIM::command vim_ex_command
9
+ end
10
+
11
+ # runs a system command in vim, by calling :! command
12
+ #
13
+ # :ruby run 'ls'
14
+ def run system_command
15
+ cmd "! #{ system_command }"
16
+ end
17
+
18
+ # evaluate vim expression
19
+ #
20
+ # :ruby puts 'x = ' + vim_eval('x')
21
+ def vim_eval vim_expression
22
+ VIM::evaluate vim_expression
23
+ end
24
+
25
+ # execute 'normal' command
26
+ #
27
+ # :ruby exec '<ESC>ihello there!<ESC>'
28
+ def exec normal_vim_command
29
+ cmd %[exec "normal #{normal_vim_command}"].gsub('<','\<')
30
+ end
31
+
32
+ # alias 'puts' to vim 'print' method
33
+ #
34
+ # :ruby puts 'hello!'
35
+ def puts message
36
+ print message
37
+ end
38
+
39
+ # check to see if a vim variable is defined
40
+ #
41
+ # :ruby puts 'x is defined? ' + vim_defined?'x'
42
+ def vim_defined? var
43
+ vim_eval("exists('#{var}')") == '1'
44
+ end
45
+
46
+ # get the value of a vim variable (else nil)
47
+ #
48
+ # :ruby x = vim_var('x'); puts "x = #{x}"
49
+ def vim_var var
50
+ vim_eval(var) if vim_defined?var
51
+ end
52
+
53
+ # get the current buffer
54
+ #
55
+ # :ruby puts "the current line says: #{current_buffer.line}"
56
+ def current_buffer
57
+ VIM::Buffer.current # $curbuf
58
+ end
59
+
60
+ # get the current window
61
+ #
62
+ # :ruby puts "the cursor is at: #{current_window.cursor.inspect}"
63
+ def current_window
64
+ VIM::Window.current # $curwin
65
+ end
66
+
67
+ # get the name of the current file
68
+ #
69
+ # :ruby puts "currently editing: #{current_file}"
70
+ def current_file
71
+ current_buffer.name
72
+ end
73
+
74
+ # get the current cursor location (as array [line_number,position])
75
+ #
76
+ # :ruby puts "the cursor is at: #{cursor.inspect}"
77
+ def cursor
78
+ current_window.cursor
79
+ end
80
+
81
+ # get the text of the currently selected line
82
+ #
83
+ # :ruby puts "the current line says: #{current_line}"
84
+ def current_line
85
+ current_buffer.line
86
+ end
87
+
88
+ # set the text of the currently selected line
89
+ #
90
+ # we're not using the more conventional current_line= because
91
+ # that simply creates a local variable named current_line
92
+ #
93
+ # :ruby set_current_line 'hi there'
94
+ def set_current_line text
95
+ current_buffer[ current_buffer.line_number ] = text.to_s
96
+ end
97
+
98
+ # deletes the current buffer (closes the file) but keeps the current layout
99
+ #
100
+ # :ruby clear
101
+ def clear
102
+ cmd 'let kwbd_bn= bufnr("%")|enew|exe "bdel ".kwbd_bn|unlet kwbd_bn'
103
+ clear_buffer
104
+ end
105
+
106
+ # forcefully deletes the current buffer and clears the wholelayout
107
+ #
108
+ # :ruby clear!
109
+ def clear!
110
+ cmd 'bd!'
111
+ clear_buffer
112
+ end
113
+
114
+ # deletes all lines in the current_buffer
115
+ def clear_buffer
116
+ exec 'gg'
117
+ current_buffer.length.times { current_buffer.delete(1) }
118
+ end
119
+
120
+ # append text to the end of the current_buffer
121
+ #
122
+ # :ruby append 'hello there'
123
+ def append text
124
+ current_buffer.append current_buffer.length, text
125
+ end
126
+
127
+ # prompts user for input
128
+ #
129
+ # :ruby prompt('username')
130
+ def prompt name = 'input', format = lambda { |name| "#{name}: " }
131
+ input = vim_eval("inputdialog('#{ format.call(name) }')")
132
+ puts '' # clear statusline thinger
133
+ input
134
+ end
135
+
136
+ # ruby method for mapping keyboard shortcuts to something
137
+ #
138
+ # this is a ruby wrapper around vim's map functions
139
+ #
140
+ # ==== VIM Modes
141
+ #
142
+ # map:: Normal, Visual, Operator-pending
143
+ # map!:: Insert, Command-line
144
+ # nmap:: Normal
145
+ # vmap:: Visual
146
+ # omap:: Operator-pending
147
+ # cmap:: Command-line
148
+ # imap:: Insert
149
+ # lmap:: Insert, Command-line, Lang-Arg
150
+ #
151
+ # references:
152
+ # - http://www.vim.org/htmldoc/map.html
153
+ # - http://howto.wikia.com/wiki/Howto_map_keys_in_vim
154
+ #
155
+ # === Usage
156
+ #
157
+ # map :normal, '<C-v>', do
158
+ # # some code that will run whenever
159
+ # # Control-V is pressed in Normal mode
160
+ # end
161
+ #
162
+ # map '<F5>', ":echo 'hello from F5'<Enter>"
163
+ #
164
+ # ==== Parameters
165
+ # modes::
166
+ # optional. either a single mode, eg. :normal or an Array of
167
+ # multiple modes, eg. %w( visual command ). default: 'normal'
168
+ #
169
+ # valid mode names: normal, visual, insert, command, operator, lang
170
+ #
171
+ # shortcut::
172
+ # a shortcut just like VIM normally understands, eg. <C-v>
173
+ #
174
+ # vim_command::
175
+ # optional. this is a string command that we'll map
176
+ # this shortcut to. if this is passed, the &block
177
+ # parameter is ignored and vim_command is run instead!
178
+ # you can still run ruby with this parameter by
179
+ # passing something like '<Esc>:ruby puts 'hi'<Enter>'
180
+ #
181
+ # &block::
182
+ # a block of code to run whenever the code is pressed
183
+ #
184
+ # TODO allow #map('<C-r>'){ ... } and use default mode
185
+ # TODO allow #map('<C-r>', 'vim command')
186
+ #
187
+ def map modes, shortcut = nil, vim_command = nil, &block
188
+
189
+ # first argument isn't a mode, it's a shortcut!
190
+ unless modes.is_a?(Symbol) or modes.is_a?(Array)
191
+ vim_command = shortcut
192
+ shortcut = modes
193
+ modes = :normal # default
194
+ end
195
+
196
+ modes_to_use = map_commands_for *modes
197
+ raise "Don't know how to map #{ modes.inspect }" if modes_to_use.empty?
198
+
199
+ if vim_command
200
+ modes_to_use.each do |mode|
201
+ cmd "#{ mode } #{ shortcut } #{ vim_command }"
202
+ end
203
+
204
+ elsif block
205
+ unique_key = "#{ shortcut.inspect } #{ modes.inspect } #{ Time.now }"
206
+ @mapped_blocks ||= { }
207
+ @mapped_blocks[unique_key] = block
208
+ modes_to_use.each do |mode|
209
+ cmd "#{ mode } #{ shortcut } <Esc>:ruby @mapped_blocks[%{#{ unique_key }}].call<Enter>"
210
+ end
211
+
212
+ else
213
+ raise "Not sure what you want to map to ... no vim_command or block passed."
214
+ end
215
+ end
216
+
217
+ # returns the map command(s) you should use if you want
218
+ # to map with the mode(s) given
219
+ #
220
+ # see spec/mapping_spec.rb
221
+ #
222
+ # >> map_commands_for(:normal)
223
+ # => :nmap
224
+ #
225
+ def map_commands_for *modes
226
+ @mapmodes ||= {
227
+ :map => [ :normal, :visual, :operator ],
228
+ :map! => [ :insert, :command ],
229
+ :nmap => [ :normal ],
230
+ :vmap => [ :visual ],
231
+ :omap => [ :operator ],
232
+ :cmap => [ :command ],
233
+ :imap => [ :insert ],
234
+ :lmap => [ :insert, :command, :lang ]
235
+ }
236
+
237
+ # symbolize
238
+ modes = modes.map {|mode| mode.to_s.downcase.to_sym }
239
+
240
+ # first, see if there's a mode that has the modes we want and nothing more
241
+ mode_that_has_everything_we_want_and_nothing_else = @mapmodes.find do |mode_command, available_modes|
242
+ match = true
243
+ match = false unless available_modes.length == modes.length
244
+ modes.each {|mode| match = false unless available_modes.include?(mode) }
245
+ match
246
+ end
247
+
248
+ return [ mode_that_has_everything_we_want_and_nothing_else[0] ] if mode_that_has_everything_we_want_and_nothing_else
249
+
250
+ # see if the modes we're looking for have a 1 <=> 1 mapping with available modes
251
+ one_to_one_mapping_modes = modes.map do |mode|
252
+ @mapmodes.find do |mode_command, available_modes|
253
+ available_modes == [mode]
254
+ end
255
+ end
256
+
257
+ return one_to_one_mapping_modes.map {|mode_command, available_modes|
258
+ mode_command
259
+ } unless one_to_one_mapping_modes.include? nil
260
+
261
+ # hmm, regardless of whether it'll have more than we want, see if we can find a mode
262
+ # that has all of the modes we're looking for
263
+ modes_that_have_everything_we_want_and_some_more = @mapmodes.select do |mode_command, available_modes|
264
+ match = true
265
+ modes.each {|mode| match = false unless available_modes.include?(mode) }
266
+ match
267
+ end
268
+
269
+ if modes_that_have_everything_we_want_and_some_more.length == 1
270
+ return [ modes_that_have_everything_we_want_and_some_more[0][0] ]
271
+ else
272
+ [] # couldn't find anything :/
273
+ end
274
+
275
+ end
276
+
277
+ # create a vim user command that calls a ruby method or block
278
+ #
279
+ # :ruby create_command :test # creates a :Test command that calls a 'test' method
280
+ # :ruby create_command 'test', :hi # creates a :Test command that calls a 'hi' method
281
+ # :ruby create_command(:test){ puts 'hi' } # creates a :Test command that calls the block passed in
282
+ #
283
+ # :ruby create_command(:foo){|*args| puts "called foo with args: #{ args.inspect }" }
284
+ #
285
+ # :Foo 'hello', 'there', 1, 2, 3
286
+ # called foo with args: ["hi", "there", 1, 2, 3]
287
+ #
288
+ # ==== Notes
289
+ #
290
+ # the name of the command will be capitalized, so :test is callable as :Test
291
+ #
292
+ def create_command name, method = nil, &block
293
+ name = name.to_s
294
+ command_name = name[0..0] + name[1..name.length]
295
+ method_name = (method.nil?) ? name.to_s : method.to_s
296
+ function_name = command_name + 'AutoGeneratedFunction'
297
+
298
+ # create a function that calls method (or block)
299
+ if block.nil?
300
+ cmd %[fu! #{ function_name }(...)\n ruby #{ method_name } *eval("\#{ vim_eval('string(a:000)') }")\nendfu]
301
+ else
302
+ generated_method = command_name + '_auto_generated_method'
303
+ Kernel.module_eval { define_method generated_method, block }
304
+ cmd %[fu! #{ function_name }(...)\n ruby #{ generated_method } *eval("\#{ vim_eval('string(a:000)') }")\nendfu]
305
+ end
306
+
307
+ # create a vim command that calls the vim function
308
+ cmd %{command! -nargs=* #{ command_name } call #{ function_name }(<args>)}
309
+ end
310
+
311
+ # get the word under the cursor
312
+ #
313
+ # :ruby puts "the cursor is on top of the word: #{current_word}"
314
+ def current_word filter=/[,'`\.:\(\)\[\]\}\{]/, replace_with=''
315
+ line, index = current_line, cursor[1]
316
+ word_start, word_end = line.rindex(' ',index) || 0, line.index(' ',index)
317
+ word_start += 1 if word_start > 0
318
+ word_end = line.length if word_end.nil?
319
+ word = line[word_start, word_end-word_start] || ''
320
+ word.gsub!(filter,replace_with) unless word.empty?
321
+ word
322
+ end
323
+
324
+ end
325
+
326
+ include Vimilicious
327
+
328
+ ### COMMANDS ###
329
+
330
+ create_command('InspectArgs'){ |*args| puts "passed: #{args.inspect}" }