import_js 0.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.
- checksums.yaml +7 -0
- data/lib/import_js/configuration.rb +128 -0
- data/lib/import_js/importer.rb +288 -0
- data/lib/import_js/js_module.rb +46 -0
- data/lib/import_js/vim_editor.rb +98 -0
- data/lib/import_js.rb +10 -0
- metadata +49 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 330ead6ec7804b53e85225024d9d66d001c29719
|
4
|
+
data.tar.gz: d959cff0e6e106e9035276a1ad69ecb740abbe74
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c6c7c887852626478ab3a3496082ec2733e03570fe46fb3aef9a113a7d490645d9c3485913c611c424e3b51cc33831c148598668b912cc51d78aa6a76579a70c
|
7
|
+
data.tar.gz: eee49961904abde1dbc4135263ed7c637ae8920a76060137c9ed1f679d393f33c4f620c8d6605ed297e16208d42cf2347c927a0c68e69f27f878490b28cec058
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module ImportJS
|
5
|
+
CONFIG_FILE = '.importjs.json'
|
6
|
+
|
7
|
+
DEFAULT_CONFIG = {
|
8
|
+
'aliases' => {},
|
9
|
+
'declaration_keyword' => 'var',
|
10
|
+
'excludes' => [],
|
11
|
+
'jshint_cmd' => 'jshint',
|
12
|
+
'lookup_paths' => ['.'],
|
13
|
+
}
|
14
|
+
|
15
|
+
# Class that initializes configuration from a .importjs.json file
|
16
|
+
class Configuration
|
17
|
+
def initialize
|
18
|
+
@config = DEFAULT_CONFIG.merge(load_config)
|
19
|
+
end
|
20
|
+
|
21
|
+
def refresh
|
22
|
+
return if @config_time == config_file_last_modified
|
23
|
+
@config = DEFAULT_CONFIG.merge(load_config)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Object] a configuration value
|
27
|
+
def get(key)
|
28
|
+
@config[key]
|
29
|
+
end
|
30
|
+
|
31
|
+
def resolve_alias(variable_name)
|
32
|
+
path = @config['aliases'][variable_name]
|
33
|
+
return resolve_destructured_alias(variable_name) unless path
|
34
|
+
|
35
|
+
path = path['path'] if path.is_a? Hash
|
36
|
+
ImportJS::JSModule.new(nil, path, self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def resolve_destructured_alias(variable_name)
|
40
|
+
@config['aliases'].each do |_, path|
|
41
|
+
next if path.is_a? String
|
42
|
+
if (path['destructure'] || []).include?(variable_name)
|
43
|
+
js_module = ImportJS::JSModule.new(nil, path['path'], self)
|
44
|
+
js_module.is_destructured = true
|
45
|
+
return js_module
|
46
|
+
end
|
47
|
+
end
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [Number?]
|
52
|
+
def columns
|
53
|
+
get_number('&columns')
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Number?]
|
57
|
+
def text_width
|
58
|
+
get_number('&textwidth')
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [String] shiftwidth number of spaces if expandtab is not set,
|
62
|
+
# otherwise `\t`
|
63
|
+
def tab
|
64
|
+
return "\t" unless expand_tab?
|
65
|
+
' ' * (shift_width || 2)
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Array<String>]
|
69
|
+
def package_dependencies
|
70
|
+
return [] unless File.exist?('package.json')
|
71
|
+
|
72
|
+
package = JSON.parse(File.read('package.json'))
|
73
|
+
dependencies = package['dependencies'] ?
|
74
|
+
package['dependencies'].keys : []
|
75
|
+
peer_dependencies = package['peerDependencies'] ?
|
76
|
+
package['peerDependencies'].keys : []
|
77
|
+
|
78
|
+
dependencies.concat(peer_dependencies)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# @return [Hash]
|
84
|
+
def load_config
|
85
|
+
@config_time = config_file_last_modified
|
86
|
+
File.exist?(CONFIG_FILE) ? JSON.parse(File.read(CONFIG_FILE)) : {}
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Time?]
|
90
|
+
def config_file_last_modified
|
91
|
+
File.exist?(CONFIG_FILE) ? File.mtime(CONFIG_FILE) : nil
|
92
|
+
end
|
93
|
+
|
94
|
+
# Check for the presence of a setting such as:
|
95
|
+
#
|
96
|
+
# - g:CommandTSmartCase (plug-in setting)
|
97
|
+
# - &wildignore (Vim setting)
|
98
|
+
# - +cursorcolumn (Vim setting, that works)
|
99
|
+
#
|
100
|
+
# @param str [String]
|
101
|
+
# @return [Boolean]
|
102
|
+
def exists?(str)
|
103
|
+
VIM.evaluate(%{exists("#{str}")}).to_i != 0
|
104
|
+
end
|
105
|
+
|
106
|
+
# @param name [String]
|
107
|
+
# @return [Number?]
|
108
|
+
def get_number(name)
|
109
|
+
exists?(name) ? VIM.evaluate("#{name}").to_i : nil
|
110
|
+
end
|
111
|
+
|
112
|
+
# @param name [String]
|
113
|
+
# @return [Boolean?]
|
114
|
+
def get_bool(name)
|
115
|
+
exists?(name) ? VIM.evaluate("#{name}").to_i != 0 : nil
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [Boolean?]
|
119
|
+
def expand_tab?
|
120
|
+
get_bool('&expandtab')
|
121
|
+
end
|
122
|
+
|
123
|
+
# @return [Number?]
|
124
|
+
def shift_width
|
125
|
+
get_number('&shiftwidth')
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,288 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'json'
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
module ImportJS
|
6
|
+
class Importer
|
7
|
+
def initialize(editor = ImportJS::VIMEditor.new)
|
8
|
+
@config = ImportJS::Configuration.new
|
9
|
+
@editor = editor
|
10
|
+
end
|
11
|
+
|
12
|
+
# Finds variable under the cursor to import. By default, this is bound to
|
13
|
+
# `<Leader>j`.
|
14
|
+
def import
|
15
|
+
@config.refresh
|
16
|
+
variable_name = @editor.current_word
|
17
|
+
if variable_name.empty?
|
18
|
+
message(<<-EOS.split.join(' '))
|
19
|
+
No variable to import. Place your cursor on a variable, then try
|
20
|
+
again.
|
21
|
+
EOS
|
22
|
+
return
|
23
|
+
end
|
24
|
+
current_row, current_col = @editor.cursor
|
25
|
+
|
26
|
+
old_buffer_lines = @editor.count_lines
|
27
|
+
import_one_variable variable_name
|
28
|
+
return unless lines_changed = @editor.count_lines - old_buffer_lines
|
29
|
+
@editor.cursor = [current_row + lines_changed, current_col]
|
30
|
+
end
|
31
|
+
|
32
|
+
def goto
|
33
|
+
@config.refresh
|
34
|
+
@timing = { start: Time.now }
|
35
|
+
variable_name = @editor.current_word
|
36
|
+
js_modules = find_js_modules(variable_name)
|
37
|
+
@timing[:end] = Time.now
|
38
|
+
return if js_modules.empty?
|
39
|
+
js_module = resolve_one_js_module(js_modules, variable_name)
|
40
|
+
@editor.open_file(js_module.file_path)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Finds all variables that haven't yet been imported.
|
44
|
+
def import_all
|
45
|
+
@config.refresh
|
46
|
+
unused_variables = find_unused_variables
|
47
|
+
|
48
|
+
if unused_variables.empty?
|
49
|
+
message('No variables to import')
|
50
|
+
return
|
51
|
+
end
|
52
|
+
|
53
|
+
unused_variables.each do |variable|
|
54
|
+
import_one_variable(variable)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def message(str)
|
61
|
+
str = "[import-js] #{str}"
|
62
|
+
if str.length > @config.columns - 1
|
63
|
+
str = str[0...(@config.columns - 2)] + '…'
|
64
|
+
end
|
65
|
+
|
66
|
+
@editor.message(str)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Array]
|
70
|
+
def find_unused_variables
|
71
|
+
content = "/* jshint undef: true, strict: true */\n" +
|
72
|
+
"/* eslint no-unused-vars: [2, { \"vars\": \"all\", \"args\": \"none\" }] */\n" +
|
73
|
+
@editor.current_file_content
|
74
|
+
|
75
|
+
out, _ = Open3.capture3("#{@config.get('jshint_cmd')} -", stdin_data: content)
|
76
|
+
result = []
|
77
|
+
out.split("\n").each do |line|
|
78
|
+
/.*['"]([^'"]+)['"] is not defined/.match(line) do |match_data|
|
79
|
+
result << match_data[1]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
result.uniq
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param variable_name [String]
|
86
|
+
def import_one_variable(variable_name)
|
87
|
+
@timing = { start: Time.now }
|
88
|
+
js_modules = find_js_modules(variable_name)
|
89
|
+
@timing[:end] = Time.now
|
90
|
+
if js_modules.empty?
|
91
|
+
message(<<-EOS.split.join(' '))
|
92
|
+
No js module to import for variable `#{variable_name}` #{timing}
|
93
|
+
EOS
|
94
|
+
return
|
95
|
+
end
|
96
|
+
|
97
|
+
resolved_js_module = resolve_one_js_module(js_modules, variable_name)
|
98
|
+
return unless resolved_js_module
|
99
|
+
|
100
|
+
write_imports(variable_name, resolved_js_module)
|
101
|
+
end
|
102
|
+
|
103
|
+
# @param variable_name [String]
|
104
|
+
# @param js_module [ImportJS::JSModule]
|
105
|
+
def write_imports(variable_name, js_module)
|
106
|
+
old_imports = find_current_imports
|
107
|
+
|
108
|
+
# Ensure that there is a blank line after the block of all imports
|
109
|
+
unless @editor.read_line(old_imports[:newline_count] + 1).strip.empty?
|
110
|
+
@editor.append_line(old_imports[:newline_count], '')
|
111
|
+
end
|
112
|
+
|
113
|
+
modified_imports = old_imports[:imports] # Array
|
114
|
+
|
115
|
+
# Add new import to the block of imports, wrapping at text_width
|
116
|
+
unless js_module.is_destructured && inject_destructured_variable(
|
117
|
+
variable_name, js_module, modified_imports)
|
118
|
+
modified_imports << generate_import(variable_name, js_module)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Sort the block of imports
|
122
|
+
modified_imports.sort!.uniq! do |import|
|
123
|
+
# Determine uniqueness by discarding the declaration keyword (`const`,
|
124
|
+
# `let`, or `var`) and normalizing multiple whitespace chars to single
|
125
|
+
# spaces.
|
126
|
+
import.sub(/\A(const|let|var)\s+/, '').sub(/\s\s+/s, ' ')
|
127
|
+
end
|
128
|
+
|
129
|
+
# Delete old imports, then add the modified list back in.
|
130
|
+
old_imports[:newline_count].times { @editor.delete_line(1) }
|
131
|
+
modified_imports.reverse_each do |import|
|
132
|
+
# We need to add each line individually because the Vim buffer will
|
133
|
+
# convert newline characters to `~@`.
|
134
|
+
import.split("\n").reverse_each { |line| @editor.append_line(0, line) }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def inject_destructured_variable(variable_name, js_module, imports)
|
139
|
+
imports.each do |import|
|
140
|
+
match = import.match(%r{((const|let|var) \{ )(.*)( \} = require\('#{js_module.import_path}'\);)})
|
141
|
+
next unless match
|
142
|
+
|
143
|
+
variables = match[3].split(/,\s*/).concat([variable_name]).uniq.sort
|
144
|
+
import.sub!(/.*/, "#{match[1]}#{variables.join(', ')}#{match[4]}")
|
145
|
+
return true
|
146
|
+
end
|
147
|
+
false
|
148
|
+
end
|
149
|
+
|
150
|
+
# @return [Hash]
|
151
|
+
def find_current_imports
|
152
|
+
potential_import_lines = []
|
153
|
+
@editor.count_lines.times do |n|
|
154
|
+
line = @editor.read_line(n + 1)
|
155
|
+
break if line.strip.empty?
|
156
|
+
potential_import_lines << line
|
157
|
+
end
|
158
|
+
|
159
|
+
# We need to put the potential imports back into a blob in order to scan
|
160
|
+
# for multiline imports
|
161
|
+
potential_imports_blob = potential_import_lines.join("\n")
|
162
|
+
|
163
|
+
imports = []
|
164
|
+
|
165
|
+
# Scan potential imports for everything ending in a semicolon, then
|
166
|
+
# iterate through those and stop at anything that's not an import.
|
167
|
+
potential_imports_blob.scan(/^.*?;/m).each do |potential_import|
|
168
|
+
break unless potential_import.match(
|
169
|
+
/(?:const|let|var)\s+.+=\s+require\(.*\).*;/)
|
170
|
+
imports << potential_import
|
171
|
+
end
|
172
|
+
|
173
|
+
newline_count = imports.length + imports.reduce(0) do |sum, import|
|
174
|
+
sum + import.scan(/\n/).length
|
175
|
+
end
|
176
|
+
{
|
177
|
+
imports: imports,
|
178
|
+
newline_count: newline_count
|
179
|
+
}
|
180
|
+
end
|
181
|
+
|
182
|
+
# @param variable_name [String]
|
183
|
+
# @param js_module [ImportJS::JSModule]
|
184
|
+
# @return [String] the import string to be added to the imports block
|
185
|
+
def generate_import(variable_name, js_module)
|
186
|
+
declaration_keyword = @config.get('declaration_keyword')
|
187
|
+
if js_module.is_destructured
|
188
|
+
declaration = "#{declaration_keyword} { #{variable_name} } ="
|
189
|
+
else
|
190
|
+
declaration = "#{declaration_keyword} #{variable_name} ="
|
191
|
+
end
|
192
|
+
value = "require('#{js_module.import_path}');"
|
193
|
+
|
194
|
+
if @config.text_width && "#{declaration} #{value}".length > @config.text_width
|
195
|
+
"#{declaration}\n#{@config.tab}#{value}"
|
196
|
+
else
|
197
|
+
"#{declaration} #{value}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# @param variable_name [String]
|
202
|
+
# @return [Array]
|
203
|
+
def find_js_modules(variable_name)
|
204
|
+
if alias_module = @config.resolve_alias(variable_name)
|
205
|
+
return [alias_module]
|
206
|
+
end
|
207
|
+
|
208
|
+
egrep_command =
|
209
|
+
"egrep -i \"(/|^)#{formatted_to_regex(variable_name)}(/index)?(/package)?\.js.*\""
|
210
|
+
matched_modules = []
|
211
|
+
@config.get('lookup_paths').each do |lookup_path|
|
212
|
+
find_command = "find #{lookup_path} -name \"**.js*\""
|
213
|
+
out, _ = Open3.capture3("#{find_command} | #{egrep_command}")
|
214
|
+
matched_modules.concat(
|
215
|
+
out.split("\n").map do |f|
|
216
|
+
next if @config.get('excludes').any? do |glob_pattern|
|
217
|
+
File.fnmatch(glob_pattern, f)
|
218
|
+
end
|
219
|
+
js_module = ImportJS::JSModule.new(lookup_path, f, @config)
|
220
|
+
next if js_module.skip
|
221
|
+
js_module
|
222
|
+
end.compact
|
223
|
+
)
|
224
|
+
end
|
225
|
+
|
226
|
+
# Find imports from package.json
|
227
|
+
@config.package_dependencies.each do |dep|
|
228
|
+
next unless dep =~ /^#{formatted_to_regex(variable_name)}$/
|
229
|
+
js_module = ImportJS::JSModule.new(
|
230
|
+
'node_modules', "node_modules/#{dep}/package.json", @config)
|
231
|
+
next if js_module.skip
|
232
|
+
matched_modules << js_module
|
233
|
+
end
|
234
|
+
|
235
|
+
# If you have overlapping lookup paths, you might end up seeing the same
|
236
|
+
# module to import twice. In order to dedupe these, we remove the module
|
237
|
+
# with the longest path
|
238
|
+
matched_modules.sort do |a, b|
|
239
|
+
a.import_path.length <=> b.import_path.length
|
240
|
+
end.uniq do |m|
|
241
|
+
m.lookup_path + '/' + m.import_path
|
242
|
+
end.sort do |a, b|
|
243
|
+
a.display_name <=> b.display_name
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# @param js_modules [Array]
|
248
|
+
# @param variable_name [String]
|
249
|
+
# @return [String]
|
250
|
+
def resolve_one_js_module(js_modules, variable_name)
|
251
|
+
if js_modules.length == 1
|
252
|
+
message("Imported `#{js_modules.first.display_name}` #{timing}")
|
253
|
+
return js_modules.first
|
254
|
+
end
|
255
|
+
|
256
|
+
selected_index = @editor.ask_for_selection(
|
257
|
+
"\"[import-js] Pick js module to import for '#{variable_name}': #{timing}\"",
|
258
|
+
js_modules.map {|m| m.display_name}
|
259
|
+
)
|
260
|
+
return unless selected_index
|
261
|
+
js_modules[selected_index]
|
262
|
+
end
|
263
|
+
|
264
|
+
# Takes a string in any of the following four formats:
|
265
|
+
# dash-separated
|
266
|
+
# snake_case
|
267
|
+
# camelCase
|
268
|
+
# PascalCase
|
269
|
+
# and turns it into a star-separated lower case format, like so:
|
270
|
+
# star*separated
|
271
|
+
#
|
272
|
+
# @param string [String]
|
273
|
+
# @return [String]
|
274
|
+
def formatted_to_regex(string)
|
275
|
+
# Based on
|
276
|
+
# http://stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby
|
277
|
+
string.
|
278
|
+
gsub(/([a-z\d])([A-Z])/, '\1.?\2'). # separates camelCase words with '.?'
|
279
|
+
tr('-_', '.'). # replaces underscores or dashes with '.'
|
280
|
+
downcase # converts all upper to lower case
|
281
|
+
end
|
282
|
+
|
283
|
+
# @return [String]
|
284
|
+
def timing
|
285
|
+
"(#{(@timing[:end] - @timing[:start]).round(2)}s)"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ImportJS
|
2
|
+
# Class that represents a js module found in the file system
|
3
|
+
class JSModule
|
4
|
+
attr_reader :import_path
|
5
|
+
attr_reader :lookup_path
|
6
|
+
attr_reader :file_path
|
7
|
+
attr_reader :main_file
|
8
|
+
attr_reader :skip
|
9
|
+
attr_accessor :is_destructured
|
10
|
+
|
11
|
+
# @param lookup_path [String] the lookup path in which this module was found
|
12
|
+
# @param relative_file_path [String] a full path to the file, relative to
|
13
|
+
# the project root.
|
14
|
+
# @param configuration [ImportJS::Configuration]
|
15
|
+
def initialize(lookup_path, relative_file_path, configuration)
|
16
|
+
@lookup_path = lookup_path
|
17
|
+
@file_path = relative_file_path
|
18
|
+
if relative_file_path.end_with? '/package.json'
|
19
|
+
@main_file = JSON.parse(File.read(relative_file_path))['main']
|
20
|
+
match = relative_file_path.match(/(.*)\/package\.json/)
|
21
|
+
@import_path = match[1]
|
22
|
+
@skip = !@main_file
|
23
|
+
elsif relative_file_path.match(/\/index\.js.*$/)
|
24
|
+
match = relative_file_path.match(/(.*)\/(index\.js.*)/)
|
25
|
+
@main_file = match[2]
|
26
|
+
@import_path = match[1]
|
27
|
+
else
|
28
|
+
@import_path = relative_file_path
|
29
|
+
unless configuration.get('keep_file_extensions')
|
30
|
+
@import_path = @import_path.sub(/\.js.*$/, '')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if lookup_path
|
35
|
+
@import_path = @import_path.sub("#{@lookup_path}\/", '') # remove path prefix
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [String] a readable description of the module
|
40
|
+
def display_name
|
41
|
+
parts = [import_path]
|
42
|
+
parts << " (main: #{@main_file})" if @main_file
|
43
|
+
parts.join('')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module ImportJS
|
2
|
+
# This is the implementation of the VIM integration in Import-JS. It can be
|
3
|
+
# used as a template for other editor integrations.
|
4
|
+
class VIMEditor
|
5
|
+
# Get the word currently under the cursor.
|
6
|
+
#
|
7
|
+
# @return [String]
|
8
|
+
def current_word
|
9
|
+
VIM.evaluate("expand('<cword>')")
|
10
|
+
end
|
11
|
+
|
12
|
+
# Open a file specified by a path.
|
13
|
+
#
|
14
|
+
# @param file_path [String]
|
15
|
+
def open_file(file_path)
|
16
|
+
VIM.command("e #{file_path}")
|
17
|
+
end
|
18
|
+
|
19
|
+
# Display a message to the user.
|
20
|
+
#
|
21
|
+
# @param str [String]
|
22
|
+
def message(str)
|
23
|
+
VIM.command(":call importjs#WideMsg('#{str}')")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Read the entire file into a string.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
def current_file_content
|
30
|
+
VIM.evaluate('join(getline(1, "$"), "\n")')
|
31
|
+
end
|
32
|
+
|
33
|
+
# Reads a line from the file.
|
34
|
+
#
|
35
|
+
# Lines are one-indexed, so 1 means the first line in the file.
|
36
|
+
# @return [String]
|
37
|
+
def read_line(line_number)
|
38
|
+
VIM::Buffer.current[line_number]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Get the cursor position.
|
42
|
+
#
|
43
|
+
# @return [Array(Number, Number)]
|
44
|
+
def cursor
|
45
|
+
VIM::Window.current.cursor
|
46
|
+
end
|
47
|
+
|
48
|
+
# Place the cursor at a specified position.
|
49
|
+
#
|
50
|
+
# @param position_tuple [Array(Number, Number)] the row and column to place
|
51
|
+
# the cursor at.
|
52
|
+
def cursor=(position_tuple)
|
53
|
+
VIM::Window.current.cursor = position_tuple
|
54
|
+
end
|
55
|
+
|
56
|
+
# Delete a line.
|
57
|
+
#
|
58
|
+
# @param line_number [Number] One-indexed line number.
|
59
|
+
# 1 is the first line in the file.
|
60
|
+
def delete_line(line_number)
|
61
|
+
VIM::Buffer.current.delete(line_number)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Append a line right after the specified line.
|
65
|
+
#
|
66
|
+
# Lines are one-indexed, but you need to support appending to line 0 (add
|
67
|
+
# content at top of file).
|
68
|
+
# @param line_number [Number]
|
69
|
+
def append_line(line_number, str)
|
70
|
+
VIM::Buffer.current.append(line_number, str)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Count the number of lines in the file.
|
74
|
+
#
|
75
|
+
# @return [Number] the number of lines in the file
|
76
|
+
def count_lines
|
77
|
+
VIM::Buffer.current.count
|
78
|
+
end
|
79
|
+
|
80
|
+
# Ask the user to select something from a list of alternatives.
|
81
|
+
#
|
82
|
+
# @param heading [String] A heading text
|
83
|
+
# @param alternatives [Array<String>] A list of alternatives
|
84
|
+
# @return [Number, nil] the index of the selected alternative, or nil if
|
85
|
+
# nothing was selected.
|
86
|
+
def ask_for_selection(heading, alternatives)
|
87
|
+
escaped_list = [heading]
|
88
|
+
escaped_list << alternatives.each_with_index.map do |alternative, i|
|
89
|
+
"\"#{i + 1}: #{alternative}\""
|
90
|
+
end
|
91
|
+
escaped_list_string = '[' + escaped_list.join(',') + ']'
|
92
|
+
|
93
|
+
selected_index = VIM.evaluate("inputlist(#{escaped_list_string})")
|
94
|
+
return if selected_index < 1
|
95
|
+
selected_index - 1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/import_js.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Namespace declaration
|
2
|
+
module ImportJS
|
3
|
+
# We initialize an empty "ImportJS" namespace here so that we can define
|
4
|
+
# classes under that namespace, e.g. `ImportJS::Importer`.
|
5
|
+
end
|
6
|
+
|
7
|
+
require_relative 'import_js/js_module'
|
8
|
+
require_relative 'import_js/importer'
|
9
|
+
require_relative 'import_js/vim_editor'
|
10
|
+
require_relative 'import_js/configuration'
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: import_js
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Henric Trotzig
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A tool to simplify importing javascript modules
|
14
|
+
email: henric.trotzig@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/import_js.rb
|
20
|
+
- lib/import_js/configuration.rb
|
21
|
+
- lib/import_js/importer.rb
|
22
|
+
- lib/import_js/js_module.rb
|
23
|
+
- lib/import_js/vim_editor.rb
|
24
|
+
homepage: http://rubygems.org/gems/import_js
|
25
|
+
licenses:
|
26
|
+
- MIT
|
27
|
+
metadata: {}
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubyforge_project:
|
44
|
+
rubygems_version: 2.4.5.1
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: Import-JS
|
48
|
+
test_files: []
|
49
|
+
has_rdoc:
|