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/macros.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Starting and stopping macros
|
|
2
|
+
class Macros
|
|
3
|
+
|
|
4
|
+
def self.menu
|
|
5
|
+
"
|
|
6
|
+
docs/
|
|
7
|
+
> Keys
|
|
8
|
+
| as+job - Start or stop recording macro
|
|
9
|
+
| do+job - Run macro (the last recorded one)
|
|
10
|
+
| up+do+job - Stop recording and apply macro to any following contiguous lines
|
|
11
|
+
"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.record
|
|
15
|
+
# If ending a macro
|
|
16
|
+
if $el.elvar.defining_kbd_macro
|
|
17
|
+
$el.end_kbd_macro nil
|
|
18
|
+
# If starting a macro
|
|
19
|
+
else
|
|
20
|
+
$el.start_kbd_macro nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.run
|
|
25
|
+
# If defining a macro, just end it and run it
|
|
26
|
+
if $el.elvar.defining_kbd_macro
|
|
27
|
+
$el.end_kbd_macro nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# If U prefix prefix, apply until blank line
|
|
31
|
+
if Keys.prefix_u?
|
|
32
|
+
orig = Location.new
|
|
33
|
+
Line.next
|
|
34
|
+
left = $el.point
|
|
35
|
+
Search.forward "^$"
|
|
36
|
+
$el.beginning_of_line
|
|
37
|
+
$el.apply_macro_to_region_lines left, $el.point
|
|
38
|
+
orig.go
|
|
39
|
+
return
|
|
40
|
+
elsif Keys.prefix == 0 # If 0, do to region
|
|
41
|
+
$el.apply_macro_to_region_lines View.range_left, View.range_right
|
|
42
|
+
return
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Run it prefix times
|
|
46
|
+
$el.call_last_kbd_macro $el.elvar.current_prefix_arg || 1
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/man.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Man
|
|
2
|
+
def self.menu command=nil
|
|
3
|
+
if command == nil
|
|
4
|
+
return "
|
|
5
|
+
| Type a command to show its man page:
|
|
6
|
+
- example: ls
|
|
7
|
+
- last used: @last/man/
|
|
8
|
+
"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
`man #{command} | col -x -b`.gsub(/^/, '| ').gsub(/^\| $/, '|')
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.root
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
data/lib/menu.rb
ADDED
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
class Menu
|
|
2
|
+
|
|
3
|
+
def self.menu
|
|
4
|
+
'
|
|
5
|
+
- history/
|
|
6
|
+
- @log/
|
|
7
|
+
- @last/
|
|
8
|
+
- @all/
|
|
9
|
+
- .create/
|
|
10
|
+
- here/
|
|
11
|
+
- class/
|
|
12
|
+
- .install/
|
|
13
|
+
- gem/
|
|
14
|
+
- .setup/
|
|
15
|
+
- @~/menus/
|
|
16
|
+
- .reload_menus/
|
|
17
|
+
- .api/
|
|
18
|
+
> Summary
|
|
19
|
+
| How to use ruby code to define menus.
|
|
20
|
+
|
|
|
21
|
+
| You can create sophisticated menus backed by classes, or by using other
|
|
22
|
+
| simple means:
|
|
23
|
+
- .classes/
|
|
24
|
+
- .simple class/
|
|
25
|
+
- .menu with method/
|
|
26
|
+
- .menu with two methods/
|
|
27
|
+
- other/
|
|
28
|
+
- With a string/
|
|
29
|
+
|
|
|
30
|
+
| Menu.fish :menu=>"- salmon/\n- tuna/\n - yellow fin/"
|
|
31
|
+
|
|
|
32
|
+
Try it out by typing 1 do_ruby (C-1 Ctrl-d Ctrl-r) while on it, then
|
|
33
|
+
double-clicking on this menu to see what happens:
|
|
34
|
+
|
|
|
35
|
+
@fish/
|
|
36
|
+
|
|
|
37
|
+
- Delegating to an existing menu/
|
|
38
|
+
|
|
|
39
|
+
| Menu.critters :menu=>"foo/animals"
|
|
40
|
+
|
|
|
41
|
+
@critters/
|
|
42
|
+
|
|
|
43
|
+
- Using a block/
|
|
44
|
+
|
|
|
45
|
+
| Menu.foo do
|
|
46
|
+
| "hey/"
|
|
47
|
+
| end
|
|
48
|
+
|
|
|
49
|
+
The block can optionally take a |path| param to handle multiple levels
|
|
50
|
+
of nesting.
|
|
51
|
+
|
|
|
52
|
+
| Menu.foo do |path|
|
|
53
|
+
| "hey/#{path}"
|
|
54
|
+
| end
|
|
55
|
+
|
|
|
56
|
+
- Extract menu text from somewhere/
|
|
57
|
+
| Tree.children just expects text that is in the form of a menu (lines with
|
|
58
|
+
| 2-space indenting for nesting). So, the text can be pulled from
|
|
59
|
+
| anywhere, such as a part of a larger file:
|
|
60
|
+
|
|
|
61
|
+
| Menu.lawn do |path|
|
|
62
|
+
| menu = Notes.read_block("/tmp/garage.notes", "> Lawn")
|
|
63
|
+
| Tree.children menu, Tree.rootless(path)
|
|
64
|
+
| end
|
|
65
|
+
|
|
|
66
|
+
|
|
|
67
|
+
| If you want to create a very simple menu you can do so without code,
|
|
68
|
+
| by just putting the menu in a file such as ~/menu/foo.menu. See:
|
|
69
|
+
|
|
|
70
|
+
<< docs/how_to_create/
|
|
71
|
+
- .docs/
|
|
72
|
+
- .How to use/
|
|
73
|
+
- .How to create/
|
|
74
|
+
- .keys/
|
|
75
|
+
> Summary
|
|
76
|
+
| Helpful keyboard shortcuts when using menus.
|
|
77
|
+
|
|
|
78
|
+
| - as+menu
|
|
79
|
+
| - Save changes to menu (or create new one)
|
|
80
|
+
| - to+menu
|
|
81
|
+
| - Jump to file that implements menu
|
|
82
|
+
|
|
|
83
|
+
'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.install *args
|
|
87
|
+
Xiki.dont_search
|
|
88
|
+
Tree.quote "
|
|
89
|
+
> TODO
|
|
90
|
+
- implement this.
|
|
91
|
+
|
|
92
|
+
- Should it look for installed gems with this name?
|
|
93
|
+
- Should it just show commands to do a gem install?
|
|
94
|
+
- How would it know whether it the gem has a xiki menu?
|
|
95
|
+
"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def self.create *args
|
|
99
|
+
type = args[0]
|
|
100
|
+
|
|
101
|
+
return self.create_here if type == "here"
|
|
102
|
+
return self.create_class if type == "class"
|
|
103
|
+
return self.create_more(*args.drop(1)) if type == "more"
|
|
104
|
+
|
|
105
|
+
"- unknown option #{type} passed to .create!"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def self.create_here
|
|
109
|
+
|
|
110
|
+
# TODO: Handle various use cases
|
|
111
|
+
# "menu/create/here/" at left margin
|
|
112
|
+
# "@menu/create/here/" nested
|
|
113
|
+
# "menu/create/\n here/" at left margin
|
|
114
|
+
# "@menu/create/\n here/" nested
|
|
115
|
+
|
|
116
|
+
trunk = Xiki.trunk
|
|
117
|
+
if wrapper = trunk[-2] # If @menu/create/here is nested
|
|
118
|
+
menu = Tree.root wrapper
|
|
119
|
+
else # If put it under a fake menu
|
|
120
|
+
|
|
121
|
+
# What? This is if it's not nested? - is this used?
|
|
122
|
+
|
|
123
|
+
# TODO: Go to left margin and remove menu...
|
|
124
|
+
|
|
125
|
+
Tree.to_root
|
|
126
|
+
|
|
127
|
+
Tree.kill_under
|
|
128
|
+
menu = "foo"
|
|
129
|
+
Line.sub! /([ +-]*).*/, "\\1#{menu}/"
|
|
130
|
+
# Insert it wherever we are
|
|
131
|
+
end
|
|
132
|
+
Xiki.dont_search
|
|
133
|
+
|
|
134
|
+
name_text = menu == "foo" ?
|
|
135
|
+
"and change '#{menu}' to something" :
|
|
136
|
+
"to go under the '#{menu}' menu"
|
|
137
|
+
|
|
138
|
+
snake = TextUtil.snake_case menu
|
|
139
|
+
|
|
140
|
+
Tree << "
|
|
141
|
+
| Supply a few items here. Then do as+menu (type Ctrl-a Ctrl-m) to create
|
|
142
|
+
| the '#{menu}' menu. Or, just create '~/menus/#{snake}.menu' yourself.
|
|
143
|
+
- example item/
|
|
144
|
+
- another/
|
|
145
|
+
- and another/
|
|
146
|
+
"
|
|
147
|
+
|
|
148
|
+
nil
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def self.create_class
|
|
153
|
+
trunk = Xiki.trunk
|
|
154
|
+
if wrapper = trunk[-2]
|
|
155
|
+
# Just do in-line
|
|
156
|
+
menu = TextUtil.snake_case Tree.root(wrapper)
|
|
157
|
+
else
|
|
158
|
+
menu = 'foo'
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
Xiki.dont_search
|
|
162
|
+
|
|
163
|
+
Tree << %`
|
|
164
|
+
| Update this sample class to your liking. Then do as+update (type
|
|
165
|
+
| Ctrl-a, Ctrl-u) to create the '#{menu}' class file.
|
|
166
|
+
- @~/menus/
|
|
167
|
+
- #{menu}.rb
|
|
168
|
+
| class #{TextUtil.camel_case(menu)}
|
|
169
|
+
| def self.menu *args
|
|
170
|
+
| "- Args Passed: \#{args.inspect}\\n- Customize me in) @ ~/menus/#{menu}.rb"
|
|
171
|
+
| end
|
|
172
|
+
| end
|
|
173
|
+
- more examples) @menu/api/classes/
|
|
174
|
+
`
|
|
175
|
+
nil
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def self.simple_class *args
|
|
179
|
+
root = 'foo'
|
|
180
|
+
trunk = Xiki.trunk
|
|
181
|
+
root = TextUtil.snake_case(trunk[-2][/^[\w -]+/]) if trunk.length > 1 # If nested path (due to @), grab root of parent
|
|
182
|
+
|
|
183
|
+
%`
|
|
184
|
+
- @~/menus/
|
|
185
|
+
- #{root}.rb
|
|
186
|
+
| class #{TextUtil.camel_case(root)}
|
|
187
|
+
| def self.menu *args
|
|
188
|
+
| "- args passed: \#{args.inspect}\n- Customize me in) @ ~/menus/#{menu}.rb"
|
|
189
|
+
| end
|
|
190
|
+
| end
|
|
191
|
+
`
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def self.menu_with_method *args
|
|
195
|
+
root = 'foo'
|
|
196
|
+
trunk = Xiki.trunk
|
|
197
|
+
root = TextUtil.snake_case(trunk[-2][/^[\w -]+/]) if trunk.length > 1 # If nested path (due to @), grab root of parent
|
|
198
|
+
|
|
199
|
+
%`
|
|
200
|
+
- @~/menus/
|
|
201
|
+
- #{root}.rb
|
|
202
|
+
| class #{TextUtil.camel_case(root)}
|
|
203
|
+
| def self.menu
|
|
204
|
+
| "
|
|
205
|
+
| - cake/
|
|
206
|
+
| - chocolate/
|
|
207
|
+
| - .pie/
|
|
208
|
+
| "
|
|
209
|
+
| end
|
|
210
|
+
|
|
|
211
|
+
| def self.pie
|
|
212
|
+
| "- apple/"
|
|
213
|
+
| end
|
|
214
|
+
| end
|
|
215
|
+
`
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def self.menu_with_two_methods *args
|
|
219
|
+
root = 'foo'
|
|
220
|
+
trunk = Xiki.trunk
|
|
221
|
+
root = TextUtil.snake_case(trunk[-2][/^[\w -]+/]) if trunk.length > 1 # If nested path (due to @), grab root of parent
|
|
222
|
+
|
|
223
|
+
%`
|
|
224
|
+
- @~/menus/
|
|
225
|
+
- #{root}.rb
|
|
226
|
+
| class #{TextUtil.camel_case(root)}
|
|
227
|
+
| def self.menu
|
|
228
|
+
| "
|
|
229
|
+
| - sammiches/
|
|
230
|
+
| - ham/
|
|
231
|
+
| - .buy/
|
|
232
|
+
| - tofu/
|
|
233
|
+
| - .buy/
|
|
234
|
+
| - .checkout/
|
|
235
|
+
| - cash/
|
|
236
|
+
| - credit/
|
|
237
|
+
| "
|
|
238
|
+
| end
|
|
239
|
+
| def self.buy category, item
|
|
240
|
+
| "- buying \#{item} \#{category}"
|
|
241
|
+
| end
|
|
242
|
+
| def self.checkout kind
|
|
243
|
+
| "- checking out as \#{kind}..."
|
|
244
|
+
| end
|
|
245
|
+
| end
|
|
246
|
+
|
|
|
247
|
+
`
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def self.how_to_use *args
|
|
251
|
+
%`
|
|
252
|
+
> Summary
|
|
253
|
+
| How to use Xiki menus. Note this refers to the wiki-style menus, not the menu bar.
|
|
254
|
+
|
|
|
255
|
+
| All menus can be used the same way. Just type something and double-click
|
|
256
|
+
| on it (or type Ctrl-enter while the cursor is on the line).
|
|
257
|
+
|
|
|
258
|
+
- example/
|
|
259
|
+
| 1: type "foo" on a line (the "@" isn't necessary when the line isn't indented)
|
|
260
|
+
@ foo
|
|
261
|
+
|
|
|
262
|
+
| 2: double-click on it to drill in. You can try it on the line above. It will look like this:
|
|
263
|
+
@ foo/
|
|
264
|
+
| - sammiches/
|
|
265
|
+
| - dranks/
|
|
266
|
+
|
|
|
267
|
+
| 3: double-click to drill in further. It will look like this:
|
|
268
|
+
@ foo/
|
|
269
|
+
| - sammiches/
|
|
270
|
+
| - ham/
|
|
271
|
+
| - tofu/
|
|
272
|
+
| - dranks/
|
|
273
|
+
|
|
|
274
|
+
- using the mouse/
|
|
275
|
+
| You can click on the "bullets" (the - and + at the beginnings of lines)
|
|
276
|
+
| to expand and collapse. You can also double-click to expand and
|
|
277
|
+
| collapse.
|
|
278
|
+
|
|
|
279
|
+
- search to narrow down/
|
|
280
|
+
| When you double-click a line the cursor turns blue and you can type
|
|
281
|
+
| letters to search and narrow down the list.
|
|
282
|
+
|
|
|
283
|
+
- misc keys/
|
|
284
|
+
| - Return: stops searching and launches (expands file or dir)
|
|
285
|
+
| - Tab: like return but hides others
|
|
286
|
+
| - ;: like return but collapses path
|
|
287
|
+
|
|
|
288
|
+
| - C-g: stops searching
|
|
289
|
+
|
|
|
290
|
+
| - Arrow keys: you can use them to go up and down and expand and collapse
|
|
291
|
+
|
|
|
292
|
+
`
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def self.how_to_create *args
|
|
296
|
+
txt = %q`
|
|
297
|
+
> Summary
|
|
298
|
+
| How to make your own menus in Xiki. Note this refers to wiki-style
|
|
299
|
+
| menus (such as this one), not the menu bar.
|
|
300
|
+
|
|
|
301
|
+
- Creating .menu files/
|
|
302
|
+
| You can make menus without code, by just put "whatever.menu" files in the
|
|
303
|
+
| "menu/" dir in your home dir.
|
|
304
|
+
|
|
|
305
|
+
| For example you could create a "foo.menu" file with the contents
|
|
306
|
+
| "- sammiches/..." etc:
|
|
307
|
+
|
|
|
308
|
+
- TODO: get these to expand out somehow! - maybe pass another arg to Tree.children below? - probably bad idea
|
|
309
|
+
- ~/menus/
|
|
310
|
+
- foo.menu
|
|
311
|
+
| - sammiches/
|
|
312
|
+
| - ham/
|
|
313
|
+
| - tofu/
|
|
314
|
+
| - dranks/
|
|
315
|
+
| - foty/
|
|
316
|
+
|
|
|
317
|
+
- Delegating/
|
|
318
|
+
| This makes a foo/ menu that you can expand. Even though these menus
|
|
319
|
+
| don't run code themselves, they can delegate to other menus or run code,
|
|
320
|
+
| like:
|
|
321
|
+
|
|
|
322
|
+
- ~/menus/
|
|
323
|
+
- foo.menu
|
|
324
|
+
| - @mymenu/
|
|
325
|
+
| - @MyClass.my_method
|
|
326
|
+
|
|
|
327
|
+
`
|
|
328
|
+
|
|
329
|
+
Tree.children(txt, args.join('/'))
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def self.reload_menus
|
|
333
|
+
Launcher.reload_menu_dirs
|
|
334
|
+
View.flash
|
|
335
|
+
nil
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def self.[] path
|
|
339
|
+
path, rest = path.split '/', 2
|
|
340
|
+
|
|
341
|
+
self.call path, rest
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def self.call root, rest=nil
|
|
345
|
+
menus = Launcher.menus
|
|
346
|
+
block = menus[0][root] || menus[1][root]
|
|
347
|
+
return if block.nil?
|
|
348
|
+
Tree.output_and_search block, :line=>"#{root}/#{rest}", :just_return=>1
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def self.method_missing *args, &block
|
|
352
|
+
Launcher.method_missing *args, &block
|
|
353
|
+
"- defined!"
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def self.split path, options={}
|
|
357
|
+
path = path.sub /\/$/, ''
|
|
358
|
+
path = Tree.rootless path if options[:rootless]
|
|
359
|
+
|
|
360
|
+
return [] if path.empty?
|
|
361
|
+
|
|
362
|
+
groups = path.split '/|', -1
|
|
363
|
+
|
|
364
|
+
result = groups[0] =~ /^\|/ ?
|
|
365
|
+
[groups[0]] :
|
|
366
|
+
groups[0].split('/', -1)
|
|
367
|
+
|
|
368
|
+
result += groups[1..-1].map{|o| "|#{o}"}
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def self.to_menu
|
|
372
|
+
# Take best guess, by looking through dirs for root
|
|
373
|
+
trunk = Xiki.trunk
|
|
374
|
+
|
|
375
|
+
return View.<<("- You weren't on a menu\n | To jump to a menu's implementation, put your cursor on it\n | (or type it on a blank line) and then do as+menu (ctrl-a ctrl-m)\n | Or, look in one of these dirs:\n - ~/menus/\n - $xiki/menus/") if trunk[-1].blank?
|
|
376
|
+
|
|
377
|
+
root = trunk[0][/^[\w _-]+/]
|
|
378
|
+
|
|
379
|
+
root = trunk[-1][/^[\w _-]+/] if ! Keys.prefix_u
|
|
380
|
+
|
|
381
|
+
root.gsub!(/[ -]/, '_') if root
|
|
382
|
+
|
|
383
|
+
root.downcase!
|
|
384
|
+
|
|
385
|
+
(["#{Xiki.dir}lib/"]+Launcher::MENU_DIRS).reverse.each do |dir|
|
|
386
|
+
next unless File.directory? dir
|
|
387
|
+
file = Dir["#{dir}/#{root}.*"]
|
|
388
|
+
next unless file.any?
|
|
389
|
+
return View.open file[0]
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# message = "
|
|
393
|
+
# - No menu found:
|
|
394
|
+
# | No \"#{root}\" menu or class file found in these dirs:
|
|
395
|
+
# @ ~/menus/
|
|
396
|
+
# @ $x/menus/
|
|
397
|
+
# ".unindent
|
|
398
|
+
|
|
399
|
+
# Should be able to get it right from proc
|
|
400
|
+
|
|
401
|
+
proc = Launcher.menus[1][root]
|
|
402
|
+
|
|
403
|
+
return View.flash "- Menu 'root' doesn't exist!", :times=>4 if ! proc
|
|
404
|
+
|
|
405
|
+
location = proc.source_location # ["./firefox.rb", 739]
|
|
406
|
+
location[0].sub! /^\.\//, Xiki.dir
|
|
407
|
+
View.open location[0]
|
|
408
|
+
View.line = location[1]
|
|
409
|
+
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def self.external menu, options={}
|
|
413
|
+
|
|
414
|
+
View.message ""
|
|
415
|
+
|
|
416
|
+
View.wrap :off
|
|
417
|
+
|
|
418
|
+
# IF nothing passed, must want to do tiny search box
|
|
419
|
+
if menu.empty?
|
|
420
|
+
Launcher.open ""
|
|
421
|
+
View.message ""
|
|
422
|
+
View.prompt "Type anything", :timed=>1, :times=>2 #, :color=>:rainbow
|
|
423
|
+
|
|
424
|
+
Launcher.launch
|
|
425
|
+
else
|
|
426
|
+
Launcher.open menu, options
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def self.as_menu
|
|
431
|
+
orig = View.cursor
|
|
432
|
+
|
|
433
|
+
Tree.to_root
|
|
434
|
+
|
|
435
|
+
root, left = Line.value, View.cursor
|
|
436
|
+
root = Line.without_label :line=>root
|
|
437
|
+
|
|
438
|
+
root = TextUtil.snake_case(root).sub(/^_+/, '')
|
|
439
|
+
|
|
440
|
+
if Line.value(2) =~ /^ +\| Supply a few items here/ # If sample text, remove
|
|
441
|
+
Line.next
|
|
442
|
+
while Line.=~(/^ +\| /)
|
|
443
|
+
Line.delete
|
|
444
|
+
end
|
|
445
|
+
Line.previous
|
|
446
|
+
orig = nil
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
Tree.after_children
|
|
450
|
+
right = View.cursor
|
|
451
|
+
View.cursor = left
|
|
452
|
+
|
|
453
|
+
# Go until end of paragraph (simple for now)
|
|
454
|
+
Effects.blink :left=>left, :right=>right
|
|
455
|
+
txt = View.txt left, right
|
|
456
|
+
txt.sub! /.+\n/, ''
|
|
457
|
+
txt.gsub! /^ /, ''
|
|
458
|
+
txt.unindent
|
|
459
|
+
|
|
460
|
+
return Tree << "| You must supply something to put under the '#{root}' menu.\n| First, add some lines here, such as these:\n- line/\n- another line/\n" if txt.empty?
|
|
461
|
+
|
|
462
|
+
path = File.expand_path "~/menus/#{root}.menu"
|
|
463
|
+
|
|
464
|
+
file_existed = File.exists? path
|
|
465
|
+
|
|
466
|
+
if file_existed
|
|
467
|
+
treeb = File.read path
|
|
468
|
+
txt = Tree.restore txt, treeb
|
|
469
|
+
|
|
470
|
+
DiffLog.save_diffs :patha=>path, :textb=>txt
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
File.open(path, "w") { |f| f << txt }
|
|
474
|
+
|
|
475
|
+
View.cursor = orig if orig
|
|
476
|
+
|
|
477
|
+
require_menu path
|
|
478
|
+
|
|
479
|
+
View.flash "- #{file_existed ? 'Updated' : 'Created'} ~/menus/#{root}.menu", :times=>3
|
|
480
|
+
nil
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
@@loaded_already = {}
|
|
484
|
+
|
|
485
|
+
def self.load_if_changed file
|
|
486
|
+
return :not_found if ! File.exists?(file)
|
|
487
|
+
previous = @@loaded_already[file]
|
|
488
|
+
recent = File.mtime(file)
|
|
489
|
+
|
|
490
|
+
if previous == nil
|
|
491
|
+
# require file
|
|
492
|
+
load file
|
|
493
|
+
@@loaded_already[file] = recent
|
|
494
|
+
return
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
return if recent <= previous
|
|
498
|
+
|
|
499
|
+
load file
|
|
500
|
+
@@loaded_already[file] = recent
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
def self.collapser_launcher
|
|
504
|
+
|
|
505
|
+
line = Line.value
|
|
506
|
+
arrows = line[/<+/].length
|
|
507
|
+
arrows -= 1 if arrows > 1 # Make "<<" go back just 1, etc.
|
|
508
|
+
|
|
509
|
+
# line.sub! /(^ +)= /, "\\1< " # Temporarily get "=" to work too
|
|
510
|
+
line = Line.without_label :line=>line
|
|
511
|
+
|
|
512
|
+
skip = line.empty? && arrows - 1
|
|
513
|
+
|
|
514
|
+
Line.sub! /^( +)<+ .+/, "\\1- " # Delete after bullet to prepare for loop
|
|
515
|
+
|
|
516
|
+
arrows.times do |i|
|
|
517
|
+
|
|
518
|
+
# If no items left on current line, jump to parent and delete
|
|
519
|
+
if Line =~ /^[ +-]+$/
|
|
520
|
+
Tree.to_parent
|
|
521
|
+
Tree.kill_under
|
|
522
|
+
Move.to_end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
unless i == skip # Remove last item, or after bullet if no items
|
|
526
|
+
Line.sub!(/\/[^\/]+\/$/, '/') || Line.sub!(/^([ @+-]*).*/, "\\1")
|
|
527
|
+
end
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
if Line.indent.blank?
|
|
531
|
+
line.sub! /^@ ?/, ''
|
|
532
|
+
Line.sub! /^@ ?/, ''
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
Line << line unless skip
|
|
536
|
+
Launcher.launch
|
|
537
|
+
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def self.root_collapser_launcher
|
|
541
|
+
|
|
542
|
+
View.cursor
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
# Grab line
|
|
546
|
+
line = Line.value
|
|
547
|
+
|
|
548
|
+
arrows = line[/<+/].length
|
|
549
|
+
|
|
550
|
+
line.sub!(/ *<+@ /, '')
|
|
551
|
+
|
|
552
|
+
# Go up to root, and kill under
|
|
553
|
+
arrows.times { Tree.to_root }
|
|
554
|
+
Tree.kill_under
|
|
555
|
+
|
|
556
|
+
# Insert line, and launch
|
|
557
|
+
old = Line.delete :leave_linebreak
|
|
558
|
+
old.sub! /^( *).+/, "\\1"
|
|
559
|
+
old << "@" if old =~ /^ / # If any indent, @ is needed
|
|
560
|
+
View << "#{old}#{line}"
|
|
561
|
+
|
|
562
|
+
Launcher.launch
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
def self.replacer_launcher
|
|
566
|
+
Line.sub! /^( +)<+= /, "\\1+ "
|
|
567
|
+
|
|
568
|
+
# Run in place, grab output, then move higher and show output
|
|
569
|
+
|
|
570
|
+
orig = View.line
|
|
571
|
+
Launcher.launch :no_search=>1
|
|
572
|
+
|
|
573
|
+
# If didn't move line, assume it had no output, and it's collapse things itself
|
|
574
|
+
return if orig == View.line
|
|
575
|
+
|
|
576
|
+
# If it inserted something
|
|
577
|
+
|
|
578
|
+
output = Tree.siblings :everything=>1
|
|
579
|
+
|
|
580
|
+
# return
|
|
581
|
+
|
|
582
|
+
# Shouldn't this be looping like self.collapser_launcher ?
|
|
583
|
+
Tree.to_parent
|
|
584
|
+
Tree.to_parent
|
|
585
|
+
Tree.kill_under :no_plus=>1
|
|
586
|
+
Tree << output
|
|
587
|
+
|
|
588
|
+
# TODO: do search now, after insterted?
|
|
589
|
+
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
def self.menu_to_hash txt
|
|
593
|
+
txt = File.read txt if txt =~ /\A\/.+\z/ # If 1 line and starts with slash, read file
|
|
594
|
+
|
|
595
|
+
txt.gsub(/^\| /, '').split("\n").inject({}) do |o, txt|
|
|
596
|
+
txt = txt.split(/ : /)
|
|
597
|
+
o[txt[0]] = txt[1]
|
|
598
|
+
o
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
# def self.config txt, *args
|
|
604
|
+
|
|
605
|
+
# # TODO: implement
|
|
606
|
+
# # Args look like sample invocation below
|
|
607
|
+
# # If not there, create it first, using supplied default
|
|
608
|
+
# # Insert quoted file contents to be edited
|
|
609
|
+
|
|
610
|
+
# # Sample invocation
|
|
611
|
+
# # Menu.config "
|
|
612
|
+
# # - @ ~/xiki_config/browser.notes
|
|
613
|
+
# # | - default browser:
|
|
614
|
+
# # | - Firefox
|
|
615
|
+
# # | - others:
|
|
616
|
+
# # | - Safari
|
|
617
|
+
# # | - Chrome
|
|
618
|
+
# # ", *args
|
|
619
|
+
|
|
620
|
+
# "TODO"
|
|
621
|
+
# end
|
|
622
|
+
|
|
623
|
+
# Moves item to root of tree (replacing tree), then launches.
|
|
624
|
+
def self.do_as_menu
|
|
625
|
+
line = Line.value
|
|
626
|
+
|
|
627
|
+
# If on ^@... line and there's child on next line...
|
|
628
|
+
|
|
629
|
+
on_subtree = line =~ /^[ +-]*@/ && Tree.has_child?
|
|
630
|
+
|
|
631
|
+
txt = on_subtree ? Tree.subtree.unindent.sub(/^[ @+-]+/, '') : Tree.path.last
|
|
632
|
+
|
|
633
|
+
Keys.prefix_u ? Tree.to_root(:highest=>1) : Tree.to_root
|
|
634
|
+
Tree.kill_under
|
|
635
|
+
|
|
636
|
+
Line.sub! /^([ @]*).+/, "\\1#{txt}"
|
|
637
|
+
|
|
638
|
+
return if on_subtree
|
|
639
|
+
|
|
640
|
+
# replace line with menu
|
|
641
|
+
|
|
642
|
+
Launcher.launch
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
# The following 3 methods are for the menu bar
|
|
647
|
+
# - a different use of the "Menu" class
|
|
648
|
+
# TODO move them into menu_bar.rb ?
|
|
649
|
+
|
|
650
|
+
def self.add_menu *name
|
|
651
|
+
menu_spaces = name.join(' ').downcase
|
|
652
|
+
menu_dashes = name.join('-').downcase
|
|
653
|
+
name = name[-1]
|
|
654
|
+
|
|
655
|
+
lisp = %Q<
|
|
656
|
+
(define-key global-map
|
|
657
|
+
[menu-bar #{menu_spaces}]
|
|
658
|
+
(cons "#{name}" (make-sparse-keymap "#{menu_dashes}")))
|
|
659
|
+
>
|
|
660
|
+
$el.el4r_lisp_eval lisp
|
|
661
|
+
|
|
662
|
+
menu = $el.elvar.menu_bar_final_items.to_a
|
|
663
|
+
$el.elvar.menu_bar_final_items = menu.push(name.downcase.to_sym)
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
def self.add_item menu, name, function
|
|
667
|
+
|
|
668
|
+
menu_spaces = menu.join(' ').downcase
|
|
669
|
+
lisp = "
|
|
670
|
+
(define-key global-map
|
|
671
|
+
[menu-bar #{menu_spaces} #{function}]
|
|
672
|
+
'(\"#{name}\" . #{function}))
|
|
673
|
+
"
|
|
674
|
+
$el.el4r_lisp_eval lisp
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
ROOT_MENU = 'Keys'
|
|
678
|
+
|
|
679
|
+
def self.init
|
|
680
|
+
|
|
681
|
+
return if ! $el
|
|
682
|
+
|
|
683
|
+
Mode.define(:menu, ".menu") do
|
|
684
|
+
Notes.mode
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
add_menu ROOT_MENU
|
|
688
|
+
|
|
689
|
+
menus = [
|
|
690
|
+
[ROOT_MENU, 'To'],
|
|
691
|
+
[ROOT_MENU, 'Open'],
|
|
692
|
+
[ROOT_MENU, 'Layout'],
|
|
693
|
+
[ROOT_MENU, 'As'],
|
|
694
|
+
[ROOT_MENU, 'Enter'],
|
|
695
|
+
[ROOT_MENU, 'Do'],
|
|
696
|
+
[ROOT_MENU, 'Search']
|
|
697
|
+
]
|
|
698
|
+
menus.reverse.each do |tuple|
|
|
699
|
+
add_menu tuple[0], tuple[1]
|
|
700
|
+
end
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
Menu.init # Define mode
|
|
707
|
+
|
|
708
|
+
|