xiki 0.5.0a
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/Gemfile +11 -0
- data/LICENSE +22 -0
- data/README.markdown +83 -0
- data/Rakefile +8 -0
- data/bin/xiki +46 -0
- data/etc/command/xiki_command.rb +203 -0
- data/etc/command/xiki_process.rb +52 -0
- data/etc/command/xiki_wrapper +2 -0
- data/etc/js/menu1.js +55 -0
- data/etc/js/xiki.js +259 -0
- data/etc/logo.png +0 -0
- data/etc/presentations/bootstrap.deck +5 -0
- data/etc/presentations/databases.deck +41 -0
- data/etc/presentations/diffs.deck +23 -0
- data/etc/presentations/documentation.deck +14 -0
- data/etc/presentations/effects.deck +5 -0
- data/etc/presentations/face.deck +297 -0
- data/etc/presentations/files.deck +79 -0
- data/etc/presentations/icons.deck +22 -0
- data/etc/presentations/images.deck +24 -0
- data/etc/presentations/key_shortcuts.deck +16 -0
- data/etc/presentations/macros.deck +18 -0
- data/etc/presentations/menu_classes.deck +44 -0
- data/etc/presentations/menu_directories.deck +30 -0
- data/etc/presentations/notes.deck +19 -0
- data/etc/presentations/other_languages.deck +55 -0
- data/etc/presentations/other_wiki_syntaxes.deck +4 -0
- data/etc/presentations/piano.deck +5 -0
- data/etc/presentations/potential/diffs.deck +38 -0
- data/etc/presentations/potential/evolution.deck +18 -0
- data/etc/presentations/potential/intro.deck +711 -0
- data/etc/presentations/potential/intro1.deck +711 -0
- data/etc/presentations/potential/intro2.deck +97 -0
- data/etc/presentations/potential/make_mysql_menu.deck +36 -0
- data/etc/presentations/potential/ruby_development.deck +17 -0
- data/etc/presentations/potential/ui_prototyping.deck +50 -0
- data/etc/presentations/potential/web_dev.deck +4 -0
- data/etc/presentations/potential/web_development.deck +10 -0
- data/etc/presentations/potential/wiki.deck +45 -0
- data/etc/presentations/presentations.deck +24 -0
- data/etc/presentations/rails_development.deck +29 -0
- data/etc/presentations/search_key_shortcuts.deck +37 -0
- data/etc/presentations/simplest_possible_ui.deck +37 -0
- data/etc/presentations/svg.deck +5 -0
- data/etc/presentations/testing.deck +28 -0
- data/etc/presentations/the_end.deck +13 -0
- data/etc/presentations/type_something_and_double_click.deck +57 -0
- data/etc/presentations/type_the_acronym.deck +144 -0
- data/etc/presentations/web_browser.deck +56 -0
- data/etc/presentations/xiki_command.deck +20 -0
- data/etc/presentations/xiki_url.deck +14 -0
- data/etc/shark.icns +0 -0
- data/etc/shark_script.icns +0 -0
- data/etc/snippets/html.notes +7 -0
- data/etc/snippets/notes.notes +20 -0
- data/etc/snippets/rb.notes +38 -0
- data/etc/templates/menu_template.menu +2 -0
- data/etc/templates/menu_template.rb +8 -0
- data/etc/templates/template.rb +5 -0
- data/etc/themes/Dark_Metal.notes +28 -0
- data/etc/themes/Orange_Path.notes +15 -0
- data/etc/themes/Shiny_Blue.notes +27 -0
- data/etc/themes/Shiny_Green.notes +27 -0
- data/etc/wrappers/wrapper.js +17 -0
- data/etc/wrappers/wrapper.py +20 -0
- data/etc/wrappers/wrapper.rb +25 -0
- data/lib/block.rb +72 -0
- data/lib/bookmarks.rb +352 -0
- data/lib/buffers.rb +170 -0
- data/lib/clipboard.rb +333 -0
- data/lib/code.rb +860 -0
- data/lib/code_tree.rb +476 -0
- data/lib/color.rb +274 -0
- data/lib/console.rb +557 -0
- data/lib/control_lock.rb +9 -0
- data/lib/control_tab.rb +176 -0
- data/lib/core_ext.rb +31 -0
- data/lib/cursor.rb +111 -0
- data/lib/deletes.rb +65 -0
- data/lib/diff_log.rb +297 -0
- data/lib/effects.rb +145 -0
- data/lib/environment.rb +5 -0
- data/lib/file_tree.rb +1875 -0
- data/lib/files.rb +334 -0
- data/lib/hide.rb +259 -0
- data/lib/history.rb +286 -0
- data/lib/image.rb +51 -0
- data/lib/incrementer.rb +15 -0
- data/lib/insert.rb +7 -0
- data/lib/irc.rb +22 -0
- data/lib/key_bindings.rb +658 -0
- data/lib/keys.rb +754 -0
- data/lib/launcher.rb +1351 -0
- data/lib/line.rb +429 -0
- data/lib/links.rb +6 -0
- data/lib/location.rb +175 -0
- data/lib/macros.rb +48 -0
- data/lib/man.rb +19 -0
- data/lib/menu.rb +708 -0
- data/lib/merb.rb +259 -0
- data/lib/message.rb +5 -0
- data/lib/meths.rb +56 -0
- data/lib/mode.rb +34 -0
- data/lib/move.rb +248 -0
- data/lib/notes.rb +1000 -0
- data/lib/numbers.rb +45 -0
- data/lib/ol.rb +203 -0
- data/lib/ol_helper.rb +44 -0
- data/lib/overlay.rb +167 -0
- data/lib/pause_means_space.rb +68 -0
- data/lib/php.rb +22 -0
- data/lib/projects.rb +21 -0
- data/lib/relinquish_exception.rb +2 -0
- data/lib/remote.rb +206 -0
- data/lib/requirer.rb +46 -0
- data/lib/rest_tree.rb +108 -0
- data/lib/ruby.rb +57 -0
- data/lib/ruby_console.rb +165 -0
- data/lib/search.rb +1572 -0
- data/lib/search_term.rb +40 -0
- data/lib/snippet.rb +68 -0
- data/lib/specs.rb +229 -0
- data/lib/styles.rb +274 -0
- data/lib/svn.rb +682 -0
- data/lib/text_util.rb +110 -0
- data/lib/tree.rb +1871 -0
- data/lib/tree_cursor.rb +87 -0
- data/lib/trouble_shooting.rb +27 -0
- data/lib/url_tree.rb +11 -0
- data/lib/view.rb +1474 -0
- data/lib/window.rb +133 -0
- data/lib/xiki.rb +404 -0
- data/menus/accounts.rb +5 -0
- data/menus/address_book.rb +21 -0
- data/menus/agenda.rb +28 -0
- data/menus/all.rb +5 -0
- data/menus/amazon.rb +16 -0
- data/menus/app.rb +16 -0
- data/menus/applescript.rb +46 -0
- data/menus/as.rb +15 -0
- data/menus/bookmarklet.rb +63 -0
- data/menus/bootstrap.rb +568 -0
- data/menus/browse.rb +13 -0
- data/menus/browser.rb +78 -0
- data/menus/cassandra_db.rb +36 -0
- data/menus/chmod.rb +27 -0
- data/menus/classes.rb +5 -0
- data/menus/coffee_script.rb +35 -0
- data/menus/computer.rb +24 -0
- data/menus/contacts.rb +5 -0
- data/menus/cookies.rb +25 -0
- data/menus/couch.rb +184 -0
- data/menus/crop.rb +45 -0
- data/menus/css.rb +55 -0
- data/menus/current.rb +5 -0
- data/menus/db.rb +12 -0
- data/menus/deck.rb +219 -0
- data/menus/dictionary.rb +9 -0
- data/menus/dir.rb +8 -0
- data/menus/disk.rb +5 -0
- data/menus/do.rb +13 -0
- data/menus/docs.rb +58 -0
- data/menus/dotsies.rb +107 -0
- data/menus/edited.rb +18 -0
- data/menus/emacs.rb +17 -0
- data/menus/enter.rb +13 -0
- data/menus/eval.rb +17 -0
- data/menus/executable.rb +16 -0
- data/menus/filter.rb +46 -0
- data/menus/firefox.rb +607 -0
- data/menus/foo.rb +30 -0
- data/menus/french.rb +7 -0
- data/menus/git.rb +185 -0
- data/menus/gito.rb +785 -0
- data/menus/google.rb +35 -0
- data/menus/google_images.rb +11 -0
- data/menus/google_patents.rb +10 -0
- data/menus/gutenberg.rb +13 -0
- data/menus/head.rb +10 -0
- data/menus/headings.rb +39 -0
- data/menus/html.rb +61 -0
- data/menus/icon.rb +40 -0
- data/menus/images.menu +2 -0
- data/menus/img.rb +15 -0
- data/menus/info.rb +9 -0
- data/menus/ip.rb +10 -0
- data/menus/iterm.rb +36 -0
- data/menus/itunes.rb +78 -0
- data/menus/javascript.rb +74 -0
- data/menus/layout.rb +18 -0
- data/menus/local_storage.rb +67 -0
- data/menus/ls.rb +19 -0
- data/menus/mac.rb +87 -0
- data/menus/maps.rb +18 -0
- data/menus/matches.rb +18 -0
- data/menus/memcache.rb +117 -0
- data/menus/mkdir.rb +23 -0
- data/menus/mongo.rb +83 -0
- data/menus/mysql.rb +294 -0
- data/menus/node.rb +88 -0
- data/menus/open.rb +19 -0
- data/menus/outline.rb +24 -0
- data/menus/piano.rb +746 -0
- data/menus/postgres.rb +34 -0
- data/menus/pre.rb +5 -0
- data/menus/python.rb +39 -0
- data/menus/rails.rb +160 -0
- data/menus/rake.rb +12 -0
- data/menus/redmine.rb +168 -0
- data/menus/riak_tree.rb +204 -0
- data/menus/rss.rb +15 -0
- data/menus/safari.rb +11 -0
- data/menus/sass.rb +15 -0
- data/menus/say.rb +6 -0
- data/menus/scale.rb +49 -0
- data/menus/serve.rb +78 -0
- data/menus/shuffle.rb +24 -0
- data/menus/spanish.rb +7 -0
- data/menus/standalone.rb +57 -0
- data/menus/tail.rb +41 -0
- data/menus/technologies.rb +19 -0
- data/menus/themes.rb +32 -0
- data/menus/thesaurus.rb +13 -0
- data/menus/to.rb +24 -0
- data/menus/twitter.rb +57 -0
- data/menus/wikipedia.rb +34 -0
- data/menus/words.rb +11 -0
- data/spec/code_tree_spec.rb +59 -0
- data/spec/diff_log_spec.rb +40 -0
- data/spec/file_tree_spec.rb +102 -0
- data/spec/keys_spec.rb +24 -0
- data/spec/line_spec.rb +68 -0
- data/spec/menu_spec.rb +50 -0
- data/spec/ol_spec.rb +98 -0
- data/spec/remote_spec.rb +43 -0
- data/spec/search_spec.rb +162 -0
- data/spec/text_util_spec.rb +119 -0
- data/spec/tree_cursor_spec.rb +91 -0
- data/spec/tree_spec.rb +955 -0
- data/tests/console_test.rb +11 -0
- data/tests/couch_db_test.rb +12 -0
- data/tests/diff_log_test.rb +43 -0
- data/tests/el_mixin.rb +16 -0
- data/tests/git_test.rb +95 -0
- data/tests/keys_test.rb +19 -0
- data/tests/line_test.rb +38 -0
- data/tests/merb_test.rb +11 -0
- data/tests/redmine_test.rb +50 -0
- data/tests/remote_test.rb +31 -0
- data/tests/rest_tree_test.rb +70 -0
- data/xiki.gemspec +37 -0
- metadata +332 -0
data/lib/code_tree.rb
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
require 'line'
|
|
2
|
+
require 'ol'
|
|
3
|
+
|
|
4
|
+
class CodeTree
|
|
5
|
+
|
|
6
|
+
def self.menus; @menus; end
|
|
7
|
+
|
|
8
|
+
def self.add_menu item
|
|
9
|
+
@menus ||= []
|
|
10
|
+
@menus << item unless @menus.member? item
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Mapped to C-.
|
|
14
|
+
def self.launch options={}
|
|
15
|
+
line = Line.without_indent
|
|
16
|
+
|
|
17
|
+
return Search.open_file_and_method line if Keys.open? # If as+open, just navigato to it!
|
|
18
|
+
|
|
19
|
+
FileTree.extra_line_if_end_of_file
|
|
20
|
+
Tree.plus_to_minus_maybe
|
|
21
|
+
orig = Location.new
|
|
22
|
+
Line.to_left
|
|
23
|
+
path = options[:path] || Tree.construct_path(:list=>true)
|
|
24
|
+
path.each do |l|
|
|
25
|
+
# if '- .xx:/", get rid of trailing slash
|
|
26
|
+
l.sub!(/^([+-] .*\..+)\/$/, "\\1")
|
|
27
|
+
end
|
|
28
|
+
# Determine code to eval
|
|
29
|
+
code = self.determine_code_from_path path
|
|
30
|
+
orig.go
|
|
31
|
+
|
|
32
|
+
self.run code, options
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.returned_to_s returned
|
|
36
|
+
|
|
37
|
+
if returned.is_a? String # Join and bulletize
|
|
38
|
+
returned
|
|
39
|
+
elsif returned.is_a? Array # Join and bulletize
|
|
40
|
+
returned.map{|l| "#{l =~ /\/$/ ? '+' : '-'} #{l}\n"}.join('')
|
|
41
|
+
elsif returned.is_a? Hash
|
|
42
|
+
(returned.map{|k, v| v =~ /\/$/ ? "+ #{k}: #{v}" : "- #{k}: #{v}"}.join("\n")) + "\n"
|
|
43
|
+
else
|
|
44
|
+
returned.to_s.strip
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.draw_exception exception, code=nil
|
|
49
|
+
message = exception.message
|
|
50
|
+
|
|
51
|
+
# TODO: pay attention to this option?
|
|
52
|
+
# Ol << "options[:suggest_args]: #{options[:suggest_args].inspect}"
|
|
53
|
+
|
|
54
|
+
# TODO
|
|
55
|
+
# For now, don't do it!
|
|
56
|
+
# - How to not show "arg1" etc
|
|
57
|
+
# - when ArgumentError is code deeper than the immediate one
|
|
58
|
+
# if exception.is_a? ArgumentError
|
|
59
|
+
# count, required = message.match(/\((\d+) for (\d+)\)/)[1..2]
|
|
60
|
+
# if count < required # We can't add sample args if too many were supplied
|
|
61
|
+
# return (count.to_i+1..required.to_i).to_a.map{|o| "arg#{o}"}.join('/')+"/"
|
|
62
|
+
# end
|
|
63
|
+
# end
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if exception.is_a? RuntimeError
|
|
67
|
+
# If it was in the format of tree output, just show it
|
|
68
|
+
|
|
69
|
+
# Some messages start with "path:line:...: " at beginning again
|
|
70
|
+
|
|
71
|
+
message.sub!(/.+?: /, '') if message =~ /in `/
|
|
72
|
+
|
|
73
|
+
return message if message =~ /\A[>|+-] / # /^- /
|
|
74
|
+
return View.prompt($1) if(message =~ /\A\.prompt (.+)/)
|
|
75
|
+
return View.flash($1) if(message =~ /\A\.flash (.+)/)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
backtrace = exception.backtrace[0..8].join("\n").gsub(/^/, ' ') + "\n"
|
|
79
|
+
|
|
80
|
+
# If path in message, move it to the stack trace
|
|
81
|
+
if message =~ /(.+\d:in `.+'): (.+)/m
|
|
82
|
+
path, message = $1, $2
|
|
83
|
+
backtrace = " #{path}\n#{backtrace}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
message = message =~ /\n/ ?
|
|
87
|
+
"\n"+message.strip.gsub(/^/, " | ").gsub(/^( +\|) ([+-])/, "\\1\\2") :
|
|
88
|
+
" #{message}"
|
|
89
|
+
|
|
90
|
+
txt = ""
|
|
91
|
+
txt << "- tried to run: #{code}\n" if code
|
|
92
|
+
txt << "- error:#{message}\n- backtrace:\n#{backtrace}"
|
|
93
|
+
txt
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.run code, options={}
|
|
97
|
+
b = View.buffer
|
|
98
|
+
|
|
99
|
+
orig = Location.new
|
|
100
|
+
orig_left = $el.point
|
|
101
|
+
|
|
102
|
+
returned, stdout, e = Code.eval(code) # Eval code
|
|
103
|
+
# If no stdout (and something was returned), print return value
|
|
104
|
+
if ! stdout.nonempty? and ! returned.nil?
|
|
105
|
+
stdout = self.returned_to_s returned
|
|
106
|
+
else
|
|
107
|
+
message(returned.to_s) if returned and (!returned.is_a?(String) or returned.size < 500)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
stdout = self.draw_exception(e, code) if e
|
|
111
|
+
|
|
112
|
+
buffer_changed = b != View.buffer # Remember whether we left the buffer
|
|
113
|
+
# Insert output if there was any
|
|
114
|
+
if stdout.nonempty?
|
|
115
|
+
# Pull out flags
|
|
116
|
+
if stdout =~ /^:code_tree_option_tree_search\n/
|
|
117
|
+
options[:tree_search] = true
|
|
118
|
+
stdout.sub! /.+\n/, '' # Remove option
|
|
119
|
+
elsif stdout =~ /^:quote_search_option\n/
|
|
120
|
+
options[:quote_search] = true
|
|
121
|
+
stdout.sub! /.+\n/, '' # Remove option
|
|
122
|
+
elsif stdout =~ /^:code_tree_option_no_search\n/
|
|
123
|
+
options[:no_search] = true
|
|
124
|
+
stdout.sub! /.+\n/, '' # Remove option
|
|
125
|
+
end
|
|
126
|
+
ended_up = Location.new
|
|
127
|
+
|
|
128
|
+
# Go back to where we were before running code
|
|
129
|
+
orig.go
|
|
130
|
+
indent = Line.indent
|
|
131
|
+
Line.to_left
|
|
132
|
+
Line.next
|
|
133
|
+
left = $el.point
|
|
134
|
+
|
|
135
|
+
# Move what they printed over to left margin initally, in case they haven't
|
|
136
|
+
stdout = TextUtil.unindent(stdout)
|
|
137
|
+
stdout.sub!(/\n\n\z/, "\n") # Remove any double linebreaks at end
|
|
138
|
+
|
|
139
|
+
stdout.gsub!(/^/, "#{indent} ")
|
|
140
|
+
|
|
141
|
+
View << stdout # Insert output
|
|
142
|
+
right = $el.point
|
|
143
|
+
|
|
144
|
+
orig.go # Move cursor back
|
|
145
|
+
ended_up.go # End up where script took us
|
|
146
|
+
|
|
147
|
+
# These are deprecated - eventually pull them out
|
|
148
|
+
if options[:tree_search] # If they want to do a tree search
|
|
149
|
+
$el.goto_char left
|
|
150
|
+
FileTree.select_next_file
|
|
151
|
+
Tree.search(:left=>left, :right=>right, :recursive=>true)
|
|
152
|
+
return
|
|
153
|
+
end
|
|
154
|
+
if options[:quote_search] # If they want to do a tree search
|
|
155
|
+
$el.goto_char left
|
|
156
|
+
Search.forward "|"
|
|
157
|
+
Line.to_beginning
|
|
158
|
+
Tree.search(:left=>left, :right=>right, :recursive_quotes=>true)
|
|
159
|
+
return
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# If script didn't move us (line or buffer), do incremental search
|
|
163
|
+
if !options[:no_search] && !buffer_changed && $el.point == orig_left
|
|
164
|
+
# TODO No search if there aren't more than 3 lines
|
|
165
|
+
$el.goto_char left
|
|
166
|
+
|
|
167
|
+
Line.to_words
|
|
168
|
+
|
|
169
|
+
# Determine how to search based on output!
|
|
170
|
+
|
|
171
|
+
Tree.search_appropriately left, right, stdout
|
|
172
|
+
|
|
173
|
+
elsif options[:no_search]
|
|
174
|
+
Line.to_beginning :down=>1
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def self.menu
|
|
181
|
+
l = []
|
|
182
|
+
ObjectSpace.each_object(Class) do |c|
|
|
183
|
+
next unless c.respond_to?(:menu)
|
|
184
|
+
l << c.to_s
|
|
185
|
+
end
|
|
186
|
+
l.map! {|c| c.sub(/^#.+::/, '')}
|
|
187
|
+
(l + menus).sort.each do |c|
|
|
188
|
+
next if ["CodeTree"].member?(c)
|
|
189
|
+
puts "+ #{c}.menu/"
|
|
190
|
+
end
|
|
191
|
+
""
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def self.layout_menu
|
|
195
|
+
View.bar if Keys.prefix_u?
|
|
196
|
+
|
|
197
|
+
buffer = "*CodeTree CodeTree menu"
|
|
198
|
+
if View.buffer_open? buffer # If open, switch to it
|
|
199
|
+
View.to_buffer(buffer)
|
|
200
|
+
else # Else open it
|
|
201
|
+
Launcher.open("- CodeTree.menu/")
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Determine whether we should handle it
|
|
206
|
+
def self.handles? list=nil
|
|
207
|
+
list ||= Tree.construct_path(:list => true) # Use current line by default
|
|
208
|
+
|
|
209
|
+
code_tree_root = nil
|
|
210
|
+
index = list.size - 1
|
|
211
|
+
|
|
212
|
+
# If @..., don't bother with rest of path
|
|
213
|
+
list = [list[-1]] if list[-1][/^ *([+-] )?@/]
|
|
214
|
+
|
|
215
|
+
list.reverse.each do |l|
|
|
216
|
+
|
|
217
|
+
# If it has a char that wouldn't be in a file, must be code tree
|
|
218
|
+
#return index if l =~ /[\[\{=]/
|
|
219
|
+
|
|
220
|
+
# If last one was suspected as root, confirm we're not a dir (must be a file if parent is a dir)
|
|
221
|
+
if code_tree_root
|
|
222
|
+
if l =~ /\/$/ # Dir means it was a file that looked like code
|
|
223
|
+
# This means never interpret classes indented under foo/
|
|
224
|
+
code_tree_root = nil
|
|
225
|
+
else
|
|
226
|
+
return index + 1 # Must be legit, so return our index
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
# If function call, it might be the root
|
|
230
|
+
if l =~ /^[+-]? ?@?[A-Z][A-Za-z0-9]*\.[a-z_]/
|
|
231
|
+
code_tree_root = index
|
|
232
|
+
end
|
|
233
|
+
index -= 1
|
|
234
|
+
end
|
|
235
|
+
code_tree_root
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Rules for constructing code from path
|
|
239
|
+
# - examine path consisting of where C-. occurred and all its ancestors
|
|
240
|
+
# - root of tree is first ancestor with Class.method
|
|
241
|
+
# - invoke first ancestor method (using its params)
|
|
242
|
+
# - append all ancestor data nodes as params
|
|
243
|
+
# - include self if a data node
|
|
244
|
+
def self.determine_code_from_path path
|
|
245
|
+
data = []
|
|
246
|
+
clazz = metho = nil
|
|
247
|
+
metho_maybe = clazz_maybe = nil
|
|
248
|
+
|
|
249
|
+
i = -1
|
|
250
|
+
|
|
251
|
+
path.reverse.each do |l| # Climb up path
|
|
252
|
+
i += 1
|
|
253
|
+
|
|
254
|
+
l.sub! /^@/, '' # Remove delegate, so it's respected
|
|
255
|
+
|
|
256
|
+
metho_tmp = self.extract_method(l)
|
|
257
|
+
clazz_tmp = self.extract_class(l)
|
|
258
|
+
l.sub(/^(\s+)[+-] /, "\\1") # Remove bullets
|
|
259
|
+
is_root = i + 1 == path.size
|
|
260
|
+
code_node = false
|
|
261
|
+
if metho_tmp # If line has method
|
|
262
|
+
if clazz_tmp # If line has class
|
|
263
|
+
if is_root || self.definite_code_tree_root(l)
|
|
264
|
+
metho ||= metho_tmp
|
|
265
|
+
code_node = true
|
|
266
|
+
clazz ||= clazz_tmp
|
|
267
|
+
break if clazz
|
|
268
|
+
else # Use this if nothing else is found
|
|
269
|
+
metho_maybe ||= metho_tmp
|
|
270
|
+
clazz_maybe ||= clazz_tmp
|
|
271
|
+
end
|
|
272
|
+
else # Otherwise, it can be a method
|
|
273
|
+
metho ||= metho_tmp
|
|
274
|
+
code_node = true
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
if ! code_node # If not code node, must be data node
|
|
278
|
+
# Prepend to data list
|
|
279
|
+
data << self.paramify(l)
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
unless clazz # If no code found
|
|
284
|
+
return nil unless clazz_maybe
|
|
285
|
+
metho = metho_maybe
|
|
286
|
+
clazz = clazz_maybe
|
|
287
|
+
data = []
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# If one line, return it literally
|
|
291
|
+
if i == 0
|
|
292
|
+
return Line.without_label(:line=>path[-1]).sub(/\/$/, '')
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Extract any params from after method
|
|
296
|
+
method_with_params, params = metho.match(/(\w+\??)(.*)/)[1..2]
|
|
297
|
+
params.sub!(/^\((.*)\)$/, "\\1") # Remove parens if they're there
|
|
298
|
+
|
|
299
|
+
# Surround with curly brackets if it's a hash, and no curly brackets already
|
|
300
|
+
# Assumes all params are in a hash, which may not be right
|
|
301
|
+
if params =~ /=>/ && params !~ /\}$/
|
|
302
|
+
params = " {#{params.strip}}"
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# If last parameter was |..., make it be all the lines
|
|
306
|
+
if data.first =~ /^ *\|/
|
|
307
|
+
data.first.replace( self.escape(
|
|
308
|
+
Tree.siblings(:all=>true).map{|i| "#{i[/^ *\| ?(.*)/, 1]}\n"}.join('')
|
|
309
|
+
))
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# If any data nodes, pass as params
|
|
313
|
+
if ! data.empty?
|
|
314
|
+
data.reverse!
|
|
315
|
+
data.map! {|a| "\"#{a}\""}
|
|
316
|
+
params << ", " + data.join(", ")
|
|
317
|
+
end
|
|
318
|
+
# TODO Get rid of comma if there is one
|
|
319
|
+
params.sub!(/^, /, '')
|
|
320
|
+
"#{clazz}.#{method_with_params}(#{params})"
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def self.extract_class l
|
|
324
|
+
l[/^([A-Z][A-Za-z0-9]*)\.[a-z_]/, 1]
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def self.extract_method l
|
|
328
|
+
l = l.sub(/^[+-] [\w -]+?: /, '').sub(/^[+-] /, '') # Remove bullets
|
|
329
|
+
# Either class or bol
|
|
330
|
+
result = l[/^[A-Z][A-Za-z0-9]*\.([a-z_].*)/, 1] || # Class and method
|
|
331
|
+
l[/^\.([a-z].*)/, 1] # Method at beginning of line
|
|
332
|
+
result ? result.sub(/\/$/, '') : nil
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def self.paramify l
|
|
336
|
+
l = Line.without_label(:line=>l)
|
|
337
|
+
|
|
338
|
+
l = self.escape(l)
|
|
339
|
+
if l =~ /^\|/ # If |..., escape single-quotes
|
|
340
|
+
# l.gsub!("'", "\\'")
|
|
341
|
+
else
|
|
342
|
+
l.gsub! ', ', '", "'
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
l
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# Always escape backslashes, single-quotes, #'s
|
|
349
|
+
def self.escape l
|
|
350
|
+
l = l.gsub("\\", "\\\\\\\\")
|
|
351
|
+
l.gsub!("\"", "\\\\\"")
|
|
352
|
+
l.gsub!("#", "\\\\#")
|
|
353
|
+
l
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def self.kill_siblings options={}
|
|
358
|
+
prefix = Keys.prefix :clear=>true
|
|
359
|
+
|
|
360
|
+
left1, right1, left2, right2 = Tree.sibling_bounds
|
|
361
|
+
|
|
362
|
+
# If number, adjust
|
|
363
|
+
|
|
364
|
+
if prefix.is_a?(Fixnum)
|
|
365
|
+
left2 = Line.left prefix + 1
|
|
366
|
+
elsif prefix == :u
|
|
367
|
+
right2 = left2
|
|
368
|
+
elsif prefix == :uu
|
|
369
|
+
right1 = left1
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
View.delete left2, right2
|
|
373
|
+
View.delete left1, right1
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def self.do_kill_indented options={}
|
|
377
|
+
if Keys.up? || options[:cross_blank_lines]
|
|
378
|
+
left, right = Tree.sibling_bounds :cross_blank_lines=>1
|
|
379
|
+
else
|
|
380
|
+
left, ignore1, ignore2, right = Tree.sibling_bounds
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
View.cursor = left
|
|
384
|
+
$el.set_mark right
|
|
385
|
+
Effects.blink :left=>left, :right=>right # unless options[:dont_cross_blank_lines]
|
|
386
|
+
|
|
387
|
+
View.delete left, right
|
|
388
|
+
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def self.as_indented
|
|
392
|
+
prefix = Keys.prefix :clear=>1
|
|
393
|
+
|
|
394
|
+
indent = Line.indent.length
|
|
395
|
+
|
|
396
|
+
# If at left margin or current line followed by child
|
|
397
|
+
if prefix != :u && (prefix == :- || indent == 0 || indent == Line.indent(Line.value(2)).length - 2)
|
|
398
|
+
orig = View.cursor
|
|
399
|
+
left = Line.left
|
|
400
|
+
Line.next
|
|
401
|
+
ignore, right = Tree.sibling_bounds :cross_blank_lines=>1
|
|
402
|
+
View.cursor = orig
|
|
403
|
+
elsif prefix == :u
|
|
404
|
+
left, ignore1, ignore2, right = Tree.sibling_bounds
|
|
405
|
+
else
|
|
406
|
+
left, right = Tree.sibling_bounds :cross_blank_lines=>1
|
|
407
|
+
end
|
|
408
|
+
View.cursor = left
|
|
409
|
+
$el.set_mark right
|
|
410
|
+
Effects.blink :left=>left, :right=>right
|
|
411
|
+
|
|
412
|
+
Clipboard.copy "0"
|
|
413
|
+
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def self.kill_rest
|
|
417
|
+
prefix = Keys.prefix(:clear=>true)
|
|
418
|
+
column = View.column
|
|
419
|
+
|
|
420
|
+
right1 = Line.left
|
|
421
|
+
left2 = Line.left 2
|
|
422
|
+
|
|
423
|
+
Line.next if Search.backward("^$", :go_anyway=>true) # Go to beginning of paragraph
|
|
424
|
+
left1 = Line.left
|
|
425
|
+
|
|
426
|
+
Search.forward("^$", :go_anyway=>true) # Go to end of paragraph
|
|
427
|
+
right2 = Line.left
|
|
428
|
+
|
|
429
|
+
if prefix.is_a?(Fixnum)
|
|
430
|
+
View.cursor = left2
|
|
431
|
+
right2 = Line.left(prefix + 1)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
View.delete left2, right2 # Always delete after
|
|
435
|
+
Line.previous
|
|
436
|
+
|
|
437
|
+
# Optionally delete before
|
|
438
|
+
View.delete(left1, right1) if prefix == :u
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def self.tree_search_option
|
|
442
|
+
":code_tree_option_tree_search\n"
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def self.quote_search_option
|
|
446
|
+
":quote_search_option\n"
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def self.no_search_option
|
|
450
|
+
":code_tree_option_no_search\n"
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
def self.definite_code_tree_root line
|
|
454
|
+
line =~ /^[\s+-]*[A-Z].+\..+[\/)]$/
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
def self.maybe_code_tree_root line
|
|
458
|
+
line =~ /^[\s+-]*[A-Z].+\.[a-z_]/
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def self.definite_dir_tree_root line
|
|
462
|
+
line =~ /^[\s+-]*\//
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
# Turn list into bulleted string (adding + or - based on ending in slash)
|
|
466
|
+
def self.bulletize list
|
|
467
|
+
(list.map{|l| l =~ /\/$/ ? "+ #{l}" : "- #{l}"}.join("\n")) + "\n"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
def self.remove_slashes *args
|
|
471
|
+
args.each do |arg|
|
|
472
|
+
arg.sub! /\/$/, '' if arg
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
end
|