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,294 @@
1
+ class Mysql
2
+ def self.menu
3
+ "
4
+ - @tables/
5
+ - @dbs/
6
+ - @columns/
7
+ - .setup/
8
+ - .start/
9
+ - .start in background/
10
+ - stop/
11
+ @ $ ps -eo pcpu,pid,user,args | grep mysql | grep -v grep
12
+ @ $ kill _
13
+ - db/
14
+ - .use/
15
+ - .create/
16
+ - .drop/
17
+ - table/
18
+ - .create/
19
+ - .drop/
20
+ - .install/
21
+ - config/
22
+ > Main config file
23
+ @ /etc/my.cnf
24
+
25
+ > Example config files
26
+ @ /usr/local/Cellar/mysql/5.5.25/support-files/
27
+ - **cnf/
28
+ - misc commands/
29
+ > Drop db
30
+ @ % mysqladmin -u root drop foo
31
+ |
32
+ > Others
33
+ @ technologies/mysql/
34
+ > Or just type some sql here
35
+ | show tables
36
+ "
37
+ end
38
+
39
+ def self.install
40
+ "
41
+ > Installing Mysql
42
+ For now, this just has the mac / homebrew instructions. Fork xiki on github to add docs for other platforms.
43
+
44
+ > Install using homebrew
45
+ - 1. double-click to install) @ % brew install mysql
46
+ - 2. look at the output) and run the commands it tells you to run
47
+
48
+ > More
49
+ See this link for more info on installing:
50
+ @http://www.mysql.com/downloads/mysql/
51
+ "
52
+ end
53
+
54
+ def self.menu_after txt, *args
55
+ return nil if txt
56
+ ENV['no_slash'] = "1"
57
+ Tree.quote self.run(nil, ENV['txt'])
58
+ end
59
+
60
+ def self.default_db db
61
+ @default_db = db
62
+ end
63
+
64
+ def self.start
65
+ Console.run "mysqld", :buffer=>"mysql", :dir=>"/tmp/"
66
+ View.to_buffer "mysql"
67
+ nil
68
+ end
69
+
70
+ def self.start_in_background
71
+ Console.run "mysql.server start"
72
+ end
73
+
74
+ def self.tables *args
75
+ if ! @default_db && ! args[0]
76
+ @default_db = "dev" # Temp
77
+ end
78
+
79
+ self.dbs @default_db, *args
80
+ end
81
+
82
+ def self.dbs db=nil, table=nil, row=nil
83
+
84
+ # If nothing passed, list db's
85
+
86
+ if db.nil?
87
+ txt = Mysql.run('', 'show databases')
88
+ return txt.split[1..-1].map{|o| "#{o}/"}
89
+ end
90
+
91
+ db.sub! /\/$/, '' if db
92
+ table.sub! /\/$/, '' if table
93
+
94
+ # If just db passed, list the tables
95
+
96
+ if table.nil?
97
+ txt = Mysql.run(db, 'show tables')
98
+ if txt.blank?
99
+ @default_db = db
100
+ return "> No tables exist. Create one?\n- @mysql/setup/table/create/"
101
+ end
102
+ return txt.split[1..-1].map{|o| "#{o}/"}
103
+ end
104
+
105
+ # If table passed, so show all records
106
+
107
+ if row.nil?
108
+ # Whole table
109
+
110
+ if ! $el || ! Keys.prefix_u
111
+ sql = "select * from #{table} limit 1000"
112
+ out = self.run(db, sql)
113
+ out = "No records, create one?\n#{self.dummy_row(db, table)}" if out.blank?
114
+ return Tree.quote out #.gsub(/^/, '| ')
115
+ else
116
+ # Pick out just a few fields
117
+ fields = self.run db, "select * from #{table} limit 1"
118
+ fields = fields.sub(/\n.+/m, '').split("\t")
119
+ fields &= ['id', 'slug', 'name', 'partner_id']
120
+ fields = ['*'] if fields.blank?
121
+ sql = "select #{fields.join ', '} from #{table} limit 1000"
122
+ txt = Mysql.run(db, sql)
123
+
124
+ return txt.gsub(/^/, '| ')
125
+ end
126
+ end
127
+
128
+ # Row passed, so save
129
+
130
+ self.save db, table, row
131
+
132
+ ".flash - saved record!"
133
+ end
134
+
135
+ def self.dummy_row db=nil, table=nil
136
+ fields = self.fields db, table
137
+ examples = {
138
+ "int"=>"1",
139
+ "varchar"=>"foo",
140
+ "text"=>"bar bar",
141
+ "date"=>"2011-01-01",
142
+ "time"=>"2011-01-01",
143
+ }
144
+ fields = fields.map{|o| examples[o[1]]}
145
+ fields.join("\t")
146
+ end
147
+
148
+ def self.fields db, table=nil
149
+ txt = self.run db, "desc #{table}"
150
+ txt.sub(/^.+\n/, '').split("\n").map{|o|
151
+ l = o.split("\t")
152
+ [l[0], l[1].sub(/\(.+/, '')] }
153
+ end
154
+
155
+ def self.use kind=nil, db=nil
156
+ # If nothing passed, show db's
157
+
158
+ if db.nil?
159
+ return Mysql.dbs
160
+ end
161
+
162
+ @default_db = db
163
+ ".flash - using db #{db}!"
164
+ end
165
+
166
+ def self.create what, name=nil, columns=nil
167
+ if name.nil?
168
+ View.prompt "Type a name"
169
+ return nil
170
+ end
171
+
172
+ if what == "db"
173
+ txt = Console.run "mysqladmin -u root create #{name}", :sync=>true
174
+ return ".flash - created db!"
175
+ end
176
+
177
+ if columns.nil?
178
+ return "
179
+ | id int not null auto_increment primary key,
180
+ | name VARCHAR(20),
181
+ | details text,
182
+ | datestamp DATE,
183
+ | timestamp TIME,
184
+ "
185
+ end
186
+
187
+ txt = "
188
+ CREATE TABLE #{name} (
189
+ #{ENV['txt'].strip.sub(/,\z/, '')}
190
+ );
191
+ "
192
+
193
+ out = self.run(@default_db, txt)
194
+
195
+ ".flash - created table!"
196
+ end
197
+
198
+ def self.drop what, name=nil
199
+ if name.nil?
200
+ return what == "db" ? Mysql.dbs : Mysql.tables
201
+ end
202
+
203
+ if what == "db"
204
+ txt = Console.run "mysqladmin -u root drop #{name}" #, :sync=>true
205
+ return
206
+ end
207
+
208
+ out = self.run(@default_db, "drop table #{name}")
209
+
210
+ ".flash - dropped table!"
211
+ end
212
+
213
+ def self.run db, sql
214
+ db ||= @default_db
215
+
216
+ File.open("/tmp/tmp.sql", "w") { |f| f << sql }
217
+ out = Console.run "mysql -u root #{db} < /tmp/tmp.sql", :sync=>true
218
+
219
+ raise "> Mysql doesn't appear to be running. Start it?\n- @mysql/setup/start/" if out =~ /^ERROR.+Can't connect/
220
+ raise "| Select a db first:\n- @mysql/setup/db/use/" if out =~ /^ERROR.+: No database selected/
221
+ raise "| Database doesn't exist. Create it?\n- @mysql/setup/db/create/#{$1}/" if out =~ /^ERROR.+Unknown database '(.+)'/
222
+ raise "| Table doesn't exist. Create it?\n- @mysql/setup/table/create/#{$1}/" if out =~ /^ERROR.+Table '.+\.(.+)' doesn't exist/
223
+ raise Tree.quote(out) if out =~ /^ERROR/
224
+ out
225
+ end
226
+
227
+ def self.save db, table, row
228
+ fields = self.fields db, table
229
+ row = row.sub(/^\| /, '').split("\t")
230
+ txt = fields.map{|o| o[0]}.map_with_index{|o, i| "#{o}='#{row[i]}'"}.join(", ")
231
+ self.run db, "INSERT INTO #{table} SET #{txt} ON DUPLICATE KEY UPDATE #{txt}"
232
+ end
233
+
234
+ def self.select statement, row=nil
235
+ table = statement[/from (.+?)( |$)/, 1]
236
+
237
+ # If just statement, run it
238
+
239
+ if row.nil?
240
+ txt = Mysql.run nil, statement.sub(/\/$/, '')
241
+ txt = "No records, create one?\n#{self.dummy_row(@default_db, table)}" if txt.blank?
242
+ return Tree.quote txt
243
+ end
244
+
245
+ # Row passed, so save it
246
+
247
+ ENV['no_slash'] = "1"
248
+ self.save @default_db, table, row
249
+
250
+ ".flash - saved!"
251
+ end
252
+ end
253
+
254
+ Keys.enter_list_mysql { Launcher.insert('- Mysql.dbs/') }
255
+
256
+ Launcher.add /^select \* from($|\/)/ do |path|
257
+ if path !~ /\// # If just "select * from", show all tables
258
+ next Tree.<< Mysql.run(@default_db, 'show tables'), :no_slash=>1
259
+ end
260
+
261
+ # If listed table underneath, collapse to same line
262
+ CodeTree.kill_siblings
263
+ Move.backward
264
+ Deletes.backward
265
+ Deletes.backward
266
+ Move.to_end
267
+
268
+ end
269
+
270
+ Launcher.add(/^select /) do |path|
271
+ args = Menu.split(path)
272
+ Tree.<< Mysql.select(*args), :no_slash=>(args.length > 1)
273
+ end
274
+
275
+ Launcher.add "tables" do |path|
276
+ Mysql.tables *Menu.split(path, :rootless=>1)
277
+ end
278
+
279
+ Launcher.add "dbs" do |path|
280
+ Mysql.dbs *Menu.split(path, :rootless=>1)
281
+ end
282
+
283
+ Launcher.add "rows" do |path|
284
+ args = path.split('/')[1..-1]
285
+ Mysql.tables(*args)
286
+ end
287
+
288
+ Launcher.add "columns" do |path|
289
+ args = path.split('/')[1..-1]
290
+ if args.size > 0
291
+ next Mysql.run(@default_db, "desc #{args[0]}").gsub!(/^/, '| ')
292
+ end
293
+ Mysql.tables(*args)
294
+ end
@@ -0,0 +1,88 @@
1
+ class Node
2
+ def self.menu
3
+ "
4
+ > Pass javascript to eval in node
5
+ | puts(1 + 2)
6
+ - .controller/
7
+ - docs/
8
+ - menu/
9
+ > To try out controller code
10
+ | @node/controller/
11
+ | | function
12
+
13
+ - node/
14
+ > Snippets
15
+ @technologies/node_js/
16
+ "
17
+ end
18
+
19
+ def self.menu_after output, *args
20
+ return output if output
21
+
22
+ if args.empty?
23
+ View.prompt("Enter some code to run in node.js")
24
+ return "| "
25
+ end
26
+
27
+ return self.block if args == ['block']
28
+
29
+ txt = Tree.leaf args[0]
30
+ result = Tree.quote self.run(txt)
31
+
32
+ result
33
+ end
34
+
35
+ def self.wrap_controller code
36
+
37
+ "
38
+ var http = require('http');
39
+ http.createServer(function (req, res) {
40
+
41
+ #{code}
42
+ }).listen(8161, '127.0.0.1');
43
+ console.log('Server running at http://127.0.0.1:8161/');
44
+ ".unindent
45
+
46
+ end
47
+
48
+ def self.controller *args
49
+
50
+ return "
51
+ | // Sample controller code
52
+ | console.log('got a request');
53
+ | res.end('Hello World');
54
+ " if args.empty?
55
+
56
+ code = self.wrap_controller ENV['txt']
57
+ self.run_controller code
58
+ end
59
+
60
+ def self.run_controller code
61
+ File.open("/tmp/controller.js", "w") { |f| f << code }
62
+
63
+ Buffers.delete "node" if View.buffer_open? "node"
64
+
65
+ Console.run "node controller.js", :dir=>"/tmp/", :buffer=>"node"
66
+ $el.sit_for 0.2
67
+ Firefox.url "http://localhost:8161"
68
+ ".flash - showing in browser!"
69
+ end
70
+
71
+ def self.block
72
+ left = Line.right + 1
73
+ ignore, ignore, right = View.block_positions "^>"
74
+
75
+ txt = self.run View.txt(right, left)
76
+ Block >> txt
77
+
78
+ nil
79
+ end
80
+
81
+ def self.run txt
82
+ file = "/tmp/nodejs.js"
83
+ txt = "function puts (txt){ return console.log(txt) }\n\n#{txt}"
84
+ File.open(file, "w") { |f| f << txt }
85
+ Console["node #{file}"]
86
+ end
87
+
88
+ end
@@ -0,0 +1,19 @@
1
+ class Open
2
+ def self.menu
3
+ %`
4
+ > Summary
5
+ | Keys shortcuts that start with "to+" (ctrl-t) such as to+end.
6
+ |
7
+ - frequent/
8
+ > Jumping cursor around
9
+ | open+bookmark: jump to a file
10
+ | open+tree: view a tree of a directory
11
+ | open+current: shows currently open files
12
+ | open+edited: shows recently edited files
13
+ | open+menu: opens view that lets you type a menu (type "-" to see all)
14
+ |
15
+ - others/
16
+ | open+history: shows recently viewed files
17
+ `
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ class Outline
2
+ def self.menu *target
3
+
4
+ if target.blank? # If just filter, show results
5
+ return View.txt.grep(/^> /).select{|o| o !~ /^> ?$/}.join("").gsub(/^/, '| ')
6
+ end
7
+ # Navigated to target text
8
+
9
+ # Grab line manually, because input will have all lines grouped together
10
+ # Should there be an option to have just 1 line passed in?
11
+ # How would it work?
12
+ # Something in the routing?
13
+ target = Line.value
14
+ target.sub! /^ *\| /, ''
15
+
16
+ View.to_highest
17
+ result = Search.forward "^#{target}$"
18
+
19
+ View.recenter_top
20
+ Line.to_beginning
21
+ nil
22
+
23
+ end
24
+ end
@@ -0,0 +1,746 @@
1
+ Requirer.require_gem 'midiator', :optional=>1
2
+
3
+ require "mode"
4
+
5
+ class Piano
6
+
7
+ include MIDIator::Notes rescue nil
8
+ include MIDIator::Drums rescue nil
9
+
10
+ @@midi = nil
11
+ @@velocity = 126
12
+ @@tempo = 120
13
+ @@probability = 100
14
+ @@melodic = 0
15
+ @@melodic_accumulator = []
16
+ @@climb = 0
17
+ @@pentatonic = false
18
+ @@variation = 0
19
+ @@consistency = 0
20
+ @@mode = 0
21
+ @@octave = 0
22
+ @@program = 1
23
+ @@repeat = 1
24
+ @@names = ['Acoustic Grand Piano', 'Bright Acoustic Piano', 'Electric Grand Piano', 'Honky-tonk Piano', 'Electric Piano 1', 'Electric Piano 2', 'Harpsichord', 'Clavinet', 'Celesta', 'Glockenspiel', 'Music Box', 'Vibraphone', 'Marimba', 'Xylophone', 'Tubular Bells', 'Dulcimer', 'Drawbar Organ', 'Percussive Organ', 'Rock Organ', 'Church Organ', 'Reed Organ', 'Accordion', 'Harmonica', 'Tango Accordion', 'Acoustic Guitar (nylon)', 'Acoustic Guitar (steel)', 'Electric Guitar (jazz)', 'Electric Guitar (clean)', 'Electric Guitar (muted)', 'Overdriven Guitar', 'Distortion Guitar', 'Guitar harmonics', 'Acoustic Bass', 'Electric Bass (finger)', 'Electric Bass (pick)', 'Fretless Bass', 'Slap Bass 1', 'Slap Bass 2', 'Synth Bass 1', 'Synth Bass 2', 'Violin', 'Viola', 'Cello', 'Contrabass', 'Tremolo Strings', 'Pizzicato Strings', 'Orchestral Harp', 'Timpani', 'String Ensemble 1', 'String Ensemble 2', 'Synth Strings 1', 'Synth Strings 2', 'Choir Aahs', 'Voice Oohs', 'Synth Choir', 'Orchestra Hit', 'Trumpet', 'Trombone', 'Tuba', 'Muted Trumpet', 'French Horn', 'Brass Section', 'Synth Brass 1', 'Synth Brass 2', 'Soprano Sax', 'Alto Sax', 'Tenor Sax', 'Baritone Sax', 'Oboe', 'English Horn', 'Bassoon', 'Clarinet', 'Piccolo', 'Flute', 'Recorder', 'Pan Flute', 'Blown Bottle', 'Shakuhachi', 'Whistle', 'Ocarina', 'Lead 1 (square)', 'Lead 2 (sawtooth)', 'Lead 3 (calliope)', 'Lead 4 (chiff)', 'Lead 5 (charang)', 'Lead 6 (voice)', 'Lead 7 (fifths)', 'Lead 8 (bass + lead)', 'Pad 1 (new age)', 'Pad 2 (warm)', 'Pad 3 (polysynth)', 'Pad 4 (choir)', 'Pad 5 (bowed)', 'Pad 6 (metallic)', 'Pad 7 (halo)', 'Pad 8 (sweep)', 'FX 1 (rain)', 'FX 2 (soundtrack)', 'FX 3 (crystal)', 'FX 4 (atmosphere)', 'FX 5 (brightness)', 'FX 6 (goblins)', 'FX 7 (echoes)', 'FX 8 (sci-fi)', 'Sitar', 'Banjo', 'Shamisen', 'Koto', 'Kalimba', 'Bag pipe', 'Fiddle', 'Shanai', 'Tinkle Bell', 'Agogo', 'Steel Drums', 'Woodblock', 'Taiko Drum', 'Melodic Tom', 'Synth Drum', 'Reverse Cymbal', 'Guitar Fret Noise', 'Breath Noise', 'Seashore', 'Bird Tweet', 'Telephone Ring', 'Helicopter', 'Applause', 'Gunshot']
25
+
26
+ begin
27
+ @@map = {
28
+ '@'=>BassDrum2, '#'=>BassDrum1,
29
+ '='=>SnareDrum2, '-'=>SnareDrum1,
30
+ "'"=>ClosedHiHat, '"'=>OpenHiHat,
31
+ '^'=>RideCymbal1, '`'=>CrashCymbal1, '*'=>CrashCymbal2, '<'=>Cowbell,
32
+ '['=>MidTom1, '_'=>MidTom2, ']'=>LowTom2,
33
+ }
34
+ rescue Exception=>e
35
+ end
36
+
37
+ def self.menu
38
+
39
+ %`
40
+ > Pass in notes
41
+ | g cdefg c c
42
+ - .setup/
43
+ - .instrument/
44
+ - most common/
45
+ - Acoustic Grand Piano/
46
+ - Electric Piano 1/
47
+ - Glockenspiel/
48
+ - Vibraphone/
49
+ - Xylophone/
50
+ - Drawbar Organ/
51
+ - Church Organ/
52
+ - Accordion/
53
+ - Acoustic Guitar (nylon)/
54
+ - Distortion Guitar/
55
+ - Electric Bass (finger)/
56
+ - Violin/
57
+ - Tremolo Strings/
58
+ - Pizzicato Strings/
59
+ - Orchestral Harp/
60
+ - Timpani/
61
+ - String Ensemble 2/
62
+ - Synth Strings 2/
63
+ - Choir Aahs/
64
+ - Synth Choir/
65
+ - Orchestra Hit/
66
+ - Trumpet/
67
+ - Flute/
68
+ - Pan Flute/
69
+ - Lead 1 (square)/
70
+ - Lead 2 (sawtooth)/
71
+ - Pad 1 (new age)/
72
+ - Pad 2 (warm)/
73
+ - Pad 4 (choir)/
74
+ - Pad 7 (halo)/
75
+ - Pad 8 (sweep)/
76
+ - FX 3 (crystal)/
77
+ - FX 6 (goblins)/
78
+ - Steel Drums/
79
+ - Woodblock/
80
+ - Taiko Drum/
81
+ - all/
82
+ - .tempo/
83
+ - 60
84
+ - 120
85
+ - 240
86
+ - 480
87
+ - 960
88
+ - .repeat/
89
+ - 1
90
+ - 2
91
+ - 4
92
+ - 8
93
+ - .mode/
94
+ - lydian) 4
95
+ - ionian - major) 3
96
+ - mixolydian) 2
97
+ - dorian) 1
98
+ - aeolian - minor) 0
99
+ - phrygian) -1
100
+ - locrian) -2
101
+ - random/
102
+ - .pentatonic/
103
+ - off
104
+ - on
105
+ - .octave/
106
+ - 2
107
+ - 1
108
+ - 0
109
+ - -1
110
+ - -2
111
+ - .velocity/
112
+ - 126
113
+ - 96
114
+ - 64
115
+ - 32
116
+ - .variation/
117
+ - 0
118
+ - 1
119
+ - 2
120
+ - 3
121
+ - .consistency/
122
+ - 0%
123
+ - 25%
124
+ - 50%
125
+ - 75%
126
+ - .melodic/
127
+ - 1
128
+ - 0
129
+ - .climb/
130
+ - 1
131
+ - -1
132
+ - 0
133
+ - .probability/
134
+ - 100%
135
+ - 75%
136
+ - 50%
137
+ - .reset/
138
+ - .random notes/
139
+ - examples/
140
+ - basics/
141
+ - chords/
142
+ @piano/
143
+ | A A A B A
144
+ | C C D D C
145
+ | E F F F E
146
+ - two parts/
147
+ @piano/
148
+ | CGcCGc C GaCGa CGcCGc C GaCGa
149
+ | cde edc d c c de e
150
+ - three parts/
151
+ @piano/
152
+ | ABCDEFGabcdefghijklmnopqrstuv
153
+ | B C D E F G a b c d e f g h
154
+ | B C D E F G a
155
+ - sharps/
156
+ @piano/
157
+ | # # # # #
158
+ | ce ecbca Gb baGbG G G a
159
+ | #
160
+ | C E C A C L B E B N B L H
161
+ - drums/
162
+ @piano/
163
+ | ' ' ' ' ' '* '
164
+ | =@@= @@@=@@= @@@
165
+ - unofficial xiki theme song/
166
+ @piano/
167
+ | xiki is so great
168
+ | P Q P Q P Q P Q P Q P Q P Q P Q
169
+ | < < < < < < < < < < < < < < < <
170
+ | @ = @@= @ = @@= @ = @@= @ = @@=
171
+ - generation/
172
+ - variation/
173
+ @piano/
174
+ | reset()
175
+ | variation()
176
+ | aaaaaaaa
177
+ - probability/
178
+ @piano/
179
+ | reset()
180
+ | variation()
181
+ | probability(50)
182
+ | aaaaaaaaaaaa
183
+ - melodic/
184
+ @piano/
185
+ | reset()
186
+ | variation(1)
187
+ | melodic()
188
+ | aaaaaaaaaaaa
189
+ - climb/
190
+ @piano/
191
+ | reset()
192
+ | variation(1)
193
+ | melodic()
194
+ | climb()
195
+ | aaaaaaaaaaaa
196
+ - consistency/
197
+ @piano/
198
+ | reset()
199
+ | variation()
200
+ | consistency(80)
201
+ | aaaaaaaaaaaa
202
+ - solo/
203
+ @piano/
204
+ | reset()
205
+ | repeat(8)
206
+ | tempo(55)
207
+ | mode(rand 100)
208
+ | variation()
209
+ | consistency(50)
210
+ | melodic()
211
+ | probability(80)
212
+ | abcdefgh
213
+ - duet/
214
+ @piano/
215
+ | reset()
216
+ | repeat(8)
217
+ | tempo(35)
218
+ | mode(rand 8)
219
+ | variation(2)
220
+ | consistency(10)
221
+ | melodic()
222
+ | A A A A
223
+ | h h h h
224
+ - all together/
225
+ @piano/
226
+ | reset()
227
+ | repeat(8)
228
+ | tempo(45)
229
+ | mode(rand 100)
230
+ | variation()
231
+ | consistency(50)
232
+ | melodic()
233
+ | probability(80)
234
+ | aaaaaaaa
235
+ | AAAAAAAA
236
+ | H H
237
+ - everything random/
238
+ @piano/
239
+ | reset()
240
+ | repeat(16)
241
+ | tempo(rand(60) + 40)
242
+ | mode(rand 200)
243
+ | variation(rand(6) + 1)
244
+ | consistency(rand(50))
245
+ | melodic(rand 1)
246
+ | octave(-1)
247
+ | probability(rand(55) + 45)
248
+ | aaaaaaaaaaaaaaaa
249
+ | AAAAAAAAAAAAAAAA
250
+ | H H H H
251
+ - cool instruments/
252
+ @piano/
253
+ | reset()
254
+ | repeat(32)
255
+ | tempo(rand(60) + 40)
256
+ | mode(rand 200)
257
+ | variation(rand(6) + 1)
258
+ | instrument([112, 108, 107, 102, 101, 100, 98, 97, 96, 95, 89, 88, 87, 86, 80, 54, 50, 49, 46, 45, 34, 12, 11, 10, 9, 8, 4][rand 27])
259
+ | consistency(rand(50))
260
+ | melodic(rand 1)
261
+ | octave(-1)
262
+ | probability(rand(55) + 45)
263
+ | aaaaaaaaaaaaaaaa
264
+ | AAAAAAAAAAAAAAAA
265
+ | H H H H
266
+ - .api/
267
+ | Play some notes
268
+ @ Piano.song "abc"
269
+ - .docs/
270
+ > Single notes
271
+ - @piano/a/
272
+ - @piano/55/
273
+
274
+ > Multiple notes
275
+ - @piano/cde edc d c c de e
276
+ - @piano/some words for fun
277
+
278
+ > Modes
279
+ modes/
280
+ | For reference, here are the whole and half steps for the options under
281
+ | the "mode" menu. By default the A scale is used.
282
+ |
283
+ | - O o o oo o oO: lydian
284
+ | - O o oo o o oO: ionian (major)
285
+ | - O o oo o oo O: mixolydian
286
+ | - O oo o o oo O: dorian
287
+ | - O oo o oo o O: aeolian (minor)
288
+ | - Oo o o oo o O: phrygian
289
+ | - Oo o oo o o O: locrian
290
+ `
291
+ end
292
+
293
+ def self.names
294
+ @@names
295
+ end
296
+
297
+
298
+ def self.menu_after menu_output, *args
299
+
300
+ # Don't interfere if menu did something
301
+ return menu_output if menu_output
302
+
303
+ # If just number, intercept
304
+ if args.length == 1 && args[0] =~ /^\d+$/
305
+ self.note args[0].to_i
306
+ return false
307
+ end
308
+
309
+ if $el
310
+ if Line =~ /\(/
311
+ Tree.to_parent
312
+ Move.to_end
313
+ Search.forward("^[^(\n]+$")
314
+ end
315
+ txt = ENV['txt']
316
+ else
317
+ txt = args[0]
318
+ end
319
+
320
+ self.song txt, :move=>1
321
+
322
+ nil
323
+ end
324
+
325
+ def self.song txt, options={}
326
+ @@lines = txt.split("\n")#.reverse
327
+
328
+ self.extract_functions
329
+
330
+ # If only config, just run first ones
331
+ # if @@lines.empty?
332
+ # return self.run_functions @@functions_by_index[0], :include_all
333
+ # end
334
+ self.run_functions @@functions_by_index[0], :include_all
335
+
336
+ repeat = (@@functions_by_index[0]||[]).find{|o| o =~ /^rep(eat)?\(/}
337
+ @@repeat = (repeat[/\d+/]||"4").to_i if repeat
338
+
339
+ @@repeat.times do |i|
340
+
341
+ # Start at where cursor is
342
+ if $el
343
+ View.column = Line.value[/.+(\/|\| ?)/].length if options[:move]
344
+ end
345
+
346
+ longest = @@lines.inject(0){|acc, e| e.length > acc ? e.length : acc}
347
+
348
+ longest.times do |j|
349
+ # self.run_functions @@functions_by_index[j] # unless j == 0
350
+ self.run_functions @@functions_by_index[j] unless i == 0
351
+
352
+ sharp = false
353
+ @@lines.each_with_index do |line, track|
354
+ char = line[j] ? line[j].chr : nil
355
+ self.note char, :no_sit=>1, :sharp=>sharp, :track=>track
356
+ sharp = char == "#"
357
+ end
358
+ if $el
359
+ Move.forward if options[:move] && View.cursor != Line.right
360
+ end
361
+ self.pause
362
+ end
363
+ end
364
+
365
+ nil
366
+ end
367
+
368
+ def self.run_functions list, include_all=nil
369
+ @@in_run_functions = true
370
+ (list||[]).each do |item|
371
+ next if !include_all && item =~ /^rep(eat)?\(/
372
+ eval("Piano.#{item}")
373
+ end
374
+ @@in_run_functions = false
375
+ end
376
+
377
+ def self.extract_functions
378
+ lines, @@lines = @@lines.partition{|i| i =~ /\(/}
379
+
380
+ @@functions_by_index = {}
381
+ lines.each do |line|
382
+ Code.parse_functions line, @@functions_by_index
383
+ end
384
+ end
385
+
386
+ def self.clear channel=1
387
+ self.driver.control_change 123, channel, 123
388
+ end
389
+
390
+ def self.<< letter
391
+ self.note letter
392
+ end
393
+
394
+ def self.letter_to_number letter, options={}
395
+
396
+ adjustment =@@mode
397
+
398
+ letter.next! if @@pentatonic && (letter == "b" || letter == "e")
399
+
400
+ number = letter[0].to_i
401
+ number = case letter
402
+ when "a".."z"; number - 96
403
+ when "A".."G"; number - 71
404
+ when "H".."N"; number - 85
405
+ when "O".."U"; number - 99
406
+ when "V".."Z"; number - 111
407
+ else; raise "Don't know how to convert the note #{letter} to a number."
408
+ end
409
+
410
+ number = self.apply_variation number, options
411
+
412
+ number = number * 12/7.0
413
+ number -= 0.01
414
+ adjustment -= 2
415
+ adjustment = (adjustment / 7.0) - 0.01
416
+ number += adjustment
417
+
418
+ number = number.floor
419
+ number += 68
420
+ number
421
+ end
422
+
423
+ def self.apply_variation number, options={}
424
+ return number if rand(100) > (100 - @@consistency) # Do nothing if consistency says to stop
425
+
426
+ random = rand(@@variation+1)
427
+
428
+ if @@climb == 0
429
+ random *= ((-1) ** rand(2)) # Half of the time, make it decrease note
430
+ end
431
+ # Ol << "random: #{random.inspect}"
432
+
433
+ if @@melodic == 1
434
+ track = options[:track]
435
+ @@melodic_accumulator[track] ||= 0
436
+ random *= @@climb if @@climb != 0
437
+ @@melodic_accumulator[track] += random
438
+
439
+ @@melodic_accumulator[track] = 0 if @@melodic_accumulator[track] > 28 || @@melodic_accumulator[track] < -28
440
+
441
+ random = @@melodic_accumulator[track]
442
+ end
443
+
444
+ number + random
445
+ end
446
+
447
+ def self.apply_probability number
448
+ return 0 if rand(100) > @@probability
449
+ number
450
+ end
451
+
452
+
453
+ def self.note letter='a', options={}
454
+
455
+ return if letter.nil? || letter == "#"
456
+
457
+ channel = 1
458
+ velocity = @@velocity
459
+
460
+ # Varying the velocity doesn't sound super-great
461
+ # velocity = 63 + rand(63)
462
+
463
+ if letter.is_a? Fixnum
464
+ number = letter
465
+ # If super-low, make them audible
466
+ number += 69 if number <= 20
467
+ elsif letter =~ /^[0-9]$/
468
+ number = letter[0] + 21
469
+ elsif letter =~ /^[a-zA-Z]$/
470
+ number = self.letter_to_number letter, options
471
+ number = self.apply_probability number
472
+ elsif letter.length == 1 && letter.count("@#='\"`^*<[_]-") == 1
473
+ channel = 10
474
+ number = @@map[letter]
475
+ velocity = letter.count("@#=-") == 1 ? 126 : 65
476
+ elsif letter == " " || letter == "+"
477
+ number = 0
478
+ elsif letter.is_a?(String) && letter.length > 1
479
+ letter.split('').each{|o| self.note o}
480
+ return
481
+ else
482
+ raise "- Note #{letter.inspect} not recognized!"
483
+ end
484
+ return if number == 0
485
+
486
+ number += 1 if options[:sharp]
487
+ number += (@@octave * 12)
488
+
489
+ self.driver.note_on(number, channel, velocity) unless number == 0
490
+
491
+ return if options[:no_sit]
492
+
493
+ self.pause
494
+ nil
495
+ end
496
+
497
+ def self.pause
498
+ pause = @@tempo * 4
499
+ pause = pause / 60.0
500
+ pause = 1 / pause
501
+ $el ? $el.sit_for(pause) : sleep(pause)
502
+ Piano.clear
503
+ Piano.clear 10
504
+ end
505
+
506
+ def self.keydef letter, note, channel=1, velocity=126
507
+ $el.define_key(:piano_mode_map, letter) do
508
+ self.driver.note_on(note, channel, velocity)
509
+ end
510
+ end
511
+
512
+ def self.midi
513
+ @@midi || self.connect
514
+ end
515
+
516
+ def self.keys
517
+ $el.elvar.piano_mode_map = $el.make_sparse_keymap unless $el.boundp :piano_mode_map
518
+
519
+ keydef " ", BassDrum2, 10
520
+ keydef "-", SnareDrum2, 10
521
+ keydef "1", SnareDrum1, 10
522
+
523
+ keydef "6", ClosedHiHat, 10, 60
524
+ keydef "1", OpenHiHat, 10, 60
525
+ keydef $el.kbd("C-i"), RideCymbal1, 10, 60
526
+
527
+ # Note: keys are optimized for dvorak
528
+ keydef ";", C3; keydef "o", Cs3
529
+ keydef "q", D3; keydef "e", Ds3
530
+ keydef "j", E3
531
+
532
+ keydef "k", F3; keydef "i", Fs3
533
+ keydef "x", G3; keydef "d", Gs3
534
+ keydef "b", A3; keydef "h", As3
535
+ keydef "m", B3
536
+ keydef "w", C4; keydef "n", Cs4
537
+ keydef "v", D4; keydef "s", Ds4
538
+ keydef "z", E4
539
+
540
+ keydef "'", B3; keydef "3", Cs4
541
+ keydef ",", C4; keydef "3", Cs4
542
+ keydef ".", D4; keydef "4", Ds4
543
+ keydef "p", E4
544
+ keydef "y", F4; keydef "6", Fs4
545
+ keydef "f", G4; keydef "7", Gs4
546
+ keydef "g", A4; keydef "8", As4
547
+ keydef "c", B4
548
+ keydef "r", C5; keydef "0", Cs5
549
+ keydef "l", D5; keydef "[", Ds5
550
+ keydef "/", E5
551
+ keydef "=", F5
552
+ keydef '\\\\', G5
553
+
554
+ "aut259]".split(//).each do |letter|
555
+ $el.define_key(:piano_mode_map, letter) do
556
+ View.message("key '#{letter}' inactive")
557
+ end
558
+
559
+ end
560
+
561
+ keydef "", :nothing # nothing
562
+
563
+
564
+ $el.define_key(:piano_mode_map, $el.kbd("<right>")) do
565
+ @@program += 1
566
+ View.message "program: #{@@program+1} - #{@@names[@@program]}"
567
+ @@midi.program_change 1, @@program
568
+ end
569
+
570
+ $el.define_key(:piano_mode_map, $el.kbd("<left>")) do
571
+ @@program -= 1
572
+ View.message "program: #{@@program+1} - #{@@names[@@program]}"
573
+ @@midi.program_change 1, @@program
574
+ end
575
+
576
+ $el.define_key(:piano_mode_map, $el.kbd("<backspace>")) do
577
+ @@midi.control_change 123, 1, 123
578
+ end
579
+
580
+ rescue Exception=>e
581
+
582
+ end
583
+
584
+ def self.init
585
+ self.keys
586
+ # Make piano mode happen for .piano files
587
+ Mode.define(:piano, ".piano") do
588
+ Notes.apply_styles
589
+ end
590
+ end
591
+
592
+ def self.instrument type, name=nil, options={}
593
+ # If 'all' show all
594
+ return @@names.map{|o| "- #{o}/"}.join("\n") if type == 'all' && name.nil?
595
+
596
+ # If 1 arg, assume it's the name
597
+ name = type if name.nil?
598
+
599
+
600
+ if name.is_a?(Fixnum)
601
+ index = name
602
+ else
603
+ name = Regexp.escape name
604
+ name.gsub! '\ ', ".+"
605
+ index = @@names.index{|o| o =~ /^#{name}$/i}
606
+ index ||= @@names.index{|o| o =~ /^#{name}/i}
607
+ index ||= @@names.index{|o| o =~ /#{name}/i}
608
+ end
609
+
610
+ @@midi.program_change 1, (index||0)
611
+ return if options[:quiet]
612
+
613
+ # TODO: turn back on, but not when called from .run_functions
614
+ # How to detect?
615
+ # or, maybe just set instance variable when in .run_functions
616
+ # @@in_run_functions = true
617
+ # maybe .sub! it to have an extra parameter to suppress?
618
+ # instrument('Piano') -> instrument('Piano', :suppress)
619
+ Piano.note "abc" unless @@in_run_functions
620
+ end
621
+
622
+ def self.reset
623
+ self.connect
624
+
625
+ @@velocity = 126
626
+ @@tempo = 120
627
+ @@probability = 100
628
+
629
+ @@variation = 0
630
+ @@melodic = 0
631
+ @@melodic_accumulator = []
632
+ @@climb = 0
633
+ @@pentatonic = false
634
+ @@consistency = 0
635
+ @@mode = 0
636
+ @@octave = 0
637
+ @@program = 1
638
+ @@repeat = 1
639
+ @@seed = nil
640
+
641
+ ".flash - success!"
642
+ end
643
+
644
+ #
645
+ # Low level call to configure midi.
646
+ #
647
+ def self.control_change a, b, c
648
+ self.driver.control_change a, b, c
649
+ end
650
+
651
+ def self.connect
652
+ @@midi = MIDIator::Interface.new
653
+ @@midi.use :dls_synth
654
+ # This doesn't work in Lion :(
655
+ @@midi.control_change 32, 10, 1 # Drums: R-808 is Program 26 in LSB bank 1
656
+ @@midi.control_change 7, 1, 126 # Turn volume up to max
657
+ @@midi
658
+ end
659
+
660
+ def self.velocity txt="126"; @@velocity = txt.to_i; ".flash - updated!"; end
661
+ def self.tempo txt="120"; @@tempo = txt.to_i; ".flash - updated!"; end
662
+ def self.probability txt="50"; @@probability = txt.to_s.sub('%', '').to_i; ".flash - updated!"; end
663
+ def self.variation txt="2"
664
+ @@variation = txt.to_i
665
+ if @@seed # If seed set manually, just use it
666
+ seed = @@seed
667
+ else # Else auto-generate seed
668
+ seed = rand 999_999_999_999_999_999_999
669
+ end
670
+
671
+ srand seed
672
+
673
+ ".flash - updated!"
674
+ end
675
+ def self.melodic txt="1"; @@melodic = txt.to_i; ".flash - updated!"; end
676
+ def self.climb txt="1"; @@climb = txt.to_i; ".flash - updated!"; end
677
+ def self.pentatonic txt="1"; Ol.<<(txt); @@pentatonic = [true, "on", 1].member?(txt); ".flash - updated!"; end
678
+ def self.consistency txt="50"; @@consistency = txt.to_s.sub('%', '').to_i; ".flash - updated!"; end
679
+ def self.octave txt="0"; @@octave = txt.to_i; ".flash - updated!"; end
680
+ def self.repeat txt="4"; @@repeat = txt.to_i; ".flash - updated!"; end
681
+ def self.seed txt; @@seed = txt.to_i; ".flash - updated!"; end
682
+
683
+ def self.mode txt=nil
684
+ return @@mode if txt.nil?
685
+
686
+ if txt.to_s == "random"
687
+ random = (-2..9).to_a[rand 7]
688
+ @@mode = random
689
+ return ".flash - updated to #{random}!"
690
+ end
691
+
692
+ @@mode = txt.to_i
693
+ ".flash - updated!"
694
+ end
695
+
696
+ class << self
697
+ alias :tem :tempo
698
+ alias :pro :probability
699
+ alias :mel :melodic
700
+ alias :cli :climb
701
+ alias :vel :velocity
702
+ alias :pen :pentatonic
703
+ alias :res :reset
704
+ alias :rep :repeat
705
+ alias :var :variation
706
+ alias :con :consistency
707
+ alias :oct :octave
708
+ alias :mod :mode
709
+ alias :ins :instrument
710
+ end
711
+
712
+ def self.driver
713
+ @@midi ||= self.connect
714
+ end
715
+
716
+ def self.random_notes range=nil, notes=nil
717
+ if range.nil?
718
+ return "- a..g/"
719
+ end
720
+
721
+ # If just range, generate
722
+
723
+ if notes.nil?
724
+
725
+ range ||= "a..g"
726
+
727
+ range =~ /(.+)\.\.(.+)/
728
+ range = $1..$2
729
+
730
+ range = range.to_a
731
+
732
+ txt = ""
733
+ 8.times do
734
+ txt << range[rand range.length]
735
+ end
736
+ return "| #{txt}"
737
+ end
738
+
739
+ self.song ENV['txt']
740
+ nil
741
+ end
742
+
743
+ end
744
+
745
+ Piano.init # Define mode
746
+ Menu.drums :menu=>'piano'