benatkin-vimilicious 0.1.5

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/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}" }