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.
Files changed (252) hide show
  1. data/Gemfile +11 -0
  2. data/LICENSE +22 -0
  3. data/README.markdown +83 -0
  4. data/Rakefile +8 -0
  5. data/bin/xiki +46 -0
  6. data/etc/command/xiki_command.rb +203 -0
  7. data/etc/command/xiki_process.rb +52 -0
  8. data/etc/command/xiki_wrapper +2 -0
  9. data/etc/js/menu1.js +55 -0
  10. data/etc/js/xiki.js +259 -0
  11. data/etc/logo.png +0 -0
  12. data/etc/presentations/bootstrap.deck +5 -0
  13. data/etc/presentations/databases.deck +41 -0
  14. data/etc/presentations/diffs.deck +23 -0
  15. data/etc/presentations/documentation.deck +14 -0
  16. data/etc/presentations/effects.deck +5 -0
  17. data/etc/presentations/face.deck +297 -0
  18. data/etc/presentations/files.deck +79 -0
  19. data/etc/presentations/icons.deck +22 -0
  20. data/etc/presentations/images.deck +24 -0
  21. data/etc/presentations/key_shortcuts.deck +16 -0
  22. data/etc/presentations/macros.deck +18 -0
  23. data/etc/presentations/menu_classes.deck +44 -0
  24. data/etc/presentations/menu_directories.deck +30 -0
  25. data/etc/presentations/notes.deck +19 -0
  26. data/etc/presentations/other_languages.deck +55 -0
  27. data/etc/presentations/other_wiki_syntaxes.deck +4 -0
  28. data/etc/presentations/piano.deck +5 -0
  29. data/etc/presentations/potential/diffs.deck +38 -0
  30. data/etc/presentations/potential/evolution.deck +18 -0
  31. data/etc/presentations/potential/intro.deck +711 -0
  32. data/etc/presentations/potential/intro1.deck +711 -0
  33. data/etc/presentations/potential/intro2.deck +97 -0
  34. data/etc/presentations/potential/make_mysql_menu.deck +36 -0
  35. data/etc/presentations/potential/ruby_development.deck +17 -0
  36. data/etc/presentations/potential/ui_prototyping.deck +50 -0
  37. data/etc/presentations/potential/web_dev.deck +4 -0
  38. data/etc/presentations/potential/web_development.deck +10 -0
  39. data/etc/presentations/potential/wiki.deck +45 -0
  40. data/etc/presentations/presentations.deck +24 -0
  41. data/etc/presentations/rails_development.deck +29 -0
  42. data/etc/presentations/search_key_shortcuts.deck +37 -0
  43. data/etc/presentations/simplest_possible_ui.deck +37 -0
  44. data/etc/presentations/svg.deck +5 -0
  45. data/etc/presentations/testing.deck +28 -0
  46. data/etc/presentations/the_end.deck +13 -0
  47. data/etc/presentations/type_something_and_double_click.deck +57 -0
  48. data/etc/presentations/type_the_acronym.deck +144 -0
  49. data/etc/presentations/web_browser.deck +56 -0
  50. data/etc/presentations/xiki_command.deck +20 -0
  51. data/etc/presentations/xiki_url.deck +14 -0
  52. data/etc/shark.icns +0 -0
  53. data/etc/shark_script.icns +0 -0
  54. data/etc/snippets/html.notes +7 -0
  55. data/etc/snippets/notes.notes +20 -0
  56. data/etc/snippets/rb.notes +38 -0
  57. data/etc/templates/menu_template.menu +2 -0
  58. data/etc/templates/menu_template.rb +8 -0
  59. data/etc/templates/template.rb +5 -0
  60. data/etc/themes/Dark_Metal.notes +28 -0
  61. data/etc/themes/Orange_Path.notes +15 -0
  62. data/etc/themes/Shiny_Blue.notes +27 -0
  63. data/etc/themes/Shiny_Green.notes +27 -0
  64. data/etc/wrappers/wrapper.js +17 -0
  65. data/etc/wrappers/wrapper.py +20 -0
  66. data/etc/wrappers/wrapper.rb +25 -0
  67. data/lib/block.rb +72 -0
  68. data/lib/bookmarks.rb +352 -0
  69. data/lib/buffers.rb +170 -0
  70. data/lib/clipboard.rb +333 -0
  71. data/lib/code.rb +860 -0
  72. data/lib/code_tree.rb +476 -0
  73. data/lib/color.rb +274 -0
  74. data/lib/console.rb +557 -0
  75. data/lib/control_lock.rb +9 -0
  76. data/lib/control_tab.rb +176 -0
  77. data/lib/core_ext.rb +31 -0
  78. data/lib/cursor.rb +111 -0
  79. data/lib/deletes.rb +65 -0
  80. data/lib/diff_log.rb +297 -0
  81. data/lib/effects.rb +145 -0
  82. data/lib/environment.rb +5 -0
  83. data/lib/file_tree.rb +1875 -0
  84. data/lib/files.rb +334 -0
  85. data/lib/hide.rb +259 -0
  86. data/lib/history.rb +286 -0
  87. data/lib/image.rb +51 -0
  88. data/lib/incrementer.rb +15 -0
  89. data/lib/insert.rb +7 -0
  90. data/lib/irc.rb +22 -0
  91. data/lib/key_bindings.rb +658 -0
  92. data/lib/keys.rb +754 -0
  93. data/lib/launcher.rb +1351 -0
  94. data/lib/line.rb +429 -0
  95. data/lib/links.rb +6 -0
  96. data/lib/location.rb +175 -0
  97. data/lib/macros.rb +48 -0
  98. data/lib/man.rb +19 -0
  99. data/lib/menu.rb +708 -0
  100. data/lib/merb.rb +259 -0
  101. data/lib/message.rb +5 -0
  102. data/lib/meths.rb +56 -0
  103. data/lib/mode.rb +34 -0
  104. data/lib/move.rb +248 -0
  105. data/lib/notes.rb +1000 -0
  106. data/lib/numbers.rb +45 -0
  107. data/lib/ol.rb +203 -0
  108. data/lib/ol_helper.rb +44 -0
  109. data/lib/overlay.rb +167 -0
  110. data/lib/pause_means_space.rb +68 -0
  111. data/lib/php.rb +22 -0
  112. data/lib/projects.rb +21 -0
  113. data/lib/relinquish_exception.rb +2 -0
  114. data/lib/remote.rb +206 -0
  115. data/lib/requirer.rb +46 -0
  116. data/lib/rest_tree.rb +108 -0
  117. data/lib/ruby.rb +57 -0
  118. data/lib/ruby_console.rb +165 -0
  119. data/lib/search.rb +1572 -0
  120. data/lib/search_term.rb +40 -0
  121. data/lib/snippet.rb +68 -0
  122. data/lib/specs.rb +229 -0
  123. data/lib/styles.rb +274 -0
  124. data/lib/svn.rb +682 -0
  125. data/lib/text_util.rb +110 -0
  126. data/lib/tree.rb +1871 -0
  127. data/lib/tree_cursor.rb +87 -0
  128. data/lib/trouble_shooting.rb +27 -0
  129. data/lib/url_tree.rb +11 -0
  130. data/lib/view.rb +1474 -0
  131. data/lib/window.rb +133 -0
  132. data/lib/xiki.rb +404 -0
  133. data/menus/accounts.rb +5 -0
  134. data/menus/address_book.rb +21 -0
  135. data/menus/agenda.rb +28 -0
  136. data/menus/all.rb +5 -0
  137. data/menus/amazon.rb +16 -0
  138. data/menus/app.rb +16 -0
  139. data/menus/applescript.rb +46 -0
  140. data/menus/as.rb +15 -0
  141. data/menus/bookmarklet.rb +63 -0
  142. data/menus/bootstrap.rb +568 -0
  143. data/menus/browse.rb +13 -0
  144. data/menus/browser.rb +78 -0
  145. data/menus/cassandra_db.rb +36 -0
  146. data/menus/chmod.rb +27 -0
  147. data/menus/classes.rb +5 -0
  148. data/menus/coffee_script.rb +35 -0
  149. data/menus/computer.rb +24 -0
  150. data/menus/contacts.rb +5 -0
  151. data/menus/cookies.rb +25 -0
  152. data/menus/couch.rb +184 -0
  153. data/menus/crop.rb +45 -0
  154. data/menus/css.rb +55 -0
  155. data/menus/current.rb +5 -0
  156. data/menus/db.rb +12 -0
  157. data/menus/deck.rb +219 -0
  158. data/menus/dictionary.rb +9 -0
  159. data/menus/dir.rb +8 -0
  160. data/menus/disk.rb +5 -0
  161. data/menus/do.rb +13 -0
  162. data/menus/docs.rb +58 -0
  163. data/menus/dotsies.rb +107 -0
  164. data/menus/edited.rb +18 -0
  165. data/menus/emacs.rb +17 -0
  166. data/menus/enter.rb +13 -0
  167. data/menus/eval.rb +17 -0
  168. data/menus/executable.rb +16 -0
  169. data/menus/filter.rb +46 -0
  170. data/menus/firefox.rb +607 -0
  171. data/menus/foo.rb +30 -0
  172. data/menus/french.rb +7 -0
  173. data/menus/git.rb +185 -0
  174. data/menus/gito.rb +785 -0
  175. data/menus/google.rb +35 -0
  176. data/menus/google_images.rb +11 -0
  177. data/menus/google_patents.rb +10 -0
  178. data/menus/gutenberg.rb +13 -0
  179. data/menus/head.rb +10 -0
  180. data/menus/headings.rb +39 -0
  181. data/menus/html.rb +61 -0
  182. data/menus/icon.rb +40 -0
  183. data/menus/images.menu +2 -0
  184. data/menus/img.rb +15 -0
  185. data/menus/info.rb +9 -0
  186. data/menus/ip.rb +10 -0
  187. data/menus/iterm.rb +36 -0
  188. data/menus/itunes.rb +78 -0
  189. data/menus/javascript.rb +74 -0
  190. data/menus/layout.rb +18 -0
  191. data/menus/local_storage.rb +67 -0
  192. data/menus/ls.rb +19 -0
  193. data/menus/mac.rb +87 -0
  194. data/menus/maps.rb +18 -0
  195. data/menus/matches.rb +18 -0
  196. data/menus/memcache.rb +117 -0
  197. data/menus/mkdir.rb +23 -0
  198. data/menus/mongo.rb +83 -0
  199. data/menus/mysql.rb +294 -0
  200. data/menus/node.rb +88 -0
  201. data/menus/open.rb +19 -0
  202. data/menus/outline.rb +24 -0
  203. data/menus/piano.rb +746 -0
  204. data/menus/postgres.rb +34 -0
  205. data/menus/pre.rb +5 -0
  206. data/menus/python.rb +39 -0
  207. data/menus/rails.rb +160 -0
  208. data/menus/rake.rb +12 -0
  209. data/menus/redmine.rb +168 -0
  210. data/menus/riak_tree.rb +204 -0
  211. data/menus/rss.rb +15 -0
  212. data/menus/safari.rb +11 -0
  213. data/menus/sass.rb +15 -0
  214. data/menus/say.rb +6 -0
  215. data/menus/scale.rb +49 -0
  216. data/menus/serve.rb +78 -0
  217. data/menus/shuffle.rb +24 -0
  218. data/menus/spanish.rb +7 -0
  219. data/menus/standalone.rb +57 -0
  220. data/menus/tail.rb +41 -0
  221. data/menus/technologies.rb +19 -0
  222. data/menus/themes.rb +32 -0
  223. data/menus/thesaurus.rb +13 -0
  224. data/menus/to.rb +24 -0
  225. data/menus/twitter.rb +57 -0
  226. data/menus/wikipedia.rb +34 -0
  227. data/menus/words.rb +11 -0
  228. data/spec/code_tree_spec.rb +59 -0
  229. data/spec/diff_log_spec.rb +40 -0
  230. data/spec/file_tree_spec.rb +102 -0
  231. data/spec/keys_spec.rb +24 -0
  232. data/spec/line_spec.rb +68 -0
  233. data/spec/menu_spec.rb +50 -0
  234. data/spec/ol_spec.rb +98 -0
  235. data/spec/remote_spec.rb +43 -0
  236. data/spec/search_spec.rb +162 -0
  237. data/spec/text_util_spec.rb +119 -0
  238. data/spec/tree_cursor_spec.rb +91 -0
  239. data/spec/tree_spec.rb +955 -0
  240. data/tests/console_test.rb +11 -0
  241. data/tests/couch_db_test.rb +12 -0
  242. data/tests/diff_log_test.rb +43 -0
  243. data/tests/el_mixin.rb +16 -0
  244. data/tests/git_test.rb +95 -0
  245. data/tests/keys_test.rb +19 -0
  246. data/tests/line_test.rb +38 -0
  247. data/tests/merb_test.rb +11 -0
  248. data/tests/redmine_test.rb +50 -0
  249. data/tests/remote_test.rb +31 -0
  250. data/tests/rest_tree_test.rb +70 -0
  251. data/xiki.gemspec +37 -0
  252. metadata +332 -0
