xiki 0.5.0a

Sign up to get free protection for your applications and to get access to all the features.
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