vimilicious 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/vimilicious.rb +340 -0
- metadata +62 -0
data/lib/vimilicious.rb
ADDED
@@ -0,0 +1,340 @@
|
|
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 current line number (of the #current_buffer)
|
82
|
+
def line_number
|
83
|
+
cursor.first
|
84
|
+
end
|
85
|
+
|
86
|
+
# get the text of the given #line_number (of the #current_buffer)
|
87
|
+
def line_text the_line_number = line_number
|
88
|
+
current_buffer[the_line_number]
|
89
|
+
end
|
90
|
+
|
91
|
+
# get the text of the currently selected line
|
92
|
+
#
|
93
|
+
# :ruby puts "the current line says: #{current_line}"
|
94
|
+
def current_line
|
95
|
+
current_buffer.line
|
96
|
+
end
|
97
|
+
|
98
|
+
# set the text of the currently selected line
|
99
|
+
#
|
100
|
+
# we're not using the more conventional current_line= because
|
101
|
+
# that simply creates a local variable named current_line
|
102
|
+
#
|
103
|
+
# :ruby set_current_line 'hi there'
|
104
|
+
def set_current_line text
|
105
|
+
current_buffer[ current_buffer.line_number ] = text.to_s
|
106
|
+
end
|
107
|
+
|
108
|
+
# deletes the current buffer (closes the file) but keeps the current layout
|
109
|
+
#
|
110
|
+
# :ruby clear
|
111
|
+
def clear
|
112
|
+
cmd 'let kwbd_bn= bufnr("%")|enew|exe "bdel ".kwbd_bn|unlet kwbd_bn'
|
113
|
+
clear_buffer
|
114
|
+
end
|
115
|
+
|
116
|
+
# forcefully deletes the current buffer and clears the wholelayout
|
117
|
+
#
|
118
|
+
# :ruby clear!
|
119
|
+
def clear!
|
120
|
+
cmd 'bd!'
|
121
|
+
clear_buffer
|
122
|
+
end
|
123
|
+
|
124
|
+
# deletes all lines in the current_buffer
|
125
|
+
def clear_buffer
|
126
|
+
exec 'gg'
|
127
|
+
current_buffer.length.times { current_buffer.delete(1) }
|
128
|
+
end
|
129
|
+
|
130
|
+
# append text to the end of the current_buffer
|
131
|
+
#
|
132
|
+
# :ruby append 'hello there'
|
133
|
+
def append text
|
134
|
+
current_buffer.append current_buffer.length, text
|
135
|
+
end
|
136
|
+
|
137
|
+
# prompts user for input
|
138
|
+
#
|
139
|
+
# :ruby prompt('username')
|
140
|
+
def prompt name = 'input', format = lambda { |name| "#{name}: " }
|
141
|
+
input = vim_eval("inputdialog('#{ format.call(name) }')")
|
142
|
+
puts '' # clear statusline thinger
|
143
|
+
input
|
144
|
+
end
|
145
|
+
|
146
|
+
# ruby method for mapping keyboard shortcuts to something
|
147
|
+
#
|
148
|
+
# this is a ruby wrapper around vim's map functions
|
149
|
+
#
|
150
|
+
# ==== VIM Modes
|
151
|
+
#
|
152
|
+
# map:: Normal, Visual, Operator-pending
|
153
|
+
# map!:: Insert, Command-line
|
154
|
+
# nmap:: Normal
|
155
|
+
# vmap:: Visual
|
156
|
+
# omap:: Operator-pending
|
157
|
+
# cmap:: Command-line
|
158
|
+
# imap:: Insert
|
159
|
+
# lmap:: Insert, Command-line, Lang-Arg
|
160
|
+
#
|
161
|
+
# references:
|
162
|
+
# - http://www.vim.org/htmldoc/map.html
|
163
|
+
# - http://howto.wikia.com/wiki/Howto_map_keys_in_vim
|
164
|
+
#
|
165
|
+
# === Usage
|
166
|
+
#
|
167
|
+
# map :normal, '<C-v>', do
|
168
|
+
# # some code that will run whenever
|
169
|
+
# # Control-V is pressed in Normal mode
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# map '<F5>', ":echo 'hello from F5'<Enter>"
|
173
|
+
#
|
174
|
+
# ==== Parameters
|
175
|
+
# modes::
|
176
|
+
# optional. either a single mode, eg. :normal or an Array of
|
177
|
+
# multiple modes, eg. %w( visual command ). default: 'normal'
|
178
|
+
#
|
179
|
+
# valid mode names: normal, visual, insert, command, operator, lang
|
180
|
+
#
|
181
|
+
# shortcut::
|
182
|
+
# a shortcut just like VIM normally understands, eg. <C-v>
|
183
|
+
#
|
184
|
+
# vim_command::
|
185
|
+
# optional. this is a string command that we'll map
|
186
|
+
# this shortcut to. if this is passed, the &block
|
187
|
+
# parameter is ignored and vim_command is run instead!
|
188
|
+
# you can still run ruby with this parameter by
|
189
|
+
# passing something like '<Esc>:ruby puts 'hi'<Enter>'
|
190
|
+
#
|
191
|
+
# &block::
|
192
|
+
# a block of code to run whenever the code is pressed
|
193
|
+
#
|
194
|
+
# TODO allow #map('<C-r>'){ ... } and use default mode
|
195
|
+
# TODO allow #map('<C-r>', 'vim command')
|
196
|
+
#
|
197
|
+
def map modes, shortcut = nil, vim_command = nil, &block
|
198
|
+
|
199
|
+
# first argument isn't a mode, it's a shortcut!
|
200
|
+
unless modes.is_a?(Symbol) or modes.is_a?(Array)
|
201
|
+
vim_command = shortcut
|
202
|
+
shortcut = modes
|
203
|
+
modes = :normal # default
|
204
|
+
end
|
205
|
+
|
206
|
+
modes_to_use = map_commands_for *modes
|
207
|
+
raise "Don't know how to map #{ modes.inspect }" if modes_to_use.empty?
|
208
|
+
|
209
|
+
if vim_command
|
210
|
+
modes_to_use.each do |mode|
|
211
|
+
cmd "#{ mode } #{ shortcut } #{ vim_command }"
|
212
|
+
end
|
213
|
+
|
214
|
+
elsif block
|
215
|
+
unique_key = "#{ shortcut.inspect }_#{ modes.inspect }_#{ Time.now.to_i }"
|
216
|
+
@mapped_blocks ||= { }
|
217
|
+
@mapped_blocks[unique_key] = block
|
218
|
+
modes_to_use.each do |mode|
|
219
|
+
cmd "#{ mode } #{ shortcut } <Esc>:ruby @mapped_blocks[#{ unique_key.inspect }].call<Enter>"
|
220
|
+
end
|
221
|
+
|
222
|
+
else
|
223
|
+
raise "Not sure what you want to map to ... no vim_command or block passed."
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# returns the map command(s) you should use if you want
|
228
|
+
# to map with the mode(s) given
|
229
|
+
#
|
230
|
+
# see spec/mapping_spec.rb
|
231
|
+
#
|
232
|
+
# >> map_commands_for(:normal)
|
233
|
+
# => :nmap
|
234
|
+
#
|
235
|
+
def map_commands_for *modes
|
236
|
+
@mapmodes ||= {
|
237
|
+
:map => [ :normal, :visual, :operator ],
|
238
|
+
:map! => [ :insert, :command ],
|
239
|
+
:nmap => [ :normal ],
|
240
|
+
:vmap => [ :visual ],
|
241
|
+
:omap => [ :operator ],
|
242
|
+
:cmap => [ :command ],
|
243
|
+
:imap => [ :insert ],
|
244
|
+
:lmap => [ :insert, :command, :lang ]
|
245
|
+
}
|
246
|
+
|
247
|
+
# symbolize
|
248
|
+
modes = modes.map {|mode| mode.to_s.downcase.to_sym }
|
249
|
+
|
250
|
+
# first, see if there's a mode that has the modes we want and nothing more
|
251
|
+
mode_that_has_everything_we_want_and_nothing_else = @mapmodes.find do |mode_command, available_modes|
|
252
|
+
match = true
|
253
|
+
match = false unless available_modes.length == modes.length
|
254
|
+
modes.each {|mode| match = false unless available_modes.include?(mode) }
|
255
|
+
match
|
256
|
+
end
|
257
|
+
|
258
|
+
return [ mode_that_has_everything_we_want_and_nothing_else[0] ] if mode_that_has_everything_we_want_and_nothing_else
|
259
|
+
|
260
|
+
# see if the modes we're looking for have a 1 <=> 1 mapping with available modes
|
261
|
+
one_to_one_mapping_modes = modes.map do |mode|
|
262
|
+
@mapmodes.find do |mode_command, available_modes|
|
263
|
+
available_modes == [mode]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
return one_to_one_mapping_modes.map {|mode_command, available_modes|
|
268
|
+
mode_command
|
269
|
+
} unless one_to_one_mapping_modes.include? nil
|
270
|
+
|
271
|
+
# hmm, regardless of whether it'll have more than we want, see if we can find a mode
|
272
|
+
# that has all of the modes we're looking for
|
273
|
+
modes_that_have_everything_we_want_and_some_more = @mapmodes.select do |mode_command, available_modes|
|
274
|
+
match = true
|
275
|
+
modes.each {|mode| match = false unless available_modes.include?(mode) }
|
276
|
+
match
|
277
|
+
end
|
278
|
+
|
279
|
+
if modes_that_have_everything_we_want_and_some_more.length == 1
|
280
|
+
return [ modes_that_have_everything_we_want_and_some_more[0][0] ]
|
281
|
+
else
|
282
|
+
[] # couldn't find anything :/
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
# create a vim user command that calls a ruby method or block
|
288
|
+
#
|
289
|
+
# :ruby create_command :test # creates a :Test command that calls a 'test' method
|
290
|
+
# :ruby create_command 'test', :hi # creates a :Test command that calls a 'hi' method
|
291
|
+
# :ruby create_command(:test){ puts 'hi' } # creates a :Test command that calls the block passed in
|
292
|
+
#
|
293
|
+
# :ruby create_command(:foo){|*args| puts "called foo with args: #{ args.inspect }" }
|
294
|
+
#
|
295
|
+
# :Foo 'hello', 'there', 1, 2, 3
|
296
|
+
# called foo with args: ["hi", "there", 1, 2, 3]
|
297
|
+
#
|
298
|
+
# ==== Notes
|
299
|
+
#
|
300
|
+
# the name of the command will be capitalized, so :test is callable as :Test
|
301
|
+
#
|
302
|
+
def create_command name, method = nil, &block
|
303
|
+
name = name.to_s
|
304
|
+
command_name = name[0..0] + name[1..name.length]
|
305
|
+
method_name = (method.nil?) ? name.to_s : method.to_s
|
306
|
+
function_name = command_name + 'AutoGeneratedFunction'
|
307
|
+
|
308
|
+
# create a function that calls method (or block)
|
309
|
+
if block.nil?
|
310
|
+
cmd %[fu! #{ function_name }(...)\n ruby #{ method_name } *eval("\#{ vim_eval('string(a:000)') }")\nendfu]
|
311
|
+
else
|
312
|
+
generated_method = command_name + '_auto_generated_method'
|
313
|
+
Kernel.module_eval { define_method generated_method, block }
|
314
|
+
cmd %[fu! #{ function_name }(...)\n ruby #{ generated_method } *eval("\#{ vim_eval('string(a:000)') }")\nendfu]
|
315
|
+
end
|
316
|
+
|
317
|
+
# create a vim command that calls the vim function
|
318
|
+
cmd %{command! -nargs=* #{ command_name } call #{ function_name }(<args>)}
|
319
|
+
end
|
320
|
+
|
321
|
+
# get the word under the cursor
|
322
|
+
#
|
323
|
+
# :ruby puts "the cursor is on top of the word: #{current_word}"
|
324
|
+
def current_word filter=/[,'`\.:\(\)\[\]\}\{]/, replace_with=''
|
325
|
+
line, index = current_line, cursor[1]
|
326
|
+
word_start, word_end = line.rindex(' ',index) || 0, line.index(' ',index)
|
327
|
+
word_start += 1 if word_start > 0
|
328
|
+
word_end = line.length if word_end.nil?
|
329
|
+
word = line[word_start, word_end-word_start] || ''
|
330
|
+
word.gsub!(filter,replace_with) unless word.empty?
|
331
|
+
word
|
332
|
+
end
|
333
|
+
|
334
|
+
end
|
335
|
+
|
336
|
+
include Vimilicious
|
337
|
+
|
338
|
+
### COMMANDS ###
|
339
|
+
|
340
|
+
create_command('InspectArgs'){ |*args| puts "passed: #{args.inspect}" }
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vimilicious
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 5
|
9
|
+
version: 0.1.5
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- remi
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-22 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: vim-ruby library making it easier to work with vim via ruby
|
22
|
+
email: remi@remitaylor.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/vimilicious.rb
|
31
|
+
has_rdoc: true
|
32
|
+
homepage: http://github.com/remi/vimilicious
|
33
|
+
licenses: []
|
34
|
+
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.3.6
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: vim-ruby library for making vim easy
|
61
|
+
test_files: []
|
62
|
+
|