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/ruby.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
class Ruby
|
|
2
|
+
def self.menu
|
|
3
|
+
"
|
|
4
|
+
- .classes/
|
|
5
|
+
- .re_index_fast_ri/
|
|
6
|
+
- .docs/
|
|
7
|
+
> Ruby docs
|
|
8
|
+
@$ qri -h
|
|
9
|
+
|
|
10
|
+
> Eval code
|
|
11
|
+
| Evaluate the ruby code on adjascent lines, until a '> ...' heading.
|
|
12
|
+
@eval
|
|
13
|
+
puts('hi')
|
|
14
|
+
- @eval/
|
|
15
|
+
- @technologies/ruby/
|
|
16
|
+
- language docs/
|
|
17
|
+
> Listing and categories of gems
|
|
18
|
+
@ https://www.ruby-toolbox.com/
|
|
19
|
+
"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.classes clazz=nil, method=nil
|
|
23
|
+
|
|
24
|
+
# If no params, show list of classes
|
|
25
|
+
|
|
26
|
+
if clazz.nil?
|
|
27
|
+
result = []
|
|
28
|
+
ObjectSpace.each_object(Class) do |c|
|
|
29
|
+
name = c.to_s
|
|
30
|
+
next if name =~ /^#/
|
|
31
|
+
result << "- #{name}/\n"
|
|
32
|
+
end
|
|
33
|
+
return result.sort.join
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# If just class, show methods
|
|
37
|
+
|
|
38
|
+
if method.nil?
|
|
39
|
+
result = ""
|
|
40
|
+
result << Kernel.const_get(clazz).instance_methods(false).sort.
|
|
41
|
+
collect {|i| "- #{i}/" }.join("\n")
|
|
42
|
+
result << Kernel.const_get(clazz).methods(false).sort.
|
|
43
|
+
collect {|i| "- ::#{i}/" }.join("\n")
|
|
44
|
+
return result
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# If method passed, lookup method's doc
|
|
48
|
+
|
|
49
|
+
method = "##{method}" unless method =~ /^::/
|
|
50
|
+
command = "qri #{clazz}#{method}"
|
|
51
|
+
Console[command].gsub(/\C-[.+?m/, '').gsub(/^/, '| ').gsub(/^\| +$/, '|')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.re_index_fast_ri
|
|
55
|
+
Console.run "fastri-server -b"
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/ruby_console.rb
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
gem 'net-ssh'
|
|
2
|
+
require 'net/ssh'
|
|
3
|
+
|
|
4
|
+
# Wraps around a local or remote irb or merb (and probably rails)
|
|
5
|
+
# console, passing commands to it and returning their stdout output.
|
|
6
|
+
class RubyConsole
|
|
7
|
+
|
|
8
|
+
@@output = ""
|
|
9
|
+
def self.output; @@output; end
|
|
10
|
+
|
|
11
|
+
@session = @channel = nil
|
|
12
|
+
|
|
13
|
+
CODE_SAMPLES = %q<
|
|
14
|
+
# Send something to a local irb console
|
|
15
|
+
RubyConsole.run("puts 'hey'")
|
|
16
|
+
|
|
17
|
+
# Send something to a merb console
|
|
18
|
+
RubyConsole.register(:foo, 'merb -m /projects/foo -i') # Do this only once
|
|
19
|
+
RubyConsole[:foo].run("y Account.first")
|
|
20
|
+
>
|
|
21
|
+
|
|
22
|
+
@@registered = {}
|
|
23
|
+
|
|
24
|
+
def initialize console_command='irb', server=nil
|
|
25
|
+
@console_command, @server = console_command, server
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def connect
|
|
29
|
+
begin
|
|
30
|
+
timeout(25) do
|
|
31
|
+
open_channel # Connect
|
|
32
|
+
# TODO: try to indent this
|
|
33
|
+
send_it %Q[conf.echo = false
|
|
34
|
+
# Temporary hack for nuby 1.8.4
|
|
35
|
+
$out_bufr = defined?(StringIO) ? StringIO.new : ''
|
|
36
|
+
|
|
37
|
+
module Kernel
|
|
38
|
+
def puts *args
|
|
39
|
+
args.each { |a|
|
|
40
|
+
$out_bufr << (
|
|
41
|
+
(a.class == Array) ?
|
|
42
|
+
(a.join("\\n") + "\\n") :
|
|
43
|
+
"\#{a}\\n"
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
48
|
+
def p *args
|
|
49
|
+
args.each { |a| $out_bufr << "\#{a.inspect}\n" }
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
end#timeout
|
|
57
|
+
rescue Timeout::Error=>e
|
|
58
|
+
Ol << 'Timed out in RubyConsole!'
|
|
59
|
+
end#begin
|
|
60
|
+
end#def
|
|
61
|
+
|
|
62
|
+
# Send output
|
|
63
|
+
def send_it the_command
|
|
64
|
+
time_stamp = "-eor#{Time.now.usec}-"
|
|
65
|
+
|
|
66
|
+
the_command = "\
|
|
67
|
+
# Temporary hack for nuby 1.8.4
|
|
68
|
+
$out_bufr = defined?(StringIO) ? StringIO.new : ''
|
|
69
|
+
begin
|
|
70
|
+
#{the_command}
|
|
71
|
+
rescue Exception => e
|
|
72
|
+
puts e.message
|
|
73
|
+
end
|
|
74
|
+
# Temporary hack for nuby 1.8.4
|
|
75
|
+
out = $out_bufr.respond_to?(:string) ? $out_bufr.string : $out_bufr
|
|
76
|
+
puts '#{time_stamp}'
|
|
77
|
+
$stdout.print out
|
|
78
|
+
"
|
|
79
|
+
|
|
80
|
+
#the_command.gsub!(/$/, " # input!")
|
|
81
|
+
begin
|
|
82
|
+
@channel.send_data(the_command)
|
|
83
|
+
@session.loop 2 do |session|
|
|
84
|
+
# Return true, unless found output
|
|
85
|
+
@@output !~ /^#{time_stamp}$/ && @@output !~ /___CLOSED___/
|
|
86
|
+
end
|
|
87
|
+
rescue Exception => e
|
|
88
|
+
puts "too slow! #{e.message}"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def open_channel
|
|
93
|
+
@session = if @server
|
|
94
|
+
user, server, port = Remote.split_root @server
|
|
95
|
+
Remote.new_connection(user, server, port)
|
|
96
|
+
else
|
|
97
|
+
Net::SSH.start('localhost', ENV['USER'] || ENV['USERNAME'])
|
|
98
|
+
end
|
|
99
|
+
@channel = @session.open_channel do |ch|
|
|
100
|
+
ch.exec @console_command do |ch, success|
|
|
101
|
+
raise "could not execute command" unless success
|
|
102
|
+
# When console returns (prints) something
|
|
103
|
+
ch.on_data do |c, data|
|
|
104
|
+
# Use to debug problems / errors on server
|
|
105
|
+
# Ol << "data: #{data.inspect}"
|
|
106
|
+
RubyConsole.output << data
|
|
107
|
+
#print data
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# "on_extended_data" is called when the process writes something to stderr
|
|
111
|
+
ch.on_extended_data do |c, type, data|
|
|
112
|
+
print "error: #{data}"
|
|
113
|
+
end
|
|
114
|
+
ch.on_close {
|
|
115
|
+
RubyConsole.output << "___CLOSED___"
|
|
116
|
+
}
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def run the_command
|
|
123
|
+
connect unless @channel
|
|
124
|
+
send_it the_command
|
|
125
|
+
out = @@output
|
|
126
|
+
@@output = ""
|
|
127
|
+
|
|
128
|
+
# Remove up until beginning of output
|
|
129
|
+
out.sub!(/.*^.*\$stdout\.print out\n/m, '')
|
|
130
|
+
# Remove last line
|
|
131
|
+
out.sub!(/^.?.?.?-eor\d+-\n.*/, '')
|
|
132
|
+
|
|
133
|
+
out == "" ? "(no output)\n" : out
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def console_command= to; @console_command = to; end
|
|
137
|
+
def console_command; @console_command; end
|
|
138
|
+
|
|
139
|
+
def self.run the_command
|
|
140
|
+
self[:irb].run the_command
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def self.[] key
|
|
144
|
+
@@registered[key]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.register key, console_command='irb', server=nil
|
|
148
|
+
@@registered[key] = RubyConsole.new(console_command, server)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def self.at key, the_command
|
|
152
|
+
key = key.to_sym if key.is_a? String
|
|
153
|
+
console = self[key]
|
|
154
|
+
raise "No console has been defined for key '#{key}'." unless console
|
|
155
|
+
console.run the_command
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def session
|
|
159
|
+
connect unless @channel
|
|
160
|
+
@session
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
RubyConsole.register(:irb, 'irb')
|
data/lib/search.rb
ADDED
|
@@ -0,0 +1,1572 @@
|
|
|
1
|
+
require "hide"
|
|
2
|
+
require 'control_lock'
|
|
3
|
+
require 'line'
|
|
4
|
+
require 'text_util'
|
|
5
|
+
|
|
6
|
+
class Search
|
|
7
|
+
|
|
8
|
+
SPECIAL_ORDER = "X!='\"[]{}<>_-+*@#\\/!$X"
|
|
9
|
+
|
|
10
|
+
@@case_options = nil
|
|
11
|
+
@@outline_goto_once = nil
|
|
12
|
+
|
|
13
|
+
@@log = File.expand_path("~/.emacs.d/search_log.notes")
|
|
14
|
+
|
|
15
|
+
def self.menu
|
|
16
|
+
'
|
|
17
|
+
- .history/
|
|
18
|
+
- .log/
|
|
19
|
+
- .launched/
|
|
20
|
+
- docs/
|
|
21
|
+
| > Summary
|
|
22
|
+
| You start a search by typing Control-s. Then type the search string.
|
|
23
|
+
| Here are some interesting keys to type while searching, to do things
|
|
24
|
+
| with the match.
|
|
25
|
+
|
|
|
26
|
+
| > What do we mean by "search_bookmark" etc.?
|
|
27
|
+
| With all xiki keyboard shorcuts, you "type the acronym".
|
|
28
|
+
| By the key shortcut "search_bookmark" we mean typing Control-s and then
|
|
29
|
+
| Control-c.
|
|
30
|
+
|
|
|
31
|
+
| Of course, typing Control-s to search lets you type characters
|
|
32
|
+
| to search for, so in some cases typing a search string in between makes
|
|
33
|
+
| sense. So, search_clipboard actually means you would type Control-s then
|
|
34
|
+
| some characters to search for then Control-c to copy to the clipboard.
|
|
35
|
+
|
|
|
36
|
+
| > Examples
|
|
37
|
+
- examples/
|
|
38
|
+
| search_copy: Copy found to clipboard
|
|
39
|
+
| search_bookmark: Search text of files in a dir
|
|
40
|
+
| search_all: Show all previous searches
|
|
41
|
+
| search_value: Insert found where search began
|
|
42
|
+
| search_delete: Delete found
|
|
43
|
+
| search_diffs (without searching): Search in diffs
|
|
44
|
+
| search_todo: Search in $t bookmark
|
|
45
|
+
| search_files: Search in $f bookmark
|
|
46
|
+
| search_paths: Search history of menus
|
|
47
|
+
- miscellaneous/
|
|
48
|
+
| search_search: Re-do the last search
|
|
49
|
+
| search_word: Suck the next word in
|
|
50
|
+
| search_yank: Suck the rest of the line in
|
|
51
|
+
| search_usurp: Suck the next expression in
|
|
52
|
+
|
|
|
53
|
+
| For more details about Xiki keyboard shortcuts, see:
|
|
54
|
+
- @keys/docs/
|
|
55
|
+
|
|
|
56
|
+
- see/
|
|
57
|
+
<@ next/
|
|
58
|
+
'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.case_options
|
|
62
|
+
return @@case_options if @@case_options
|
|
63
|
+
@@case_options = [] # Set to empty if not set yet
|
|
64
|
+
self.add_case_option 'upper', proc {|txt| txt.upcase}
|
|
65
|
+
self.add_case_option 'lower', proc {|txt| txt.downcase}
|
|
66
|
+
self.add_case_option 'camel', proc {|txt| TextUtil.camel_case(txt)}
|
|
67
|
+
self.add_case_option 'snake', proc {|txt| TextUtil.snake_case(txt)}
|
|
68
|
+
@@case_options
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Make another option show up for View.cases
|
|
72
|
+
def self.add_case_option name, the_proc
|
|
73
|
+
# Delete if there already
|
|
74
|
+
@@case_options.delete_if{|i| i.first == name}
|
|
75
|
+
@@case_options << [name, the_proc]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.insert_at_spot
|
|
79
|
+
match = self.stop
|
|
80
|
+
Hide.show
|
|
81
|
+
|
|
82
|
+
Location.to_spot
|
|
83
|
+
|
|
84
|
+
$el.insert match
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.insert_tree_at_spot
|
|
88
|
+
self.stop
|
|
89
|
+
txt = FileTree.snippet # Grab symbol
|
|
90
|
+
Hide.show
|
|
91
|
+
Location.go :_0
|
|
92
|
+
$el.insert txt
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def self.insert_at_search_start
|
|
96
|
+
was_reverse = self.was_reverse
|
|
97
|
+
match = self.stop
|
|
98
|
+
|
|
99
|
+
if match.nil? # If nothing searched for yet, search difflog
|
|
100
|
+
loc = Keys.input(:chars=>1, :prompt=>"Enter one char to search for corresponding string: ")
|
|
101
|
+
loc = loc.to_s
|
|
102
|
+
|
|
103
|
+
txt = Clipboard.hash[loc.to_s] || Clipboard.hash_by_first_letter[loc.to_s]
|
|
104
|
+
txt ||= self.searches.find{|o| o =~ /^#{loc}/i}
|
|
105
|
+
|
|
106
|
+
return View.message("Nothing to search for matching '#{loc}'.", :beep=>1) if txt.nil?
|
|
107
|
+
self.isearch txt, :reverse=>was_reverse
|
|
108
|
+
|
|
109
|
+
return
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
self.to_start # Go back to start
|
|
113
|
+
$el.insert match
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def self.isearch_have_within
|
|
117
|
+
match = self.stop
|
|
118
|
+
self.to_start # Go back to start
|
|
119
|
+
$el.insert match[/^.(.*).$/, 1]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def self.move_to_search_start match
|
|
123
|
+
was_reverse = self.was_reverse
|
|
124
|
+
View.delete(Search.left, Search.right)
|
|
125
|
+
|
|
126
|
+
deleted = View.cursor
|
|
127
|
+
self.to_start # Go back to start
|
|
128
|
+
Move.backward match.length if was_reverse # If reverse, move back width of thing deleted
|
|
129
|
+
|
|
130
|
+
View.insert match
|
|
131
|
+
|
|
132
|
+
# Save spot where it was deleted (must do after modification, for bookmark to work)
|
|
133
|
+
View.cursor = deleted
|
|
134
|
+
Move.forward(match.length) unless was_reverse
|
|
135
|
+
Location.as_spot('killed')
|
|
136
|
+
|
|
137
|
+
self.to_start # Go back to start
|
|
138
|
+
Move.forward(match.length) unless was_reverse
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def self.insert_var_at_search_start
|
|
142
|
+
match = self.stop
|
|
143
|
+
self.to_start # Go back to start
|
|
144
|
+
$el.insert "\#{#{match}}"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.insert_quote_at_search_start
|
|
148
|
+
match = self.stop
|
|
149
|
+
self.to_start
|
|
150
|
+
$el.insert "'#{match}'"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.isearch_select_inner
|
|
154
|
+
self.stop
|
|
155
|
+
$el.set_mark self.left + 1
|
|
156
|
+
$el.goto_char self.right - 1
|
|
157
|
+
Effects.blink :what=>:region
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def self.isearch_delete
|
|
161
|
+
match = self.stop
|
|
162
|
+
|
|
163
|
+
# If nothing searched for, go to spot of last delete
|
|
164
|
+
if match.nil? # If nothing searched for yet, search difflog
|
|
165
|
+
DiffLog.open
|
|
166
|
+
View.to_bottom
|
|
167
|
+
Search.isearch nil, :reverse=>true
|
|
168
|
+
else
|
|
169
|
+
View.delete(Search.left, Search.right)
|
|
170
|
+
Location.as_spot('killed')
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def self.enter txt=nil
|
|
175
|
+
match = self.stop
|
|
176
|
+
txt ||= Clipboard[0]
|
|
177
|
+
|
|
178
|
+
if match.nil? # If nothing searched for yet, do search_edits
|
|
179
|
+
bm = Keys.input :timed=>true, :prompt=>"Enter a bookmark to search edits: "
|
|
180
|
+
|
|
181
|
+
return Launcher.open("diff log/diffs/") if bm == "8" || bm == " "
|
|
182
|
+
|
|
183
|
+
path = bm == "." ? View.file : "$#{bm}/"
|
|
184
|
+
return Launcher.open("- #{path}\n @edits/")
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
View.delete(Search.left, Search.right)
|
|
188
|
+
View.insert txt
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def self.copy_and_comment
|
|
192
|
+
self.stop
|
|
193
|
+
line = Line.value(1, :include_linebreak=>true).sub("\n", "")
|
|
194
|
+
Code.comment Line.left, Line.right
|
|
195
|
+
self.to_start # Go back to start
|
|
196
|
+
$el.insert "#{line}"
|
|
197
|
+
Line.to_beginning
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def self.isearch_just_comment
|
|
201
|
+
self.stop
|
|
202
|
+
Code.comment Line.left, Line.right
|
|
203
|
+
Line.to_beginning
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def self.just_increment options={}
|
|
207
|
+
|
|
208
|
+
match = self.stop
|
|
209
|
+
|
|
210
|
+
View.delete(Search.left, Search.right)
|
|
211
|
+
|
|
212
|
+
orig = View.cursor
|
|
213
|
+
|
|
214
|
+
position = SPECIAL_ORDER.index match
|
|
215
|
+
|
|
216
|
+
# If one of certain chars, use custom order
|
|
217
|
+
result =
|
|
218
|
+
if position # Change '[' to ']', etc
|
|
219
|
+
|
|
220
|
+
increment_or_decrement = options[:decrement] ? -1 : 1
|
|
221
|
+
SPECIAL_ORDER[position+increment_or_decrement].chr
|
|
222
|
+
|
|
223
|
+
else
|
|
224
|
+
if options[:decrement]
|
|
225
|
+
match =~ /[a-z]/i ?
|
|
226
|
+
(match[0] - 1) :
|
|
227
|
+
(match.to_i - 1).to_s
|
|
228
|
+
else
|
|
229
|
+
|
|
230
|
+
match.next
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
View.insert(result)
|
|
235
|
+
View.cursor = orig
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def self.jump_to_difflog
|
|
239
|
+
match = self.stop
|
|
240
|
+
self.to_start
|
|
241
|
+
Location.as_spot
|
|
242
|
+
|
|
243
|
+
DiffLog.open
|
|
244
|
+
View.to_bottom
|
|
245
|
+
|
|
246
|
+
Search.isearch match, :reverse=>true
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def self.just_edits
|
|
250
|
+
match = self.stop
|
|
251
|
+
DiffLog.open View.file
|
|
252
|
+
View.to_bottom
|
|
253
|
+
|
|
254
|
+
Search.isearch match, :reverse=>true
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def self.copy match
|
|
258
|
+
Clipboard[0] = match
|
|
259
|
+
$el.set_register ?X, match
|
|
260
|
+
$el.x_select_text match
|
|
261
|
+
Clipboard.save_by_first_letter match # Store for retrieval with enter_yank
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def self.cut
|
|
265
|
+
match = self.stop
|
|
266
|
+
|
|
267
|
+
# If nothing searched for, go to spot of last delete
|
|
268
|
+
if match.nil? # If nothing searched for yet
|
|
269
|
+
Location.to_spot('killed')
|
|
270
|
+
else
|
|
271
|
+
Clipboard.set(0, match)
|
|
272
|
+
$el.set_register ?X, match
|
|
273
|
+
View.delete self.left, self.right
|
|
274
|
+
Location.as_spot('killed')
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def self.go_to_end
|
|
279
|
+
match = self.stop
|
|
280
|
+
|
|
281
|
+
if match.nil? # If nothing searched for yet
|
|
282
|
+
Search.isearch_restart "$f", :restart=>true
|
|
283
|
+
return
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
$el.goto_char self.right
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Clears the isearch, allowing for inserting, or whatever else
|
|
290
|
+
def self.stop options={}
|
|
291
|
+
|
|
292
|
+
left, right = self.left, self.right
|
|
293
|
+
|
|
294
|
+
txt = self.match(left, right)# if options[:match]
|
|
295
|
+
|
|
296
|
+
# Make it do special clear if nothing found (to avoid weird isearch error)
|
|
297
|
+
if txt.nil?
|
|
298
|
+
if $el.elvar.isearch_success # || Search.left == View.bottom
|
|
299
|
+
# Done so isearch_done won't error
|
|
300
|
+
$el.isearch_resume "[^`]", true, nil, true, "", true
|
|
301
|
+
View.message ""
|
|
302
|
+
else
|
|
303
|
+
txt = :not_found
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
$el.elvar.isearch_mode = nil
|
|
308
|
+
|
|
309
|
+
$el.isearch_clean_overlays
|
|
310
|
+
$el.isearch_done
|
|
311
|
+
|
|
312
|
+
txt == :not_found ? Search.last_search : txt
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def self.match left=nil, right=nil
|
|
316
|
+
left ||= self.left
|
|
317
|
+
right ||= self.right
|
|
318
|
+
|
|
319
|
+
return nil if left == 0# || self.nil?
|
|
320
|
+
result = $el.buffer_substring(left, right)
|
|
321
|
+
|
|
322
|
+
return nil if result == ""
|
|
323
|
+
result
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def self.to_start
|
|
327
|
+
View.to($el.elvar.isearch_opoint)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# Do query replace depending on what they type
|
|
331
|
+
def self.query_replace s1=nil, s2=nil
|
|
332
|
+
if s1 && s2 # If manually passed in
|
|
333
|
+
$el.query_replace_regexp($el.regexp_quote(s1 || ""), s2 || "")
|
|
334
|
+
return
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
first = Keys.input(:timed=>true)
|
|
338
|
+
# If they typed 'o', use clipboard 1 and clipboard 2
|
|
339
|
+
if first == "o" || first == "1"
|
|
340
|
+
$el.query_replace_regexp($el.regexp_quote(Clipboard.get("1")), Clipboard.get("2"))
|
|
341
|
+
# If they typed 't', use clipboard 2 and clipboard 1
|
|
342
|
+
elsif first == "t" || first == "2"
|
|
343
|
+
$el.query_replace_regexp(Clipboard.get("2"), Clipboard.get("1"))
|
|
344
|
+
# If 'q', prompt for both args
|
|
345
|
+
elsif first == "q"
|
|
346
|
+
$el.query_replace_regexp(
|
|
347
|
+
Keys.input(:prompt=>"Replace: "),
|
|
348
|
+
Keys.input(:prompt=>"With: "))
|
|
349
|
+
# If they typed 'c', use clipboard and prompt for 2nd arg
|
|
350
|
+
elsif first == "c"
|
|
351
|
+
$el.query_replace_regexp(Clipboard.get, Keys.input(:prompt=>"Replace with (pause when done): ", :timed=>true))
|
|
352
|
+
# If they typed 'c', use clipboard and prompt for 2nd arg
|
|
353
|
+
elsif first == "l"
|
|
354
|
+
$el.query_replace_regexp(@@query_from, @@query_to)
|
|
355
|
+
# Otherwise, just get more input and use it
|
|
356
|
+
else
|
|
357
|
+
$el.query_replace_regexp(first, Keys.input(:timed=>true))
|
|
358
|
+
end
|
|
359
|
+
nil
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def self.isearch_query_replace after=nil
|
|
363
|
+
match = self.stop#
|
|
364
|
+
was_upper = match =~ /[A-Z]/
|
|
365
|
+
|
|
366
|
+
match.downcase!
|
|
367
|
+
left, right = Search.left, Search.right
|
|
368
|
+
before = $el.regexp_quote(match) # Always start with isearch match
|
|
369
|
+
|
|
370
|
+
# If before not there or is :match, prompt for input
|
|
371
|
+
if after.nil? || after == :match
|
|
372
|
+
initial_input = after == :match ? before : ''
|
|
373
|
+
after = Keys.input(:prompt=>"Change instances of '#{before}' to: ", :initial_input=>initial_input)
|
|
374
|
+
@@query_from, @@query_to = before, after
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
View.delete left, right
|
|
378
|
+
View.insert was_upper ?
|
|
379
|
+
TextUtil.title_case(after) :
|
|
380
|
+
after
|
|
381
|
+
|
|
382
|
+
$el.query_replace_regexp before, after
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def self.grep
|
|
386
|
+
cm_grep("./", read_from_minibuffer("Grep for pattern: "))
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def self.tree_grep # prefix=nil
|
|
390
|
+
|
|
391
|
+
prefix = Keys.isearch_prefix
|
|
392
|
+
path = Keys.bookmark_as_path :include_file=>1 # Get path (from bookmark)
|
|
393
|
+
|
|
394
|
+
# If C-u, just jump to bookmark and search from the top
|
|
395
|
+
if prefix == :u
|
|
396
|
+
View.open path
|
|
397
|
+
View.to_highest
|
|
398
|
+
Search.isearch
|
|
399
|
+
return
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
if path == :space # If space, search in buffers
|
|
403
|
+
self.find_in_buffers Keys.input(:prompt=>"Search all open files for: ")
|
|
404
|
+
return
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
input = Keys.input(:prompt=>"Text to search for: ")
|
|
408
|
+
|
|
409
|
+
input.gsub! "#", "\\#"
|
|
410
|
+
|
|
411
|
+
FileTree.grep_with_hashes path, input
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# Incrementeal search between cursor and end of paragraph (kills unmatching lines)
|
|
415
|
+
def self.kill_search(left, right)
|
|
416
|
+
pattern = ""
|
|
417
|
+
lines = $el.buffer_substring(left, right).split "\n"
|
|
418
|
+
ch = $el.char_to_string read_char
|
|
419
|
+
while ch =~ /[~#-'>a-zA-Z0-9!*\_'.~#-\/]/
|
|
420
|
+
if ch == "\t"
|
|
421
|
+
pattern = ""
|
|
422
|
+
else
|
|
423
|
+
pattern = pattern + regexp_quote(ch)
|
|
424
|
+
# Filter text and put back
|
|
425
|
+
View.delete left, right
|
|
426
|
+
# Replace out lines that don't match
|
|
427
|
+
lines = lines.grep(/#{pattern}/i)
|
|
428
|
+
# Put back into buffer
|
|
429
|
+
$el.insert lines.join("\n") + "\n"
|
|
430
|
+
right = $el.point
|
|
431
|
+
# Go to first file
|
|
432
|
+
$el.goto_char left
|
|
433
|
+
end
|
|
434
|
+
$el.message "Delete lines not matching: %s", pattern
|
|
435
|
+
ch = $el.char_to_string read_char
|
|
436
|
+
end
|
|
437
|
+
# Run whatever they typed last as a command (it was probably C-m or C-a, etc.)
|
|
438
|
+
case ch
|
|
439
|
+
when "\C-m" # If it was C-m
|
|
440
|
+
# Do nothing
|
|
441
|
+
else
|
|
442
|
+
$el.command_execute ch
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def self.search_in_bookmark match
|
|
447
|
+
|
|
448
|
+
bm = Keys.bookmark_as_path :include_file=>1
|
|
449
|
+
|
|
450
|
+
if bm == :slash # If space, go back to root and search
|
|
451
|
+
# Make match be orange
|
|
452
|
+
Overlay.face(:ls_search, :left=>self.left, :right=>self.right)
|
|
453
|
+
self.search_at_root match
|
|
454
|
+
return
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
View.to_after_bar if View.in_bar?
|
|
458
|
+
|
|
459
|
+
if bm == :space # If space, search in buffers
|
|
460
|
+
self.find_in_buffers match
|
|
461
|
+
return
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
match.gsub!(/([#()*+?^$\[\]|.])/, "\\\\\\1")
|
|
465
|
+
match.gsub! "\\+", "." # Change + to . to help when searching for key shortcuts
|
|
466
|
+
|
|
467
|
+
# Search in bookmark
|
|
468
|
+
FileTree.grep_with_hashes bm, match
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def self.subtract
|
|
473
|
+
match = self.match
|
|
474
|
+
|
|
475
|
+
if match # If currently searching
|
|
476
|
+
return $el.isearch_del_char
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
View.message "Unused!", :beep=>1
|
|
480
|
+
|
|
481
|
+
self.stop
|
|
482
|
+
self.search_last_launched
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def self.search_last_launched
|
|
486
|
+
match = self.stop
|
|
487
|
+
|
|
488
|
+
Launcher.open Launcher.last_launched_menu
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def self.launched bm=nil
|
|
492
|
+
|
|
493
|
+
txt = File.read @@log
|
|
494
|
+
txt = txt.sub(/\A- /, '').split(/^- /).reverse.uniq
|
|
495
|
+
if bm && bm == "#"
|
|
496
|
+
txt = txt.select{|o| o =~ /^ - ##/}
|
|
497
|
+
elsif bm && bm == ":"
|
|
498
|
+
txt = txt.select{|o| o =~ /^ - [^#].*: /}
|
|
499
|
+
elsif bm
|
|
500
|
+
|
|
501
|
+
path = Bookmarks[bm]
|
|
502
|
+
|
|
503
|
+
if File.file? path # File
|
|
504
|
+
regex = /^#{Regexp.escape File.dirname path}\/\n - #{Regexp.escape File.basename path}/
|
|
505
|
+
else # Dir
|
|
506
|
+
regex = /^#{Regexp.escape path}/
|
|
507
|
+
path = "#{path}/" if path !~ /\/$/
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
txt = txt.select{|o| o =~ regex}
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
result = "- @#{txt.join("- @")}"
|
|
514
|
+
result
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def self.left
|
|
518
|
+
$el.match_beginning 0
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def self.right
|
|
522
|
+
$el.match_end 0
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
def self.isearch_find_in_buffers options={}
|
|
526
|
+
match = self.stop
|
|
527
|
+
self.find_in_buffers match, options
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def self.find_in_buffers string, options={}
|
|
531
|
+
string.gsub!('"', '\\"')
|
|
532
|
+
new_args = "\"#{string}\""
|
|
533
|
+
new_options = {}
|
|
534
|
+
new_options[:buffer] = View.buffer_name if options[:current_only]
|
|
535
|
+
new_args << ", #{new_options.inspect[1..-2]}" unless new_options.empty?
|
|
536
|
+
|
|
537
|
+
View.bar if options[:in_bar]
|
|
538
|
+
$el.switch_to_buffer "*tree find in buffers"
|
|
539
|
+
Notes.mode
|
|
540
|
+
$el.erase_buffer
|
|
541
|
+
|
|
542
|
+
View.insert "+ Buffers.search #{new_args}/"
|
|
543
|
+
$el.open_line 1
|
|
544
|
+
CodeTree.launch :no_search=>true
|
|
545
|
+
if new_options[:buffer] # Goto first match
|
|
546
|
+
$el.goto_line 4
|
|
547
|
+
Line.to_words
|
|
548
|
+
Tree.search(:recursive=>false, :left=>Line.left, :right=>View.bottom)
|
|
549
|
+
else # Goto first match in 2nd file
|
|
550
|
+
$el.goto_line 2
|
|
551
|
+
$el.re_search_forward "^ -", nil, true
|
|
552
|
+
Line.next 2
|
|
553
|
+
Line.to_words
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
def self.just_marker
|
|
558
|
+
match = self.stop
|
|
559
|
+
|
|
560
|
+
$el.highlight_regexp(Regexp.quote(match), :notes_label)
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
def self.highlight_found
|
|
564
|
+
match = self.stop
|
|
565
|
+
|
|
566
|
+
$el.highlight_regexp(Regexp.quote(match), :hi_yellow)
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def self.hide
|
|
570
|
+
match = self.stop
|
|
571
|
+
Hide.hide_unless /#{Regexp.quote(match)}/i
|
|
572
|
+
$el.recenter -3
|
|
573
|
+
Hide.search
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
# Insert line at beginning of search
|
|
577
|
+
def self.have_line
|
|
578
|
+
self.stop
|
|
579
|
+
line = Line.value(1, :include_linebreak=>true).sub("\n", "")
|
|
580
|
+
self.to_start # Go back to start
|
|
581
|
+
$el.insert line
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
# Insert line at beginning of search
|
|
585
|
+
def self.have_label
|
|
586
|
+
self.stop
|
|
587
|
+
label = Line.label
|
|
588
|
+
self.to_start # Go back to start
|
|
589
|
+
$el.insert "- #{label}: "
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
# Insert line at beginning of search
|
|
593
|
+
def self.have_paragraph
|
|
594
|
+
self.stop
|
|
595
|
+
paragraph = View.paragraph
|
|
596
|
+
offset = View.cursor - View.paragraph(:bounds=>true)[0]
|
|
597
|
+
self.to_start # Go back to start
|
|
598
|
+
orig = Location.new
|
|
599
|
+
$el.insert paragraph
|
|
600
|
+
orig.go
|
|
601
|
+
Move.forward offset
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
# During isearch, pull next n words
|
|
606
|
+
def self.isearch_pull_in_words n
|
|
607
|
+
# If on the beginning of a grouping char, move back to catch the sexp
|
|
608
|
+
$el.el4r_lisp_eval "
|
|
609
|
+
(isearch-yank-internal
|
|
610
|
+
(lambda ()
|
|
611
|
+
(forward-word #{n}) (point)))"
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
# During isearch, pull next sexp into the search string
|
|
615
|
+
def self.isearch_pull_in_sexp
|
|
616
|
+
# If on the beginning of a grouping char, move back to catch the sexp
|
|
617
|
+
|
|
618
|
+
$el.el4r_lisp_eval %q=
|
|
619
|
+
(isearch-yank-internal
|
|
620
|
+
(lambda ()
|
|
621
|
+
(if (and (> (point) 1)
|
|
622
|
+
(string-match "[{<\\\\\"'(\\\\[]" (char-to-string (char-before (point))))
|
|
623
|
+
)
|
|
624
|
+
(backward-char))
|
|
625
|
+
(forward-sexp) (point)))=
|
|
626
|
+
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
# During isearch, open most recently edited file with the search string in its name
|
|
630
|
+
def self.isearch_to
|
|
631
|
+
match = self.stop
|
|
632
|
+
|
|
633
|
+
if match.nil? # If nothing searched for yet
|
|
634
|
+
Search.isearch_restart "$t", :restart=>true
|
|
635
|
+
|
|
636
|
+
else
|
|
637
|
+
dir = Keys.bookmark_as_path :prompt=>"Enter bookmark to look in (or space for recently edited): "
|
|
638
|
+
|
|
639
|
+
return View.message("Use space!", :beep=>1) if dir == :comma
|
|
640
|
+
|
|
641
|
+
return self.open_file_and_method(match) if dir == :space # If key is comma, treat as last edited
|
|
642
|
+
|
|
643
|
+
TextUtil.snake_case! match if match =~ /[a-z][A-Z]/ # If camel case, file is probably snake
|
|
644
|
+
FileTree.grep_with_hashes dir, match, '**' # Open buffer and search
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
#
|
|
649
|
+
# Jumps to the file corresponding to a string.
|
|
650
|
+
# The string has no path - the edited history (and visited history?)
|
|
651
|
+
# are used to find the file.
|
|
652
|
+
#
|
|
653
|
+
# If the string is like "Foo.bar" it jumps to the method as well ("foo").
|
|
654
|
+
#
|
|
655
|
+
# > Examples
|
|
656
|
+
# Search.open_file_and_method "View"
|
|
657
|
+
# Search.open_file_and_method "View.path"
|
|
658
|
+
#
|
|
659
|
+
def self.open_file_and_method match
|
|
660
|
+
|
|
661
|
+
match.sub!(/^[+-] /, '')
|
|
662
|
+
match.sub!(/ .+/, '')
|
|
663
|
+
|
|
664
|
+
if match =~ /(.+)[.#](.+)/
|
|
665
|
+
match, method = $1, $2 # split off, and open
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
# Convert to snake case, or nil if already in snake case
|
|
669
|
+
snake = TextUtil.snake_case(match)
|
|
670
|
+
snake = nil if snake == match
|
|
671
|
+
|
|
672
|
+
match = "#{match}."
|
|
673
|
+
snake = "#{snake}."
|
|
674
|
+
# For each file edited
|
|
675
|
+
found = (Files.edited_array + Files.history_array).find do |o|
|
|
676
|
+
|
|
677
|
+
next if o =~ /.notes$/ # Ignore notes files
|
|
678
|
+
next if o =~ /:/ # Ignore files with colons (tramp)
|
|
679
|
+
name = o[/.*\/(.*)/, 1] # Strip off path
|
|
680
|
+
# Check for match
|
|
681
|
+
if name =~ /^#{Regexp.quote(match)}/i || (snake && name =~ /^#{Regexp.quote(snake)}/i)
|
|
682
|
+
o
|
|
683
|
+
else
|
|
684
|
+
false
|
|
685
|
+
end
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
if found # Open it if it matches
|
|
689
|
+
View.open found
|
|
690
|
+
if method # If method, go to it
|
|
691
|
+
View.to_highest
|
|
692
|
+
result = Search.forward "^ +def \\(self\\.\\)?#{method}[^_a-zA-Z0-9]", :beginning=>true
|
|
693
|
+
|
|
694
|
+
return Code.suggest_creating_method View.file, method if !result # If not found, suggest creating
|
|
695
|
+
|
|
696
|
+
Move.to_axis
|
|
697
|
+
$el.recenter 0
|
|
698
|
+
|
|
699
|
+
dir, name = found.match(/(.+\/)(.+)/)[1..2]
|
|
700
|
+
Search.append_log dir, "- #{name}\n | #{Line.value}"
|
|
701
|
+
|
|
702
|
+
end
|
|
703
|
+
else
|
|
704
|
+
View.message "'#{match}' not found (no recently edited file with that substring found)."
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
return
|
|
708
|
+
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
def self.isearch_or_copy name
|
|
712
|
+
was_reverse = self.was_reverse
|
|
713
|
+
match = self.stop
|
|
714
|
+
|
|
715
|
+
if match.nil? # If nothing searched for yet
|
|
716
|
+
self.isearch Clipboard[name].downcase, :reverse=>was_reverse
|
|
717
|
+
else # Else, if nothing searched for
|
|
718
|
+
self.stop
|
|
719
|
+
Clipboard[name] = match
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
def self.isearch_copy_as name
|
|
724
|
+
self.stop
|
|
725
|
+
Clipboard.set(name, self.match)
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
def self.kill_filter options={}
|
|
729
|
+
# TODO: Get options[:kill_matching]=>true to delete matching
|
|
730
|
+
# - and map to Keys.do_kill_matching
|
|
731
|
+
Line.start
|
|
732
|
+
left = $el.point
|
|
733
|
+
$el.re_search_forward "^$", nil, 1
|
|
734
|
+
right = $el.point
|
|
735
|
+
$el.goto_char left
|
|
736
|
+
Tree.search(:left=>left, :right=>right, :recursive=>true)
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
def self.cancel
|
|
740
|
+
self.stop
|
|
741
|
+
self.to_start # Go back to start
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
# def self.not_found?
|
|
745
|
+
# # Note this returns false when nothing searched for
|
|
746
|
+
|
|
747
|
+
# ! elvar.isearch_success
|
|
748
|
+
# end
|
|
749
|
+
|
|
750
|
+
def self.forward search, options={}
|
|
751
|
+
View.to_highest if options[:from_top]
|
|
752
|
+
|
|
753
|
+
orig = View.cursor
|
|
754
|
+
found = $el.re_search_forward search, nil, (options[:go_anyway] ? 1 : true)
|
|
755
|
+
View.cursor = orig if options[:dont_move]
|
|
756
|
+
View.cursor = self.left if options[:beginning] && View.cursor != View.bottom
|
|
757
|
+
|
|
758
|
+
found
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
def self.backward search, options={}
|
|
762
|
+
orig = View.cursor
|
|
763
|
+
found = $el.re_search_backward search, nil, (options[:go_anyway] ? 1 : true)
|
|
764
|
+
View.cursor = orig if options[:dont_move]
|
|
765
|
+
found
|
|
766
|
+
end
|
|
767
|
+
|
|
768
|
+
def self.to find
|
|
769
|
+
Move.forward
|
|
770
|
+
if Search.forward(find)
|
|
771
|
+
match = $el.buffer_substring self.left, self.right
|
|
772
|
+
Move.backward(match.size)
|
|
773
|
+
else
|
|
774
|
+
$el.beep
|
|
775
|
+
$el.message "not found"
|
|
776
|
+
Move.backward
|
|
777
|
+
end
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
def self.isearch_open
|
|
781
|
+
self.stop
|
|
782
|
+
View.open(self.match)
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
def self.isearch_google options={}
|
|
786
|
+
term = self.stop
|
|
787
|
+
if term
|
|
788
|
+
term.gsub!(' ', '+')
|
|
789
|
+
|
|
790
|
+
term = "\"#{term}\"" if options[:quote]
|
|
791
|
+
|
|
792
|
+
term =~ /^https?:\/\// ? # If url, just browse
|
|
793
|
+
$el.browse_url(term) :
|
|
794
|
+
$el.browse_url("http://google.com/search?q=#{term}")
|
|
795
|
+
return
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
Firefox.log
|
|
799
|
+
Search.isearch nil, :from_bottom=>true
|
|
800
|
+
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
def self.search_thesaurus
|
|
804
|
+
term = self.stop
|
|
805
|
+
|
|
806
|
+
url = term.sub(/^\s+/, '').gsub('"', '%22').gsub(':', '%3A').gsub(' ', '%20')
|
|
807
|
+
$el.browse_url "http://thesaurus.reference.com/browse/#{url}"
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
def self.isearch_move_line
|
|
811
|
+
$el.isearch_done
|
|
812
|
+
$el.isearch_clean_overlays
|
|
813
|
+
line = $el.buffer_substring $el.point_at_bol, $el.point_at_eol + 1
|
|
814
|
+
View.delete $el.point_at_bol, $el.point_at_eol + 1
|
|
815
|
+
#self.to_start # Go back to start
|
|
816
|
+
$el.exchange_point_and_mark
|
|
817
|
+
$el.insert line
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
def self.outline
|
|
821
|
+
if Keys.prefix_u?
|
|
822
|
+
History.open_current :outline => true, :prompt_for_bookmark => true
|
|
823
|
+
else
|
|
824
|
+
History.open_current :outline => true
|
|
825
|
+
end
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
def self.outline_search
|
|
829
|
+
if Keys.prefix_u?
|
|
830
|
+
History.open_current :bar=>true, :all=>true
|
|
831
|
+
else
|
|
832
|
+
History.open_current :all=>true
|
|
833
|
+
end
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
def self.upcase
|
|
837
|
+
self.stop
|
|
838
|
+
$el.upcase_region(self.left, self.right)
|
|
839
|
+
end
|
|
840
|
+
|
|
841
|
+
def self.downcase
|
|
842
|
+
self.stop
|
|
843
|
+
$el.downcase_region(self.left, self.right)
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
def self.enter_like_edits
|
|
847
|
+
Notes.enter_junior
|
|
848
|
+
View << "@edits/"
|
|
849
|
+
Launcher.launch
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
def self.enter_search bm=nil, input=nil
|
|
853
|
+
# If line already has something, assume we'll add - ##foo/ to it
|
|
854
|
+
if ! Line[/^ *$/]
|
|
855
|
+
input = Keys.prefix_u ? Clipboard.get : Keys.input(:prompt=>"Text to search for: ")
|
|
856
|
+
indent = Line.indent
|
|
857
|
+
Line.to_right
|
|
858
|
+
View.insert "\n#{indent} - ###{input}/"
|
|
859
|
+
Launcher.launch
|
|
860
|
+
return
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
bm ||= Keys.input(:timed=>true, :prompt=>"Enter bookmark in which to search: ")
|
|
864
|
+
return unless bm
|
|
865
|
+
input ||= Keys.prefix_u? ? # Do search
|
|
866
|
+
Clipboard.get :
|
|
867
|
+
Keys.input(:prompt=>"Text to search for: ")
|
|
868
|
+
|
|
869
|
+
if bm == "." # Do tree in dir from bookmark
|
|
870
|
+
if Line.blank?
|
|
871
|
+
dir = $el.elvar.default_directory
|
|
872
|
+
else
|
|
873
|
+
dir = nil
|
|
874
|
+
end
|
|
875
|
+
else
|
|
876
|
+
dir = Bookmarks.expand("$#{bm}")
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
View.insert("- #{dir}" || "")
|
|
880
|
+
indent = Line.indent
|
|
881
|
+
Line.to_right
|
|
882
|
+
View.insert("\n#{indent} - ###{input}/")
|
|
883
|
+
FileTree.launch
|
|
884
|
+
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
def self.isearch_have_output
|
|
888
|
+
|
|
889
|
+
return self.isearch_have_output_javascript if View.extension == "js"
|
|
890
|
+
|
|
891
|
+
match = self.stop
|
|
892
|
+
self.to_start
|
|
893
|
+
return View.insert("Ol.line") if match.nil?
|
|
894
|
+
|
|
895
|
+
if Tree.construct_path(:all=>1, :slashes=>1) =~ /<script/
|
|
896
|
+
View.insert "console.log('#{match}: ' + #{match});"
|
|
897
|
+
return
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
View.insert "Ol << \"#{match}: \#{#{match}.inspect}\""
|
|
901
|
+
end
|
|
902
|
+
|
|
903
|
+
def self.isearch_have_output_javascript
|
|
904
|
+
match = self.stop
|
|
905
|
+
self.to_start
|
|
906
|
+
View.insert "p(\"#{match}: \" + #{match});"
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
def self.isearch_as_camel
|
|
910
|
+
self.stop
|
|
911
|
+
term = self.match
|
|
912
|
+
self.to_start
|
|
913
|
+
View.insert TextUtil.camel_case(term)
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
def self.isearch_as_snake
|
|
917
|
+
self.stop
|
|
918
|
+
term = self.match
|
|
919
|
+
self.to_start
|
|
920
|
+
View.insert TextUtil.snake_case(term)
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
def self.isearch_just_adjust
|
|
924
|
+
self.stop
|
|
925
|
+
Move.forward
|
|
926
|
+
transpose_chars 1
|
|
927
|
+
self.to_start
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
# Go to root of tree and do search
|
|
931
|
+
def self.search_at_root txt
|
|
932
|
+
Search.backward("^ *[+-] /")
|
|
933
|
+
# If next line isn't ##... line (will be visually distinct) add linebreak
|
|
934
|
+
unless Line.value(2) =~ /^ *[+-] ##/
|
|
935
|
+
Line.next
|
|
936
|
+
View.insert "\n"
|
|
937
|
+
Line.previous 2
|
|
938
|
+
end
|
|
939
|
+
self.enter_search '.', txt
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
def self.just_select
|
|
943
|
+
self.stop
|
|
944
|
+
View.set_mark(Search.right)
|
|
945
|
+
View.to(Search.left)
|
|
946
|
+
Effects.blink :what=>:region
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
def self.isearch_just_tag
|
|
950
|
+
self.stop
|
|
951
|
+
|
|
952
|
+
left, right = Search.left, Search.right
|
|
953
|
+
tag = Keys.input :timed=>true, :prompt=>"Enter tag name: "
|
|
954
|
+
left_tag = "<#{tag}>"
|
|
955
|
+
right_tag = "</#{tag}>"
|
|
956
|
+
if tag == 'di'
|
|
957
|
+
left_tag = "<div id='#{Keys.input :prompt=>"Enter id: "}'>"
|
|
958
|
+
right_tag = "</div>"
|
|
959
|
+
elsif tag == 'dc'
|
|
960
|
+
left_tag = "<div class='#{Keys.input :prompt=>"Enter id: "}'>"
|
|
961
|
+
right_tag = "</div>"
|
|
962
|
+
end
|
|
963
|
+
|
|
964
|
+
View.to(right)
|
|
965
|
+
View.insert right_tag
|
|
966
|
+
View.to(left)
|
|
967
|
+
View.insert left_tag
|
|
968
|
+
View.to right + left_tag.length
|
|
969
|
+
end
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
def self.isearch_just_wrap
|
|
973
|
+
self.stop
|
|
974
|
+
left, right = Search.left, Search.right
|
|
975
|
+
|
|
976
|
+
wrap_with = Keys.input :timed=>true, :prompt=>"Enter string to wrap match with: "
|
|
977
|
+
|
|
978
|
+
View.to(right)
|
|
979
|
+
View.insert wrap_with
|
|
980
|
+
View.to(left)
|
|
981
|
+
View.insert wrap_with
|
|
982
|
+
View.to right + wrap_with.length
|
|
983
|
+
end
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
def self.just_orange
|
|
987
|
+
self.stop
|
|
988
|
+
Overlay.face(:notes_label, :left=>Search.left, :right=>Search.right)
|
|
989
|
+
end
|
|
990
|
+
|
|
991
|
+
def self.just_edges
|
|
992
|
+
self.stop
|
|
993
|
+
left, right = Search.left+1, Search.right-1
|
|
994
|
+
Effects.blink :left=>left, :right=>right
|
|
995
|
+
View.delete(left, right)
|
|
996
|
+
View.to(Search.left+1)
|
|
997
|
+
end
|
|
998
|
+
|
|
999
|
+
def self.isearch_just_surround_with_char left=nil, right=nil
|
|
1000
|
+
|
|
1001
|
+
right ||= left
|
|
1002
|
+
term = self.stop
|
|
1003
|
+
|
|
1004
|
+
if term == ""
|
|
1005
|
+
View.insert "()"
|
|
1006
|
+
Move.backward
|
|
1007
|
+
return
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
View.to(Search.left + term.length)
|
|
1011
|
+
View.insert right
|
|
1012
|
+
View.to(Search.left)
|
|
1013
|
+
View.insert left
|
|
1014
|
+
View.to Search.left
|
|
1015
|
+
end
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
def self.isearch_surround_with_tag
|
|
1019
|
+
|
|
1020
|
+
term = self.stop
|
|
1021
|
+
left = Search.left
|
|
1022
|
+
|
|
1023
|
+
tag = Keys.input :timed=>1, :prompt=>"Enter tag to surround: "
|
|
1024
|
+
|
|
1025
|
+
View.to(left + term.length)
|
|
1026
|
+
View.insert "</#{tag}>"
|
|
1027
|
+
View.to left
|
|
1028
|
+
View.insert "<#{tag}>"
|
|
1029
|
+
View.to left
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
# Copy match as name (like Keys.as_name)
|
|
1033
|
+
def self.just_name
|
|
1034
|
+
term = self.stop
|
|
1035
|
+
loc ||= Keys.input(:chars=>1, :prompt=>"Enter one char (variable name to store this as): ") || "0"
|
|
1036
|
+
Clipboard.copy loc, term
|
|
1037
|
+
Effects.blink :left=>left, :right=>right
|
|
1038
|
+
end
|
|
1039
|
+
|
|
1040
|
+
def self.just_macro
|
|
1041
|
+
self.stop
|
|
1042
|
+
Macros.run
|
|
1043
|
+
end
|
|
1044
|
+
|
|
1045
|
+
def self.to_left
|
|
1046
|
+
match = self.stop
|
|
1047
|
+
if match.nil? # If nothing searched for yet
|
|
1048
|
+
return Launcher.open "- search/.history/", :bar_is_fine=>1
|
|
1049
|
+
end
|
|
1050
|
+
|
|
1051
|
+
Line.to_left
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
def self.just_menu
|
|
1055
|
+
match = self.stop
|
|
1056
|
+
View.open "$ml"
|
|
1057
|
+
View.to_bottom
|
|
1058
|
+
Search.isearch match, :reverse=>true
|
|
1059
|
+
end
|
|
1060
|
+
|
|
1061
|
+
def self.isearch_just_case
|
|
1062
|
+
was_reverse = self.was_reverse
|
|
1063
|
+
txt = self.stop
|
|
1064
|
+
|
|
1065
|
+
return Search.isearch(Clipboard[0], :reverse=>was_reverse) if txt.nil?
|
|
1066
|
+
|
|
1067
|
+
choice = Keys.input(:prompt=>'convert to which case?: ', :choices=>TextUtil.case_choices)
|
|
1068
|
+
View.delete(Search.left, Search.right)
|
|
1069
|
+
View.insert choice[txt]
|
|
1070
|
+
end
|
|
1071
|
+
|
|
1072
|
+
def self.isearch_have_case
|
|
1073
|
+
self.stop
|
|
1074
|
+
txt = self.match
|
|
1075
|
+
lam = Keys.input(:prompt=>'convert to which case?: ', :choices=>TextUtil.case_choices)
|
|
1076
|
+
self.to_start # Go back to start
|
|
1077
|
+
$el.insert lam[txt]
|
|
1078
|
+
end
|
|
1079
|
+
|
|
1080
|
+
def self.isearch_just_underscores
|
|
1081
|
+
self.stop
|
|
1082
|
+
term = self.match
|
|
1083
|
+
View.delete(Search.left, Search.right)
|
|
1084
|
+
View.insert TextUtil.snake_case(term)
|
|
1085
|
+
end
|
|
1086
|
+
|
|
1087
|
+
@@zap_hooks ||= {}
|
|
1088
|
+
# To set a hook
|
|
1089
|
+
# Search.zap_hooks 'm' do ... end
|
|
1090
|
+
def self.zap_hooks # key, &block
|
|
1091
|
+
@@zap_hooks#[key] = value
|
|
1092
|
+
end
|
|
1093
|
+
|
|
1094
|
+
def self.zap
|
|
1095
|
+
match = self.stop
|
|
1096
|
+
|
|
1097
|
+
if match.nil? # If nothing searched for yet
|
|
1098
|
+
char = Keys.input(:chars=>1, :prompt=>"Enter one char: ")
|
|
1099
|
+
block = self.zap_hooks[char]
|
|
1100
|
+
return View.beep "- search+zap+#{char}... doesn't seem to be defined!" if block.nil?
|
|
1101
|
+
return block.call
|
|
1102
|
+
end
|
|
1103
|
+
|
|
1104
|
+
right = $el.point
|
|
1105
|
+
self.to_start # Go back to search start
|
|
1106
|
+
View.delete($el.point, right)
|
|
1107
|
+
end
|
|
1108
|
+
|
|
1109
|
+
def self.xiki
|
|
1110
|
+
match = self.stop
|
|
1111
|
+
|
|
1112
|
+
View.beep "- Don't know what to do when search+x with search match." if match
|
|
1113
|
+
|
|
1114
|
+
char = Keys.input(:chars=>1, :prompt=>"Enter one char: ")
|
|
1115
|
+
if char == "m"
|
|
1116
|
+
Launcher.open("- $x/\n - ##\\bdef /")
|
|
1117
|
+
elsif char == "k"
|
|
1118
|
+
Launcher.open("- $x/key_bindings.rb\n - ##\\bKeys\\./")
|
|
1119
|
+
elsif char == "l"
|
|
1120
|
+
Launcher.open("- $ttm\n - ##xiki|isearch/")
|
|
1121
|
+
else
|
|
1122
|
+
View.beep "Don't know what to do with that char."
|
|
1123
|
+
end
|
|
1124
|
+
|
|
1125
|
+
end
|
|
1126
|
+
|
|
1127
|
+
def self.isearch_restart path, options={}
|
|
1128
|
+
self.stop
|
|
1129
|
+
term = Search.last_search
|
|
1130
|
+
|
|
1131
|
+
if path == "$t" # If $t, open bar
|
|
1132
|
+
View.layout_todo
|
|
1133
|
+
# FileTree.open_in_bar; Effects.blink(:what=>:line)
|
|
1134
|
+
elsif path == "$f"
|
|
1135
|
+
View.layout_files
|
|
1136
|
+
elsif path == "$o"
|
|
1137
|
+
View.layout_output
|
|
1138
|
+
options[:reverse] = true
|
|
1139
|
+
elsif path == "$d"
|
|
1140
|
+
View.open "$d"
|
|
1141
|
+
options[:reverse] = true
|
|
1142
|
+
elsif path == :top
|
|
1143
|
+
# Will go to highest below
|
|
1144
|
+
elsif path == :right
|
|
1145
|
+
View.layout_right 1
|
|
1146
|
+
elsif path == :next
|
|
1147
|
+
View.next
|
|
1148
|
+
elsif path == :previous
|
|
1149
|
+
View.previous
|
|
1150
|
+
else
|
|
1151
|
+
View.open Bookmarks[path]
|
|
1152
|
+
end
|
|
1153
|
+
|
|
1154
|
+
View.wrap unless options[:restart] # Don't change wrapping if starting search
|
|
1155
|
+
View.to_highest
|
|
1156
|
+
|
|
1157
|
+
if options[:reverse]
|
|
1158
|
+
View.to_bottom
|
|
1159
|
+
options[:restart] ? $el.isearch_backward : self.isearch(term, :reverse=>true)
|
|
1160
|
+
return
|
|
1161
|
+
end
|
|
1162
|
+
|
|
1163
|
+
options[:restart] ? $el.isearch_forward : self.isearch(term)
|
|
1164
|
+
end
|
|
1165
|
+
|
|
1166
|
+
def self.isearch txt=nil, options={}
|
|
1167
|
+
|
|
1168
|
+
if options[:from_bottom]
|
|
1169
|
+
View.to_bottom
|
|
1170
|
+
options[:reverse] = true
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1173
|
+
txt ||= "" # Searchig for nil causes error
|
|
1174
|
+
$el.isearch_resume txt, (options[:regex] ?true:nil), nil, (! options[:reverse]), txt, true
|
|
1175
|
+
$el.isearch_update
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
def self.isearch_stop_at_end
|
|
1179
|
+
# Kind of a hack - search for anything, so it won't error when we stop
|
|
1180
|
+
$el.isearch_resume "[^`]", true, nil, true, "", true
|
|
1181
|
+
|
|
1182
|
+
self.stop
|
|
1183
|
+
self.to_start # Go back to start
|
|
1184
|
+
|
|
1185
|
+
View.message ""
|
|
1186
|
+
nil
|
|
1187
|
+
end
|
|
1188
|
+
|
|
1189
|
+
def self.isearch_outline
|
|
1190
|
+
match = self.stop
|
|
1191
|
+
|
|
1192
|
+
if match.nil? # If nothing searched for yet
|
|
1193
|
+
# Do isearch in Ol buffer
|
|
1194
|
+
Search.isearch_restart "$o", :restart=>true
|
|
1195
|
+
|
|
1196
|
+
else
|
|
1197
|
+
if ! View.file # If buffer, not file
|
|
1198
|
+
buffer_name = $el.buffer_name
|
|
1199
|
+
txt = View.txt
|
|
1200
|
+
View.to_buffer "* outline of matches in #{buffer_name}"
|
|
1201
|
+
Notes.mode
|
|
1202
|
+
View.kill_all
|
|
1203
|
+
View.insert txt.grep(Regexp.new(match)).join
|
|
1204
|
+
|
|
1205
|
+
return
|
|
1206
|
+
end
|
|
1207
|
+
|
|
1208
|
+
# If file
|
|
1209
|
+
|
|
1210
|
+
Search.outline_goto_once = Line.number
|
|
1211
|
+
|
|
1212
|
+
dir = View.dir
|
|
1213
|
+
file_name = View.file_name
|
|
1214
|
+
View.to_buffer "*tree grep"; View.dir = dir
|
|
1215
|
+
View.clear; Notes.mode
|
|
1216
|
+
View.insert "
|
|
1217
|
+
- #{dir}/
|
|
1218
|
+
- #{file_name}
|
|
1219
|
+
- ###{Regexp.quote(match)}/
|
|
1220
|
+
".unindent
|
|
1221
|
+
|
|
1222
|
+
View.to_line 3
|
|
1223
|
+
FileTree.launch
|
|
1224
|
+
|
|
1225
|
+
# Search.isearch_find_in_buffers(:current_only=>true)
|
|
1226
|
+
end
|
|
1227
|
+
end
|
|
1228
|
+
|
|
1229
|
+
def self.isearch_paths
|
|
1230
|
+
was_reverse = self.was_reverse
|
|
1231
|
+
match = self.stop
|
|
1232
|
+
return Line.previous if match.nil? && was_reverse # Odd case, user might do this if at end of file
|
|
1233
|
+
return Git.search_repository if match.nil?
|
|
1234
|
+
|
|
1235
|
+
Search.move_to_search_start match
|
|
1236
|
+
end
|
|
1237
|
+
|
|
1238
|
+
def self.isearch_next
|
|
1239
|
+
was_reverse = self.was_reverse
|
|
1240
|
+
match = self.stop
|
|
1241
|
+
if match.nil? && Keys.before_last == "19" # If nothing searched for yet
|
|
1242
|
+
self.stop
|
|
1243
|
+
self.search_last_launched
|
|
1244
|
+
else
|
|
1245
|
+
|
|
1246
|
+
self.stop
|
|
1247
|
+
$el.next_line
|
|
1248
|
+
end
|
|
1249
|
+
end
|
|
1250
|
+
|
|
1251
|
+
def self.was_reverse
|
|
1252
|
+
! $el.elvar.isearch_forward
|
|
1253
|
+
end
|
|
1254
|
+
|
|
1255
|
+
def self.isearch_clipboard
|
|
1256
|
+
txt = Search.stop
|
|
1257
|
+
|
|
1258
|
+
if txt.nil? # If nothing searched for yet
|
|
1259
|
+
Console.search_last_commands
|
|
1260
|
+
else
|
|
1261
|
+
self.copy txt
|
|
1262
|
+
Location.as_spot('clipboard')
|
|
1263
|
+
end
|
|
1264
|
+
end
|
|
1265
|
+
|
|
1266
|
+
def self.isearch_pause_or_resume
|
|
1267
|
+
match = self.stop
|
|
1268
|
+
|
|
1269
|
+
if match.nil? # If nothing searched for yet, resume search
|
|
1270
|
+
Location.to_spot('paused')
|
|
1271
|
+
Search.isearch $xiki_paused_isearch_string
|
|
1272
|
+
else
|
|
1273
|
+
# If search in progress, stop it, remembering spot
|
|
1274
|
+
$xiki_paused_isearch_string = self.match.downcase
|
|
1275
|
+
Location.as_spot('paused')
|
|
1276
|
+
end
|
|
1277
|
+
end
|
|
1278
|
+
|
|
1279
|
+
def self.isearch_just_search
|
|
1280
|
+
self.just_orange
|
|
1281
|
+
match = self.match
|
|
1282
|
+
|
|
1283
|
+
Tree.to_parent # Go to parent
|
|
1284
|
+
Tree.to_parent if Line[/^ *- ##/]
|
|
1285
|
+
|
|
1286
|
+
Tree.under "- \#\##{match}/", :escape=>'', :no_search=>true
|
|
1287
|
+
Launcher.launch
|
|
1288
|
+
end
|
|
1289
|
+
|
|
1290
|
+
def self.isearch_enter_and_next
|
|
1291
|
+
if self.match == "" # If nothing searched for yet, go to where last copy happened
|
|
1292
|
+
self.stop
|
|
1293
|
+
Location.to_spot('clipboard')
|
|
1294
|
+
Search.isearch Clipboard[0]
|
|
1295
|
+
return
|
|
1296
|
+
end
|
|
1297
|
+
|
|
1298
|
+
match = self.stop
|
|
1299
|
+
View.delete(Search.left, Search.right)
|
|
1300
|
+
View.insert Clipboard[0]
|
|
1301
|
+
Search.isearch match
|
|
1302
|
+
end
|
|
1303
|
+
|
|
1304
|
+
def self.isearch_move_to path, options={}
|
|
1305
|
+
match = self.stop
|
|
1306
|
+
match = Line.value if match.nil? # Use line if nothing searched for
|
|
1307
|
+
self.move_to path, match, options
|
|
1308
|
+
end
|
|
1309
|
+
|
|
1310
|
+
|
|
1311
|
+
def self.move_to_files match
|
|
1312
|
+
match_with_path = FileTree.snippet :txt=>match
|
|
1313
|
+
match_with_path = ">\n- #{match_with_path}"
|
|
1314
|
+
|
|
1315
|
+
result = self.fit_in_snippet match
|
|
1316
|
+
result ? nil : match_with_path
|
|
1317
|
+
end
|
|
1318
|
+
|
|
1319
|
+
def self.fit_in_snippet match
|
|
1320
|
+
|
|
1321
|
+
target_path = View.file
|
|
1322
|
+
View.layout_files :no_blink=>1
|
|
1323
|
+
|
|
1324
|
+
View.to_highest
|
|
1325
|
+
Move.to_junior # Go to first file
|
|
1326
|
+
|
|
1327
|
+
path = Xiki.trunk.last # Grab from wiki tree
|
|
1328
|
+
|
|
1329
|
+
# If doesn't fit in the tree, just return to delegate back
|
|
1330
|
+
return false if ! target_path || ! target_path.start_with?(path)
|
|
1331
|
+
|
|
1332
|
+
cursor = Line.left 2
|
|
1333
|
+
FileTree.enter_quote match
|
|
1334
|
+
View.cursor = cursor
|
|
1335
|
+
|
|
1336
|
+
return true # If handled
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
def self.move_to path, match, options={}
|
|
1341
|
+
orig = Location.new
|
|
1342
|
+
was_in_bar = View.in_bar?
|
|
1343
|
+
|
|
1344
|
+
if path == "$t" # If $f, grab path also
|
|
1345
|
+
View.layout_todo :no_blink=>1
|
|
1346
|
+
elsif path == "$f" # If $f, grab path also
|
|
1347
|
+
match = self.move_to_files match
|
|
1348
|
+
return orig.go if ! match # It handled it if it didn't return the match
|
|
1349
|
+
else
|
|
1350
|
+
View.open path
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
# Maybe extract to .insert_in_section ?
|
|
1354
|
+
View.to_highest
|
|
1355
|
+
|
|
1356
|
+
line_occupied = ! Line.blank?
|
|
1357
|
+
|
|
1358
|
+
Notes.to_block if options[:append]
|
|
1359
|
+
|
|
1360
|
+
View.insert match
|
|
1361
|
+
|
|
1362
|
+
View.insert "\n" if line_occupied # Make room if line not blank
|
|
1363
|
+
|
|
1364
|
+
# Add line after if before heading, unless match already had one
|
|
1365
|
+
View.insert "\n" if Line[/^>/] && match !~ /\n$/ # If there wasn't a linebreak at the end of the match
|
|
1366
|
+
|
|
1367
|
+
line = View.line
|
|
1368
|
+
|
|
1369
|
+
View.to_highest
|
|
1370
|
+
|
|
1371
|
+
# Which case was this handling? Being in $f? Why leave cursor in $t when in $f?
|
|
1372
|
+
# return if path == "$t" && was_in_bar && orig.buffer != "todo.notes"
|
|
1373
|
+
|
|
1374
|
+
orig.go
|
|
1375
|
+
|
|
1376
|
+
if path == "$t" && orig.buffer == "todo.notes"
|
|
1377
|
+
Line.next line-1
|
|
1378
|
+
View.column = orig.column
|
|
1379
|
+
end
|
|
1380
|
+
end
|
|
1381
|
+
|
|
1382
|
+
def self.log
|
|
1383
|
+
View.open @@log
|
|
1384
|
+
end
|
|
1385
|
+
|
|
1386
|
+
def self.append_log dir, txt#, prefix=''
|
|
1387
|
+
txt = "- #{dir}\n #{txt}\n"
|
|
1388
|
+
File.open(@@log, "a") { |f| f << txt } rescue nil
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
def self.bookmark
|
|
1392
|
+
match = self.stop
|
|
1393
|
+
|
|
1394
|
+
if match.nil? # If nothing searched for yet, resume search
|
|
1395
|
+
Search.tree_grep
|
|
1396
|
+
else
|
|
1397
|
+
Search.search_in_bookmark match
|
|
1398
|
+
end
|
|
1399
|
+
end
|
|
1400
|
+
|
|
1401
|
+
def self.searches
|
|
1402
|
+
begin
|
|
1403
|
+
$el.elvar.search_ring.to_a
|
|
1404
|
+
rescue Exception=>e
|
|
1405
|
+
["error getting searches, probably because of special char :("]
|
|
1406
|
+
end
|
|
1407
|
+
end
|
|
1408
|
+
|
|
1409
|
+
def self.last_search
|
|
1410
|
+
begin
|
|
1411
|
+
$el.nth 0, $el.elvar.search_ring.to_a
|
|
1412
|
+
rescue Exception=>e
|
|
1413
|
+
View.beep
|
|
1414
|
+
return "- weird stuff in search ring!"
|
|
1415
|
+
end
|
|
1416
|
+
end
|
|
1417
|
+
|
|
1418
|
+
def self.history txt=nil
|
|
1419
|
+
|
|
1420
|
+
# If nothing selected yet, show history
|
|
1421
|
+
|
|
1422
|
+
if ! txt
|
|
1423
|
+
searches = self.searches.uniq
|
|
1424
|
+
return searches.map{|o| "| #{o}\n"}.join("")
|
|
1425
|
+
end
|
|
1426
|
+
|
|
1427
|
+
# Option selected, so search for it
|
|
1428
|
+
|
|
1429
|
+
txt.sub! /^\| /, ''
|
|
1430
|
+
|
|
1431
|
+
# Go back to where we came from, if we're in special search buffer
|
|
1432
|
+
View.kill if View.buffer_name == "@search/history/"
|
|
1433
|
+
|
|
1434
|
+
Search.isearch txt
|
|
1435
|
+
nil
|
|
1436
|
+
end
|
|
1437
|
+
|
|
1438
|
+
def self.outline_goto_once; @@outline_goto_once; end
|
|
1439
|
+
def self.outline_goto_once= txt; @@outline_goto_once = txt; end
|
|
1440
|
+
|
|
1441
|
+
def self.deep_outline txt, line
|
|
1442
|
+
txt = txt.split "\n"
|
|
1443
|
+
target_i = line
|
|
1444
|
+
|
|
1445
|
+
# Start with current line
|
|
1446
|
+
|
|
1447
|
+
i, children, matched_above = target_i-1, false, 1
|
|
1448
|
+
result = [txt[i]]
|
|
1449
|
+
target_indent = txt[i][/^ */].length / 2
|
|
1450
|
+
|
|
1451
|
+
# Go through each line above
|
|
1452
|
+
|
|
1453
|
+
while (i -= 1) >= 0
|
|
1454
|
+
# Grab lines with incrementally lower indent, but only if they have lines under!
|
|
1455
|
+
|
|
1456
|
+
line = txt[i]
|
|
1457
|
+
next if line.empty?
|
|
1458
|
+
indent = line[/^ */].length / 2
|
|
1459
|
+
|
|
1460
|
+
if indent > target_indent # If lower, skip, remembering children
|
|
1461
|
+
children = true
|
|
1462
|
+
elsif indent == target_indent # If same, only grab if there were children
|
|
1463
|
+
if children
|
|
1464
|
+
matched_above += 1
|
|
1465
|
+
result.unshift txt[i]
|
|
1466
|
+
end
|
|
1467
|
+
children = false
|
|
1468
|
+
else # Indented less
|
|
1469
|
+
|
|
1470
|
+
next if indent == 0 && line =~ /^#? ?Ol\b/ # Skip if ^Ol... line
|
|
1471
|
+
|
|
1472
|
+
matched_above += 1
|
|
1473
|
+
result.unshift txt[i]
|
|
1474
|
+
children = false
|
|
1475
|
+
target_indent = indent
|
|
1476
|
+
end
|
|
1477
|
+
end
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
i, candidate = target_i-1, nil
|
|
1481
|
+
target_indent = txt[i][/^ */].length / 2
|
|
1482
|
+
|
|
1483
|
+
# Go through each line below
|
|
1484
|
+
|
|
1485
|
+
while (i += 1) < txt.length
|
|
1486
|
+
# Grab lins with incrementally lower indent, but only if they have lines under!
|
|
1487
|
+
|
|
1488
|
+
line = txt[i]
|
|
1489
|
+
next if line.empty?
|
|
1490
|
+
indent = line[/^ */].length / 2
|
|
1491
|
+
|
|
1492
|
+
if indent > target_indent # If lower, add candidate if any
|
|
1493
|
+
if candidate
|
|
1494
|
+
result << candidate
|
|
1495
|
+
candidate = nil
|
|
1496
|
+
end
|
|
1497
|
+
|
|
1498
|
+
elsif indent == target_indent # If same, only grab if there were children
|
|
1499
|
+
candidate = txt[i]
|
|
1500
|
+
else # Indented less
|
|
1501
|
+
|
|
1502
|
+
next if indent == 0 && line =~ /^#? ?Ol\b/ # Skip if ^Ol... line
|
|
1503
|
+
|
|
1504
|
+
target_indent = indent
|
|
1505
|
+
candidate = txt[i]
|
|
1506
|
+
end
|
|
1507
|
+
|
|
1508
|
+
end
|
|
1509
|
+
|
|
1510
|
+
[result.join("\n")+"\n", matched_above]
|
|
1511
|
+
end
|
|
1512
|
+
|
|
1513
|
+
def self.isearch_m
|
|
1514
|
+
match = self.stop
|
|
1515
|
+
|
|
1516
|
+
return if match # If there was a match, just stop
|
|
1517
|
+
|
|
1518
|
+
Launcher.open("- log/") if match.nil?
|
|
1519
|
+
end
|
|
1520
|
+
|
|
1521
|
+
def self.just_bookmark
|
|
1522
|
+
match = self.stop
|
|
1523
|
+
path = Keys.bookmark_as_path :include_file=>1 # Get path (from bookmark)
|
|
1524
|
+
View.open path
|
|
1525
|
+
View.to_highest
|
|
1526
|
+
Search.isearch match
|
|
1527
|
+
end
|
|
1528
|
+
|
|
1529
|
+
def self.enter_insert_search
|
|
1530
|
+
# If in file tree, do ##
|
|
1531
|
+
if FileTree.handles?
|
|
1532
|
+
Search.enter_search
|
|
1533
|
+
else
|
|
1534
|
+
Google.insert
|
|
1535
|
+
end
|
|
1536
|
+
end
|
|
1537
|
+
|
|
1538
|
+
def self.like_delete
|
|
1539
|
+
match = self.stop
|
|
1540
|
+
|
|
1541
|
+
line = View.line
|
|
1542
|
+
|
|
1543
|
+
View.to_highest
|
|
1544
|
+
$el.delete_matching_lines match
|
|
1545
|
+
|
|
1546
|
+
View.line = line
|
|
1547
|
+
|
|
1548
|
+
end
|
|
1549
|
+
|
|
1550
|
+
def self.have_right
|
|
1551
|
+
match = self.stop
|
|
1552
|
+
View.to_upper
|
|
1553
|
+
View.to_highest
|
|
1554
|
+
View << "#{match}\n\n"
|
|
1555
|
+
end
|
|
1556
|
+
|
|
1557
|
+
#
|
|
1558
|
+
# Query replaces from "1" clipboard to "2" clipboard, etc.
|
|
1559
|
+
#
|
|
1560
|
+
# Search.query_replace_nth "1", "2"
|
|
1561
|
+
#
|
|
1562
|
+
def self.query_replace_nth n1, n2
|
|
1563
|
+
|
|
1564
|
+
if Keys.up? # If up+, grab line from last diff
|
|
1565
|
+
a, b = DiffLog.last_intraline_diff
|
|
1566
|
+
return Search.query_replace a, b
|
|
1567
|
+
end
|
|
1568
|
+
|
|
1569
|
+
Search.query_replace Clipboard.get(n1), Clipboard.get(n2)
|
|
1570
|
+
end
|
|
1571
|
+
|
|
1572
|
+
end
|