@@ -0,0 +1,68 @@
1
+ require 'keys'
2
+
3
+ class PauseMeansSpace
4
+
5
+ def self.go
6
+ Cursor.remember :before_q
7
+ Cursor.green
8
+
9
+ while(inserted = insert_until_pause)
10
+ next if inserted == 127
11
+ if inserted == "."
12
+ $el.delete_backward_char 2; insert ". "
13
+ next
14
+
15
+ end
16
+ insert " "
17
+ end
18
+ $el.delete_backward_char 1
19
+ $el.message "Typing finished"
20
+
21
+ Cursor.restore :before_q
22
+ # TODO print ---- if enter
23
+ end
24
+
25
+ def self.insert_until_pause
26
+ # Get first char and insert
27
+ c = $el.read_char("insert text (pause means space): ")
28
+
29
+ # Exit if they pressed enter
30
+ return false if c == 13
31
+
32
+ # Delete if they pressed delete
33
+ if c == 127
34
+ $el.backward_kill_word 1
35
+ return 127
36
+ end
37
+
38
+ inserted = "#{c.chr}"
39
+ insert c.chr
40
+
41
+ o = $el.make_overlay $el.point, $el.point - 1
42
+
43
+ # TODO use different face - purple?
44
+
45
+ $el.overlay_put o, :face, :control_lock_found
46
+ # While no pause, insert more chars
47
+ while(c = read_char("insert text (pause means space): ", nil, 0.24))
48
+ $el.delete_overlay o
49
+
50
+ # Exit if they pressed enter
51
+ return false if c == 13
52
+ inserted += c.chr
53
+ insert c.chr
54
+
55
+ o = $el.make_overlay $el.point, $el.point - inserted.size
56
+ $el.overlay_put o, :face, :control_lock_found
57
+ end
58
+ $el.delete_overlay o
59
+
60
+ # User didn't press enter
61
+ return inserted
62
+
63
+ end
64
+ def self.keys
65
+ Keys.set("C-S-q", "PauseMeansSpace.go")
66
+ end
67
+
68
+ end
@@ -0,0 +1,22 @@
1
+ class Php
2
+ def self.run
3
+ # Get block contents
4
+ txt, left, right = View.txt_per_prefix #:prefix=>Keys.prefix
5
+
6
+ result = self.run_internal txt
7
+ # Insert result at end of block
8
+ orig = Location.new
9
+ View.cursor = right
10
+ Line.to_left
11
+ View.insert result.gsub(/^/, ' ')+"\n"
12
+ orig.go
13
+ end
14
+
15
+ def self.run_internal txt
16
+ # Write to temp file
17
+ File.open("/tmp/tmp.php", "w") { |f| f << "<?\n#{txt}\n?>\n" }
18
+ # Call js
19
+ Console.run "php -f /tmp/tmp.php", :sync=>true
20
+ end
21
+
22
+ end
@@ -0,0 +1,21 @@
1
+ class Projects
2
+ def self.menu
3
+ "
4
+ - This will never be called, because of projects.menu...
5
+ - Think again of ways for .menu and .rb to work together creating menus
6
+ - api/
7
+ "
8
+ end
9
+
10
+ def self.current
11
+ # If parent is dir, return it, else return first project
12
+ dir = FileTree.handles?(Xiki.trunk[-2]) ? "#{Dir.pwd}/" : self.default_project
13
+ end
14
+
15
+ def self.default_project
16
+ txt = File.read(File.expand_path "~/menus/projects.menu") rescue nil
17
+ return nil if ! txt
18
+
19
+ Line.without_label(:line=>txt[/.+/])
20
+ end
21
+ end
@@ -0,0 +1,2 @@
1
+ class RelinquishException < RuntimeError
2
+ end
@@ -0,0 +1,206 @@
1
+ gem 'net-ssh'
2
+ require 'net/ssh'
3
+ require 'net/sftp'
4
+ require 'timeout'
5
+ require 'ol'
6
+
7
+ class Remote
8
+
9
+ @@temp_dir = "/tmp/remote_rb"
10
+
11
+ @@connections = {}
12
+
13
+ def self.menu
14
+ "
15
+ - docs/
16
+ > Summary
17
+ | You can browse files and run commands on remote servers.
18
+ @ /user@foo.com/tmp/
19
+ << see) @servers/
20
+ "
21
+ end
22
+
23
+ # Called when dir or file is launched
24
+ def self.file_contents whole_path
25
+ user, server, port, path = self.split_root(whole_path)
26
+ connection = self.connection whole_path
27
+ connection.sftp.download!(path)
28
+ end
29
+
30
+ def self.dir root, *path_append
31
+
32
+ connection = self.connection root
33
+
34
+ user, server, port, path = self.split_root(root)
35
+
36
+ # Add slash to path if none there
37
+ path << "/" unless path =~ /\/$/
38
+
39
+ path_passed = path_append.size > 0
40
+
41
+ if path_passed # If anything in array
42
+ path << "#{path_append.join('')}" # append to path
43
+ path.sub! /^\/\//, '/'
44
+ end
45
+
46
+ timeout(15) do
47
+ if path =~ /\/$/ # If a dir
48
+ out = connection.exec!("ls -pa #{path}")
49
+ out ||= ""
50
+ out = out.grep(/^[^#]+$/).join("") # Weed out #...#
51
+ out.gsub!(/@/, '/') # Change @ to /
52
+
53
+ # Get rid of . and ..
54
+ out = out.split("\n").select{|o| o !~ /^\.+\/$/}.join("\n")+"\n"
55
+ self.sort(out)
56
+
57
+ else # If a file
58
+
59
+ Dir.mkdir @@temp_dir unless File.exists? @@temp_dir
60
+ local_path = self.calculate_local_path path, server
61
+
62
+ was_open = Files.open? local_path
63
+
64
+ # Download if not open already
65
+ unless was_open
66
+ begin
67
+ connection.sftp.download!(path, local_path)
68
+ rescue Exception=>e
69
+ # If doesn't exist, we'll just create
70
+ end
71
+ end
72
+
73
+ View.to_after_bar
74
+ View.open local_path
75
+
76
+ # TODO: save root path as var in buffer
77
+ $el.make_local_variable :remote_rb_server_root
78
+ server_root = "/#{user}@#{server}#{port ? ":#{port}" : ""}/"
79
+ $el.elvar.remote_rb_server_root = server_root
80
+
81
+ # TODO save timestamp in buffer var
82
+ # - Use it to determine whether file changed when saving
83
+
84
+ end
85
+ end
86
+ end
87
+
88
+ def self.command root #, *path_append
89
+
90
+ the_command = root[-1][/\$ ?(.+)/, 1]
91
+
92
+ # Pull off command
93
+ while(root.last =~ /^\$/) do # Remove all !foo lines from root
94
+ root.pop
95
+ end
96
+ root = root.join('')
97
+
98
+ connection = self.connection root
99
+
100
+ user, server, port, path = self.split_root(root)
101
+
102
+ path << "/" unless path =~ /\/$/ # Add slash to path if none there
103
+
104
+ timeout(6) do
105
+ out = connection.exec!("cd \"#{path}\" && #{the_command}")
106
+ # out = connection.exec!("cd \"#{path}\"; #{the_command}")
107
+ out ||= ""
108
+
109
+ Tree.under out, :escape=>'| ', :no_slash=>1
110
+ end
111
+ end
112
+
113
+ def self.connections
114
+ @@connections
115
+ end
116
+
117
+ def self.connection root
118
+ user, server, port, path = self.split_root root
119
+ address = "#{user}@#{server}:#{port}"
120
+ @@connections[address] ||= self.new_connection user, server, port.to_i
121
+ @@connections[address]
122
+ end
123
+
124
+ def self.new_connection user, server, port
125
+ begin
126
+ timeout(6) do
127
+ Net::SSH.start(server, user, :port => port.to_i, :paranoid => false)
128
+ end
129
+ rescue Exception => e
130
+ raise "Timed out: #{e.message}"
131
+ end
132
+ end
133
+
134
+
135
+ def self.split_root root # Splits name@server:port/path
136
+ root = root.dup # Append / at end if no / exists
137
+ root << "/" unless root =~ /\/$/
138
+
139
+ user, server_port, path = root.match(/^(.+?)@(.+?)(\/.*?)\/?$/)[1..3]
140
+
141
+ if(server_port =~ /(.+?):(.+)/)
142
+ server, port = $1, $2
143
+ else
144
+ server, port = server_port, "22"
145
+ end
146
+
147
+ user.sub! /^\//, ''
148
+ [user, server, port, path]
149
+ end
150
+
151
+ def self.sort lines
152
+ l = lines.split("\n")
153
+ l.sort!{|a,b| a.sub(/(.+)\//, "\\1") <=> b.sub(/(.+)\//, "\\1")}
154
+ end
155
+
156
+ def self.remote_buffer_name(server, path)
157
+ dir, file = path.match(/(.+\/)(.+)/)[1..2]
158
+ "*remote #{file} (#{server}:#{dir})"
159
+ end
160
+
161
+ def self.save_file
162
+ local_path = View.file
163
+ # Error out if not in right place
164
+ if local_path !~ /^#{@@temp_dir}/
165
+ View.beep
166
+ return View.message("This isn't a file the Remote code_tree retrieved")
167
+ end
168
+
169
+ # Save if modified
170
+ $el.save_buffer if $el.buffer_modified_p
171
+
172
+ remote_path = $el.elvar.remote_rb_server_root
173
+
174
+
175
+ # Convert to path
176
+ remote_path = self.calculate_remote_path local_path
177
+ begin # Do save
178
+ connection = self.connection $el.elvar.remote_rb_server_root
179
+ connection.sftp.upload!(local_path, remote_path)
180
+ View.message "successfully saved remotely!"
181
+ rescue Exception => e
182
+ View.message "- error: #{e.message}"
183
+ end
184
+
185
+ end
186
+
187
+ def self.calculate_local_path path, server
188
+ "#{@@temp_dir}/#{server},#{path.gsub('/', ',')[1..-1]}"
189
+ end
190
+
191
+ def self.calculate_remote_path path
192
+ path.gsub(/^#{@@temp_dir}\/.+?,/, '/').gsub(',', '/')
193
+ end
194
+
195
+ def self.init
196
+ # TODO remove this
197
+ end
198
+
199
+ end
200
+
201
+ Keys.do_as_remote do
202
+ Remote.save_file
203
+ end
204
+
205
+
206
+ # Remote.init
@@ -0,0 +1,46 @@
1
+ require 'core_ext'
2
+
3
+ class Requirer
4
+ def self.show txt
5
+ if ! $el
6
+ return if txt !~ /(^Xiki requires|exception:$)/
7
+ return puts "#{txt}"
8
+ end
9
+
10
+ $el.switch_to_buffer "Issues Loading Xiki"
11
+ $el.insert txt
12
+ $el.bury_buffer unless $el.buffer_substring($el.point_min, $el.point_max) =~ /(^Xiki requires|exception:$)/
13
+ end
14
+
15
+ def self.require_gem name, options={}
16
+ begin
17
+ gem name
18
+ require options[:name2] || name
19
+ rescue Exception=>e
20
+ self.show "Xiki #{options[:optional] ? 'optionally uses' : 'requires'} the '#{name}' gem.\n% sudo gem install #{name}\n\n"
21
+ raise e if options[:raise]
22
+ end
23
+ end
24
+
25
+ def self.extract_gem_from_exception txt
26
+ txt = txt[/-- (.*)/, 1] || txt[/RubyGem (.*)/, 1] || txt[/Could not find (.+?) /, 1] || txt
27
+
28
+ return nil if ! txt
29
+
30
+ txt.sub!(/\(.+/, '')
31
+ txt.strip
32
+ end
33
+
34
+ def self.require_classes files
35
+ files.each do |l|
36
+ begin
37
+ require l
38
+ rescue LoadError => e
39
+ self.show "#{e.to_s}\n"
40
+ gem_name = self.extract_gem_from_exception e.to_s
41
+ self.show "_Xiki requires the '#{gem_name}' gem.\n% sudo gem install #{gem_name}\n\n"
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,108 @@
1
+ class RestTree
2
+
3
+ def self.launch_inner path, children
4
+
5
+ self.remove_before_root path
6
+
7
+ # Extract verbs from root and current line
8
+ root_verb = self.extract_root_verb path
9
+ verb = self.extract_verb path.last
10
+
11
+ body = nil
12
+ # If line had verb
13
+ if verb
14
+ if ! path.last.empty? # If line isn't blank, use as body
15
+ body = path.last
16
+ path.pop
17
+ else
18
+ # Remove quoted children
19
+ children = children ? children.select{|e| e !~ /^\|/} : nil
20
+ if children and children.any? # If line blank and has children, use them as body
21
+ body = children.map{|i| "#{i.sub(/^\s+/, '')}\n"}.join('')
22
+ end
23
+ end
24
+ end
25
+
26
+ verb ||= root_verb
27
+
28
+ [verb || root_verb, path.join(''), body]
29
+ end
30
+
31
+ def self.launch options={}
32
+
33
+ Tree.plus_to_minus_maybe
34
+ verb, url, body = self.launch_inner options[:path], Tree.children
35
+ url = "http://#{url}" unless url =~ %r"http://"
36
+
37
+ result = self.request verb, url, body
38
+ result = "#{result}\n" unless result =~ /\n\z/
39
+ result.gsub! "\cm", ''
40
+
41
+ # Quote unless begins with "|"
42
+ result.gsub! /^/, "| "
43
+ result.gsub! /^\| ( *[-+] )/, "\\1"
44
+
45
+ Tree.<< result, :escape=>'', :no_slash=>1
46
+
47
+ nil
48
+ end
49
+
50
+ # Tell Launcher whether we're in a rest tree
51
+ def self.handles? list
52
+ list.index{|i| i =~ /^(GET|PUT|POST|DELETE)/}
53
+ end
54
+
55
+ # Pull out root
56
+ def self.extract_root_verb path
57
+ path.first.sub! /^ *(GET|PUT|POST|DELETE) /, "\\2"
58
+ $1
59
+ end
60
+
61
+ # Pull out verb
62
+ def self.extract_verb line
63
+ line.sub! /^ *(GET|PUT|POST|DELETE) ?(.*)/, "\\2"
64
+ $1
65
+ end
66
+
67
+ def self.remove_before_root list
68
+ # Delete from beginning until root is found
69
+ while list.first !~ /^ *(GET|PUT|POST|DELETE) /
70
+ break unless list.any?
71
+ list.shift
72
+ end
73
+ list
74
+ end
75
+
76
+ def self.request verb, url, body=nil
77
+ begin
78
+ net_http_class = Net::HTTP.const_get(verb.capitalize)
79
+ url.gsub!('"', '%22')
80
+ uri = URI.parse(url)
81
+
82
+ req = net_http_class.new(uri.request_uri)
83
+ req.body = body
84
+ res = Net::HTTP.start(uri.host, uri.port) {|http|
85
+ http.request(req)
86
+ }
87
+ (res.code == '200' ? '' : "#{res.code} ") + res.body
88
+ rescue Exception=>e
89
+ e.message
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+
96
+
97
+ Launcher.add(/^.*(- )?GET \/.+/) do
98
+ line = Line.without_label
99
+
100
+ regex, url = /GET \/(.+?)\/ (.+)/.match(line)[1..2]
101
+ url = "http://#{url}" unless url =~ %r"http://"
102
+ url.gsub! ' ', '+'
103
+
104
+ result = RestTree.request "GET", url
105
+
106
+ result = result.grep(/#{regex}/i).join
107
+ Tree.under result, :no_slash=>1
108
+ end