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,1000 @@
1
+ require 'styles'
2
+ require 'line'
3
+ require 'effects'
4
+ require 'view'
5
+ require 'keys'
6
+ require 'clipboard'
7
+
8
+ class Notes
9
+
10
+ LABEL_REGEX = /(?:[a-zA-Z0-9 _-]+\) )?/
11
+
12
+ def self.menu
13
+ %`
14
+ - api/
15
+ > Turn notes wiki text into html
16
+ @ Notes.to_html "> Heading\\njust text\\n"
17
+ `
18
+ end
19
+
20
+ def self.block regex="^> "
21
+ left, after_header, right = View.block_positions regex
22
+ View.txt after_header, right
23
+ end
24
+
25
+ def self.narrow_block options={}
26
+
27
+ delimiter = options[:delimiter] || ">"
28
+
29
+ # If nothing hidden, hide all but current
30
+ if $el.point_min == 1 && ($el.buffer_size + 1 == $el.point_max)
31
+ left, after_header, right = View.block_positions "^#{delimiter}\\( \\|$\\)"
32
+ $el.narrow_to_region left, right
33
+ return
34
+ end
35
+ # Otherwise, expand all, go to next heading, hide all but current
36
+ $el.widen
37
+ Notes.to_block
38
+ left, after_header, right = View.block_positions "^#{delimiter}\\( \\|$\\)"
39
+ $el.narrow_to_region left, right
40
+ end
41
+
42
+ def self.archive
43
+ block = get_block
44
+ block.archive
45
+ end
46
+
47
+ def self.show_text
48
+ block = get_block
49
+ block.show_text
50
+ end
51
+
52
+ def self.hide_text
53
+ block = get_block
54
+ block.hide_text
55
+ end
56
+
57
+ def self.to_block up=false
58
+
59
+ regex = self.heading_regex Keys.prefix
60
+
61
+ prefix = Keys.prefix :clear=>1
62
+
63
+ times = prefix.is_a?(Fixnum) ? prefix : 1
64
+
65
+ if up
66
+ times.times do
67
+ Line.to_left
68
+ Search.backward regex
69
+ end
70
+ else
71
+ times.times do
72
+ Line.next if $el.string_match regex, Line.value # Use elisp matcher
73
+ Search.forward regex
74
+ Line.to_left
75
+ end
76
+ end
77
+ end
78
+
79
+ def self.heading_regex prefix=nil
80
+ prefix == :u ?
81
+ "^[>=]\\{1,2\\}\\( \\|$\\)" :
82
+ "^[>=]\\( \\|$\\)"
83
+ end
84
+
85
+ def self.move_block up=false
86
+ regex = self.heading_regex Keys.prefix
87
+
88
+ times = Keys.prefix_times
89
+
90
+ orig = Location.new
91
+
92
+ prefix = Keys.prefix :clear=>1
93
+
94
+ block = get_block prefix == :u ? 2 : 1
95
+ block.delete_content
96
+
97
+ if up
98
+ times.times do
99
+ Search.backward regex, :go_anyway=>true
100
+ end
101
+ $el.insert block.content
102
+ Search.backward regex
103
+ else
104
+
105
+ move_regex = prefix == :u ? "^>" : regex
106
+
107
+ Search.forward move_regex
108
+ times.times do
109
+ Search.forward move_regex, :go_anyway=>true
110
+ end
111
+ Move.to_axis
112
+
113
+ View.insert block.content
114
+
115
+ Search.backward move_regex
116
+ end
117
+ moved_block = get_block regex
118
+
119
+ times == 1 ?
120
+ moved_block.fade_in :
121
+ orig.go
122
+ end
123
+
124
+ def self.insert_heading options={}
125
+ Line.start
126
+ orig = Line.value
127
+
128
+ times = Keys.prefix_u? ? 1 : (Keys.prefix || 1)
129
+ times.times { $el.insert ">" }
130
+ View.insert " " # unless times > 1
131
+
132
+ if options[:extra_space] || Keys.prefix_u? # If U create blank lines.
133
+ View.insert("\n"*4, :dont_move=>1)
134
+ return
135
+ end
136
+
137
+ View.insert("\n", :dont_move=>1) if orig != ""
138
+ end
139
+
140
+ def self.cut_block no_clipboard=false
141
+ block = get_block Keys.prefix
142
+
143
+ block.blink
144
+
145
+ unless no_clipboard
146
+ Clipboard.set("0", block.content)
147
+ end
148
+ block.delete_content
149
+ end
150
+
151
+ def self.copy_block
152
+ prefix = Keys.prefix
153
+ block = get_block prefix == :u ? 2 : 1
154
+ block.blink
155
+ Clipboard.set("0", Keys.prefix_u ? block.text : block.content)
156
+ end
157
+
158
+ def self.move_block_to_top no_clipboard=false
159
+
160
+ prefix_u = Keys.prefix_u :clear=>true
161
+ block = get_block
162
+
163
+ if prefix_u
164
+ line = View.line_number
165
+ scroll = View.scroll_position
166
+ orig_right = block.right
167
+ end
168
+
169
+ block.fade_out unless prefix_u
170
+
171
+ block.delete_content
172
+
173
+ $el.beginning_of_buffer
174
+ $el.insert block.content
175
+
176
+ if prefix_u
177
+ View.to_line line
178
+ View.scroll_position = scroll
179
+ View.cursor = orig_right
180
+ Line.next
181
+ else
182
+ View.to_line 2
183
+ end
184
+
185
+ moved_block = get_block
186
+
187
+ moved_block.fade_in unless prefix_u
188
+
189
+ end
190
+
191
+ def self.keys
192
+
193
+ return if ! $el
194
+
195
+ # Get reference to map if already there (don't mess with existing buffers)
196
+ $el.elvar.notes_mode_map = $el.make_sparse_keymap unless $el.boundp :notes_mode_map
197
+
198
+ Keys.custom_archive(:notes_mode_map) { Notes.archive }
199
+ Keys.custom_back(:notes_mode_map) { Notes.move_block :backwards } # Move block up to before next block
200
+ Keys.custom_clipboard(:notes_mode_map) { Notes.copy_block } # block -> clipboard
201
+ Keys.custom_delete(:notes_mode_map) { Notes.cut_block :backwards } # block -> clear
202
+ # Keys.custom_expand(:notes_mode_map) { Notes.narrow_block } # Show just block
203
+ Keys.custom_forward(:notes_mode_map) { Notes.move_block } # Move block down to after next block
204
+ Keys.custom_heading(:notes_mode_map) { Notes.insert_heading } # Insert |... etc. heading
205
+ Keys.custom_item(:notes_mode_map) { Agenda.quick_add_line }
206
+ # j
207
+ Keys.custom_kill(:notes_mode_map) { Notes.cut_block } # block -> cut
208
+ # l
209
+ Keys.custom_mask(:notes_mode_map) { Notes.hide_text } # block -> hide
210
+ Keys.custom_next(:notes_mode_map) { Notes.to_block } # Go to block after next block
211
+ Keys.custom_open(:notes_mode_map) { Notes.show_text } # block -> reveal
212
+ Keys.custom_previous(:notes_mode_map) { Notes.to_block :backwards } # Go to block before next block
213
+ # q
214
+ # r
215
+ Keys.custom_stamp(:notes_mode_map) { $el.insert Time.now.strftime("- %Y-%m-%d %I:%M%p: ").downcase.sub(' 0', ' ') }
216
+ Keys.custom_top(:notes_mode_map) { Notes.move_block_to_top } # block -> top
217
+ # u
218
+ # v
219
+ # w
220
+ Keys.custom_x(:notes_mode_map) { Notes.cut_block } # block -> cut
221
+ # y
222
+ # z
223
+
224
+ $el.define_key(:notes_mode_map, $el.kbd("<double-mouse-1>"), :notes_mouse_double_click)
225
+ $el.define_key(:notes_mode_map, $el.kbd("<mouse-1>"), :notes_mouse_toggle)
226
+
227
+ $el.define_key(:notes_mode_map, $el.kbd("<M-mouse-1>"), :notes_mouse_double_click)
228
+ $el.define_key(:notes_mode_map, $el.kbd("<S-mouse-1>"), :notes_mouse_double_click)
229
+ $el.define_key(:notes_mode_map, $el.kbd("<C-mouse-1>"), :notes_mouse_double_click)
230
+
231
+
232
+ $el.define_key(:notes_mode_map, $el.kbd("C-i")) { Notes.tab_key }
233
+ end
234
+
235
+ def self.define_styles
236
+
237
+ return if ! $el
238
+
239
+ # - foo (r): <here>
240
+ Styles.define :notes_light_gray,
241
+ :fg => "bbb"
242
+
243
+ # - foo (r): <here>
244
+ Styles.define :variable,
245
+ :face => 'verdana' #, :size => "+2"
246
+
247
+ # - foo (r): <here>
248
+ Styles.define :notes_label_parens,
249
+ :fg => "bbb",
250
+ :size => "-2",
251
+ :face => 'arial'
252
+
253
+ # |...
254
+ h1_size = "+3"
255
+
256
+ # Colors of "| ..." headings
257
+ if Styles.inverse # If black bg
258
+ @@h1_styles = {
259
+ :notes_h1 =>"333",
260
+ :notes_h1r=>"611", # | r This will be red
261
+ :notes_h1o=>"841", # | o This will be orange
262
+ :notes_h1y=>"871",
263
+ :notes_h1e=>"363",
264
+ :notes_h1g=>"363",
265
+ :notes_h1b=>"678",
266
+ :notes_h1p=>"636",
267
+ :notes_h1m=>"622",
268
+ :notes_h1x=>"345",
269
+ :notes_h1t=>"055",
270
+ }
271
+ else
272
+ # Colors of headings
273
+ @@h1_styles = {
274
+ :notes_h1 =>"aaa",
275
+ :notes_h1r=>"b66", # | r This will be red
276
+ :notes_h1o=>"b83", # | o This will be orange
277
+ :notes_h1y=>"bb3",
278
+ :notes_h1e=>"363",
279
+ :notes_h1g=>"7b6",
280
+ :notes_h1b=>"678",
281
+ :notes_h1p=>"b8b",
282
+ :notes_h1m=>"944",
283
+ :notes_h1x=>"678",
284
+ :notes_h1t=>"055",
285
+ }
286
+ end
287
+
288
+ @@h1_styles.each do |k, v|
289
+ pipe = v.gsub(/./) {|c| (c.to_i(16) + "3".to_i(16)).to_s(16)}
290
+ label = v.gsub(/./) {|c| (c.to_i(16) + "6".to_i(16)).to_s(16)}
291
+ Styles.define k,
292
+ :face=>'arial', :size=>h1_size, :fg=>'ffffff', :bg=>v, :bold=> true
293
+ Styles.define "#{k}_pipe".to_sym, :face=>'arial', :size=>h1_size, :fg=>pipe, :bg=>v, :bold=>true
294
+ Styles.define "#{k}_label".to_sym, :face=>'arial', :size=>h1_size, :fg=>label, :bg=>v, :bold=>true
295
+ end
296
+
297
+ Styles.define :notes_h1_agenda_pipe, :face => 'arial', :size => h1_size, :fg => '88cc88', :bg => '336633', :bold => true
298
+ Styles.define :notes_h1_agenda, :face => 'arial', :size => h1_size, :fg => 'ffffff', :bg => '336633', :bold => true
299
+
300
+ # |||...
301
+ Styles.define :notes_h3,
302
+ :face => 'arial', :size => "-1",
303
+ :fg => '999',#, :bg => "9999cc",
304
+ :bold => true
305
+ Styles.define :notes_h3_pipe,
306
+ :face => 'arial', :size => "-1",
307
+ :fg => '333'
308
+
309
+ # ||||...
310
+ Styles.define :notes_h4,
311
+ :face => 'arial', :size => "-3",
312
+ :fg => '55b',
313
+ :bold => true
314
+ Styles.define :notes_h4_pipe,
315
+ :face => 'arial', :size => "-3",
316
+ :fg => '224'
317
+
318
+
319
+ if Styles.inverse # If black and white
320
+ label_color = "e70"
321
+ else
322
+ label_color = "f70"
323
+ end
324
+
325
+ # Labels, emphasis
326
+ Styles.define :notes_label,
327
+ :face=>'arial black', :size=>"0", # Mac
328
+ #:face=>'courier', :size=>"0", # Mac
329
+ :fg=>label_color, :bold=>true
330
+
331
+ Styles.define :notes_bullet_parens,
332
+ :face => 'arial', :size => "-2",
333
+ :fg => "ee7700", :bold => true
334
+
335
+ # Strikethrough
336
+ Styles.define(:strike, :strike=>true)
337
+
338
+ # - <here> (r): foo
339
+ Styles.define :notes_label_link,
340
+ :face => 'verdana', :size => "-1",
341
+ :fg => "66f",
342
+ :bold => true, :underline => true
343
+
344
+ Styles.define :notes_g, :fg=>"6cf", :face=>'arial black', :size=>"0", :bold=>true
345
+ Styles.define :notes_blue, :fg=>"69f", :face=>'arial black', :size=>"0", :bold=>true
346
+ Styles.define :notes_red, :fg=>"c55", :face=>'arial black', :size=>"0", :bold=>true
347
+ Styles.define :notes_yellow, :fg=>"CC0", :face=>'arial black', :size=>"0", :bold=>true
348
+ Styles.define :notes_green, :fg=>"3C3", :face=>'arial black', :size=>"0", :bold=>true
349
+
350
+
351
+ if Styles.inverse # If black bg
352
+ # >>...
353
+ Styles.define :notes_h2, :face=>'arial', :size=>"-1", :fg=>'fff', :bg=>"333", :bold=>false
354
+ Styles.define :notes_h2_pipe, :face=>'arial', :size=>"-1", :fg=>'555555', :bg=>"333333", :bold=> true
355
+ else
356
+ Styles.define :notes_h2, :face=>'arial', :size=>"-1", :fg=>'fff', :bg=>"999", :bold=>true
357
+ Styles.define :notes_h2_pipe, :face=>'arial', :size=>"-1", :fg=>'bbb', :bg=>"999", :bold=>true
358
+ end
359
+
360
+ if Styles.inverse # If black bg
361
+ Styles.dotted :bg=>'080808', :fg=>'111', :strike=>nil, :underline=>nil, :border=>['111', -1]
362
+ else
363
+ Styles.dotted :bg=>'eee', :fg=>'ddd', :strike=>nil, :underline=>nil, :border=>['ddd', -1]
364
+ end
365
+
366
+ notes_exclamation_color = Styles.inverse ? "7c4" : "5a0"
367
+
368
+ Styles.define :notes_exclamation, # Green bold text
369
+ :face=>'arial black', :size=>"0",
370
+ :fg=>notes_exclamation_color, :bold=>true
371
+
372
+ Styles.notes_link :fg=>(Styles.inverse ? "9ce" : "08f")
373
+
374
+ Styles.shell_prompt :fg=>'#888', :bold=>1
375
+
376
+ end
377
+
378
+ def self.apply_styles
379
+ # Don't format quotes (it overrides the following formatting)
380
+ Styles.clear
381
+
382
+ # >... lines (headings)
383
+ Styles.apply("^\\(>\\)\\(.*\n\\)", nil, :notes_h1_pipe, :notes_h1)
384
+
385
+ Styles.apply("^\\(> \\)\\(.*\n\\)", nil, :notes_h1_pipe, :notes_h1)
386
+ Styles.apply("^\\(>> \\)\\(.*\n\\)", nil, :notes_h2_pipe, :notes_h2)
387
+ Styles.apply("^\\(= \\)\\(.*\n\\)", nil, :notes_h1_pipe, :notes_h1)
388
+ Styles.apply("^\\(== \\)\\(.*\n\\)", nil, :notes_h2_pipe, :notes_h2)
389
+
390
+ Styles.apply("^\\(>\\)\\( .+?: \\)\\(.+\n\\)", nil, :notes_h1_pipe, :notes_h1_label, :notes_h1)
391
+
392
+ Styles.apply("^\\(> 20[0-9][0-9]-[0-9][0-9]-[0-9][0-9].*:\\)\\(.*\n\\)", nil, :notes_h1_agenda_pipe, :notes_h1_agenda)
393
+
394
+ @@h1_styles.each do |k, v|
395
+ l = k.to_s[/_..(.)$/, 1]
396
+ next unless l
397
+ Styles.apply("^\\(> #{l}\\)\\(\n\\| .*\n\\)", nil, "#{k}_pipe".to_sym, k)
398
+ Styles.apply("^\\(>\\)\\( #{l} .+: \\)\\(.*\n\\)", nil, "#{k}_pipe".to_sym, "#{k}_label".to_sym, k)
399
+ end
400
+
401
+ # >>... lines
402
+ # Styles.apply("^\\(>>\\)\\(.*\\)", nil, :notes_h2_pipe, :notes_h2)
403
+ Styles.apply("^\\(>>\\)\\(.*\n\\)", nil, :notes_h2_pipe, :notes_h2)
404
+
405
+ # Commented
406
+ Styles.apply("^\\(>> .+?: \\)\\(.+\n\\)", nil, :notes_h2_pipe, :notes_h2)
407
+
408
+ # >>>... lines
409
+ Styles.apply("^\\(>>>\\)\\(.*\n\\)", nil, :notes_h3_pipe, :notes_h3)
410
+
411
+ # >>>... lines
412
+ Styles.apply("^\\(>>>>\\)\\(.*\n\\)", nil, :notes_h4_pipe, :notes_h4)
413
+
414
+ # - bullets with labels and comments
415
+ Styles.apply("^[ \t]*\\([<+-]\\) \\([^/:\n]+:\\) ", nil, :ls_bullet, :notes_label) # - hey: you
416
+ Styles.apply("^[ \t]*\\([<+-]<*\\) \\([^(\n]+?)\\) ", nil, :ls_bullet, :notes_label) # - hey) you
417
+
418
+ Styles.apply("^[ \t]*\\([<+=-]<*\\) \\([^(\n]+)\\)$", nil, :ls_bullet, :notes_label) # - hey)
419
+ Styles.apply("^[ \t]*\\([<+=-]<*\\) \\(.+:\\)$", nil, :ls_bullet, :notes_label) # - hey)
420
+
421
+ # Styles.apply("^[ \t]*\\(x\\)\\( \\)\\(.+\\)", nil, :notes_label, :variable, :strike)
422
+
423
+ Styles.apply("^\\([ \t]*\\)\\([<+-]\\) \\(.+?:\\) +\\(|.*\n\\)", nil, :default, :ls_bullet, :notes_label, :ls_quote)
424
+ Styles.apply("^\\([ \t]*\\)\\([<+-]\\) \\([^(\n]+?)\\) +\\(|.*\n\\)", nil, :default, :ls_bullet, :notes_label, :ls_quote)
425
+
426
+ Styles.apply("^ +\\(!.*\n\\)", nil, :ls_quote) # ^!... for commands
427
+
428
+ # exclamation! / todo
429
+ Styles.apply("^[ \t]*\\([<+-]\\) \\(.*!\\)$", nil, :ls_bullet, :notes_exclamation)
430
+ Styles.apply("^ +\\(!\\+.*\n\\)", nil, :diff_green) # Whole lines
431
+ Styles.apply("^ +\\(!-.*\n\\)", nil, :diff_red)
432
+
433
+ Styles.apply("\\(\(-\\)\\(.+?\\)\\(-\)\\)", nil, :diff_small, :diff_red, :diff_small)
434
+ Styles.apply("\\(\(\\+\\)\\(.+?\\)\\(\\+\)\\)", nil, :diff_small, :diff_green, :diff_small)
435
+
436
+ # google/
437
+ Styles.apply "^ *\\(-?\\) ?\\(@?\\)\\(g\\)\\(o\\)\\(o\\)\\(g\\)\\(l\\)\\(e\\)\\(/\\)", nil, :ls_bullet, :ls_dir,
438
+ :notes_blue, :notes_red, :notes_yellow, :notes_blue, :notes_green, :notes_red,
439
+ :ls_dir
440
+
441
+ Styles.apply "^hint/.+", :fade6
442
+
443
+ Styles.apply "^ *@? ?\\([%$&]\\) ", nil, :shell_prompt # Colorize shell prompts
444
+
445
+ Styles.apply("^ *\\(|`\\)\\(.*\n\\)", nil, :quote_heading_pipe, :dotsies_experimental)
446
+ Styles.apply("^ *\\(|~\\)\\([^\n~]+\\)\\(~?\\)", nil, :quote_heading_pipe, :dotsies, :quote_heading_pipe)
447
+
448
+ end
449
+
450
+ # Startup
451
+ def self.init
452
+
453
+ return if ! $el
454
+
455
+ $el.defun(:notes_mouse_meta_click, :interactive => "e") do |e|
456
+ $el.mouse_set_point(e)
457
+ View.insert "hey"
458
+ end
459
+
460
+ $el.defun(:notes_mouse_double_click, :interactive => "e") do |e|
461
+ next Launcher.insert "h" if Line =~ /^$/ # If blank line, launch history
462
+ Launcher.launch_or_hide(:blink=>true)
463
+ end
464
+
465
+ $el.defun(:notes_mouse_toggle, :interactive => "e") do |e|
466
+ $el.mouse_set_point(e)
467
+ Notes.mouse_toggle
468
+ end
469
+
470
+ $el.defun(:notes_mode, :interactive => "", :docstring => "Apply notes styles, etc") {# |point|
471
+ $el.el4r_lisp_eval "(setq font-lock-defaults '(nil t))"
472
+
473
+ FileTree.apply_styles
474
+ Notes.apply_styles
475
+ FileTree.apply_styles_at_end
476
+ $el.use_local_map $el.elvar.notes_mode_map
477
+ }
478
+ $el.el4r_lisp_eval %q<
479
+ (progn
480
+ (add-to-list 'auto-mode-alist '("\\\\.notes\\\\'" . notes-mode))
481
+ (add-to-list 'auto-mode-alist '("\\\\.xik\\\\'" . notes-mode))
482
+ (add-to-list 'auto-mode-alist '("\\\\.wik\\\\'" . notes-mode)))
483
+ >
484
+ end
485
+
486
+ def self.mode
487
+ $el.notes_mode
488
+ end
489
+
490
+ def self.enter_label_bullet
491
+ Line.to_left
492
+ View.insert "- : "
493
+ Move.backward 2
494
+ end
495
+
496
+ def self.enter_junior
497
+
498
+ Move.to_end if Line.before_cursor =~ /^ +$/ # If at awkward position, move
499
+
500
+ cursor = View.cursor
501
+ line = Line.value
502
+ indent = Line.indent line
503
+ pipe = line =~ /^ *([|#])/ ? $1 : ""
504
+ if Line.left == cursor || Line.right == cursor # If beginning or end, leave current line alone
505
+ Move.to_end
506
+ else # In middle of line
507
+ Deletes.delete_whitespace
508
+ end
509
+
510
+ return View.<< "\n#{line[/^[ |#]*/]} " if pipe
511
+ View << "\n#{indent}#{pipe} "
512
+ end
513
+
514
+ def self.bullet bullet_text="- "
515
+ prefix = Keys.prefix :clear=>true
516
+
517
+ if prefix == :u
518
+ Move.forward if Line.at_right?
519
+ return Tree.collapse
520
+ end
521
+
522
+ if prefix == :uu
523
+ return Tree.collapse :replace_parent=>1
524
+ end
525
+
526
+ line = Line.value
527
+ indent = Line.indent indent
528
+
529
+ if line.present? # If non-blank line
530
+ Move.to_end if line =~ /^ / && View.column <= indent.length # If just entered a bullet, go to end first
531
+
532
+ Move.to_end if line =~ /^[+-] / && View.column <= 2 # If just entered a bullet, go to end first
533
+
534
+ # If at beginning of line, just insert bullet
535
+ return View.insert "- " if View.column == 0 && bullet_text == "- " && line !~ /^ /
536
+
537
+ if View.cursor != Line.right
538
+ Deletes.delete_whitespace
539
+ end
540
+ View.insert "\n"
541
+
542
+ # Do simple case if quoted
543
+ return View.<<("#{line[/^[ |#]*/]} - ") if line =~ /^ *[|#]/
544
+
545
+ # Do simple case if on heading
546
+ return View.<<("- ") if line =~ /^>/
547
+ end
548
+
549
+ if prefix.is_a? Fixnum # If numeric prefix, indent by n
550
+ View.insert((" " * prefix) + bullet_text)
551
+ else # Get bullet indent of previous line
552
+ prev = Line.value(0)
553
+ prev_indent = prev[/^( *)/]
554
+
555
+ # Indent further, unless it we're doing bullets and not following bullet
556
+ prev_indent << " " if line != "" && (bullet_text != "- " || prev =~ /^ *[+-]/ || prev !~ /^>/)
557
+ prev_indent = "#{prev_indent}#{bullet_text}"
558
+ View.insert prev_indent
559
+
560
+ if prefix == :-
561
+ View.insert "(): "
562
+ Move.backward 3
563
+ end
564
+ end
565
+
566
+ return if bullet_text == "" # Don't indent rest if not using bullets (enter_junior)
567
+
568
+ following_line = Line.value(2)
569
+ return if following_line !~ /^ / # Don't indent rest of lines if at left margin
570
+ return if Line.matches /^[ -]*$/ # Exit if new bullet was blank
571
+
572
+ indent = Line.indent
573
+
574
+ return if indent.empty? # Don't indent anything if new bullet wasn't indented
575
+
576
+ cursor = View.cursor
577
+ Line.next
578
+ top = View.cursor
579
+
580
+ # Find next line not indented underneath
581
+ Search.forward "^ \\{0,#{indent.size-1}\\}\\($\\|[^ \n]\\)", :beginning=>true
582
+ $el.indent_rigidly top, Line.left, 2
583
+ View.cursor = cursor
584
+
585
+ end
586
+
587
+ def self.mouse_toggle
588
+ #Launcher.launch_or_hide(:blink=>true)
589
+
590
+ # If next line is indented more, kill children
591
+ # If starts with plus or minus, and on plus or minus, launch
592
+ if Line.matches(/^\s*[+-]/) and View.char =~ /[+-]/
593
+ plus_or_minus = Tree.toggle_plus_and_minus
594
+ if ! Tree.children?
595
+ #plus_or_minus == '+' # If +, expand (launch
596
+
597
+ if FileTree.dir? or ! FileTree.handles? # If on a dir or code_tree
598
+ Launcher.launch
599
+ else # If on a file in a FileTree
600
+ FileTree.enter_lines
601
+ end
602
+
603
+ else # If -, kill under
604
+ Tree.kill_under
605
+ Line.to_beginning
606
+ end
607
+ end
608
+ end
609
+
610
+ # Returns an instance of BlockNotes representing the block the point is currently in
611
+ # def self.get_block regex="^[|>]\\( \\|$\\)"
612
+ def self.get_block regex=nil
613
+ regex ||= self.heading_regex
614
+
615
+ regex = self.heading_regex if regex == 1
616
+ regex = self.heading_regex(:u) if regex == 2 || regex == :u
617
+
618
+ left, after_header, right = View.block_positions regex
619
+ NotesBlock.new(left, after_header, right)
620
+ end
621
+
622
+ def self.to_html txt
623
+ txt = txt.
624
+ gsub(/^> (.+)/, "<h1>\\1</h1>").
625
+ gsub(/(^|[^\n>])$/, "\\0<br>")
626
+ end
627
+
628
+ def self.as_nav
629
+
630
+ prefix = Keys.prefix :clear=>true
631
+ txt = ""
632
+ if prefix == :u || prefix == :uu
633
+ txt = Code.grab_containing_method
634
+ end
635
+
636
+ label = nil
637
+ if prefix == 9
638
+ label = Keys.input :prompt=>"label: ", :timed=>1
639
+ label = "do" if label.blank?
640
+ label = Notes.expand_if_action_abbrev(label) || label
641
+
642
+ prefix = nil
643
+ end
644
+
645
+ if prefix == :uu # up+up means add function and line
646
+ txt << "\n#{Line.value}"
647
+ elsif prefix != :u
648
+ txt = View.txt_per_prefix prefix, :selection=>1, :default_is_line=>1, :just_txt=>1
649
+ end
650
+
651
+ # If file has bullet or ends with slash, grab path
652
+
653
+ keep_tweeking = true
654
+ if ! prefix && FileTree.handles? # Grab tree
655
+ txt = Tree.ancestors_indented :just_sub_tree=>1
656
+ txt.sub! /^ /, ' - '
657
+ keep_tweeking = false
658
+ end
659
+
660
+ file = View.file
661
+ orig = Location.new
662
+
663
+ if keep_tweeking
664
+ if Search.fit_in_snippet(txt) # Insert it in existing tree if there
665
+ View << " - #{label}:\n" if label
666
+ return orig.go
667
+ end
668
+ else
669
+ View.layout_files :no_blink=>1
670
+ end
671
+
672
+ # Make it quoted, unless already a quote
673
+ if keep_tweeking && (txt !~ /\A([+-] |\/)/ || txt !~ /^ +/) # If txt isn't already a tree, make it one
674
+ txt = FileTree.snippet :txt=>txt, :file=>file
675
+ txt.sub! /^ /, " - #{label}:\n " if label
676
+ end
677
+
678
+ # Else, add it to top...
679
+
680
+ View.to_highest
681
+
682
+ if prefix == 8
683
+ if Line =~ /^>/
684
+ Line.next
685
+ end
686
+ result = "#{txt}\n"
687
+ else
688
+ result = ">\n#{txt}\n"
689
+ end
690
+
691
+ View.<< result, :dont_move=>1
692
+
693
+ orig.go
694
+ end
695
+
696
+
697
+ def self.as_todo
698
+ prefix = Keys.prefix :clear=>1
699
+
700
+ txt = nil
701
+
702
+ # If method, make it Foo.bar method call
703
+ line = Line.value
704
+
705
+ if View.file =~ /_spec.rb/ && line =~ /^ *(it|describe) /
706
+ return Specs.enter_as_rspec
707
+ end
708
+
709
+ buffer_name = $el.buffer_name
710
+ file_name = View.file_name
711
+ trunk = Xiki.trunk
712
+
713
+ if prefix.nil? # So 1+ or numeric prefix just grab normally
714
+ if buffer_name == "*ol" # Make it into "foo = bar" format
715
+ txt = line[/\) (.+)/, 1]
716
+ txt.sub!(": ", " = ") if txt
717
+ txt ||= line[/ *- (.+?) /, 1]
718
+
719
+ elsif trunk.last =~ /(\w+)\.rb\/\| *def ([\w\.?]+)/
720
+ clazz = $1
721
+ method = $2
722
+ clazz = TextUtil.camel_case clazz if method.slice! /^self\./
723
+ txt = "#{clazz}.#{method}"
724
+
725
+ elsif line =~ /^ +def (.+)/ # Make it into Foo.bar format
726
+ method = $1
727
+ clazz = file_name[/\w+/]
728
+ clazz = TextUtil.camel_case clazz if method.slice! /^self\./
729
+
730
+ txt = "#{clazz}.#{method}"
731
+
732
+ elsif line =~ /^ *\|/ # Make it into Foo.bar format
733
+ txt = line.sub /^ *\| ?/, ''
734
+ elsif FileTree.handles?
735
+ txt = Tree.dir
736
+ elsif line =~ /(^ *[+-] |\/$)/ # Make it into Foo.bar format
737
+ txt = Xiki.trunk.last
738
+ end
739
+ end
740
+
741
+ txt ||= View.txt_per_prefix(prefix, :selection=>1, :just_txt=>1, :default_is_line=>1)
742
+ txt.strip! if txt =~ /\A.+\n\z/ # Strip when only 1 linebreak
743
+
744
+ options = prefix == :uu ? {:append=>1} : {}
745
+ Search.move_to "$t", txt, options
746
+ end
747
+
748
+
749
+ class NotesBlock
750
+
751
+ attr_accessor :left, :after_header, :right
752
+ attr_accessor :header, :text
753
+
754
+ def initialize(left, after_header, right)
755
+ @left, @after_header, @right = left, after_header, right
756
+ @header = $el.buffer_substring left, after_header
757
+ @text = $el.buffer_substring after_header, right
758
+ end
759
+
760
+ def positions
761
+ [left, after_header, right]
762
+ end
763
+
764
+ def content
765
+ header + text
766
+ end
767
+
768
+ def to_s
769
+ content
770
+ end
771
+
772
+ def blink
773
+ Effects.blink :left => after_header, :right => right
774
+ end
775
+
776
+ def fade_out
777
+ Effects.glow :fade_out=>1, :what=>[left, right]
778
+ end
779
+
780
+ def fade_in
781
+ Effects.glow :fade_in=>1, :what=>[left, right]
782
+ end
783
+
784
+ def delete_content
785
+ $el.delete_region left, right
786
+ end
787
+
788
+ # initialize an overlay for this notes block
789
+ # it has a special hook that updates name to be header always
790
+ # this way we can always find the overlay corresponding to header
791
+
792
+ def show_text
793
+ @header_overlay ||= Overlay.find_or_make(left, after_header - 1)
794
+
795
+ @body_overlay ||= Overlay.find_or_make(after_header, right)
796
+ @body_overlay.invisible = false
797
+ end
798
+
799
+ def hide_text
800
+ @header_overlay ||= Overlay.find_or_make(left, after_header - 1)
801
+
802
+ @body_overlay ||= Overlay.find_or_make(after_header, right)
803
+ @body_overlay.invisible = true
804
+ end
805
+
806
+ # cuts the block, and stores it in archive.file.notes
807
+ # example: ruby.notes -> archive.ruby.notes
808
+ def archive
809
+ delete_content
810
+ filename = 'archive.' + $el.file_name_nondirectory(buffer_file_name)
811
+ timestamp = "--- archived on #{Time.now.strftime('%Y-%m-%d at %H:%M')} --- \n"
812
+ $el.append_to_file timestamp, nil, filename
813
+ $el.append_to_file content, nil, filename
814
+ end
815
+ end
816
+
817
+ def self.enter_do_bullet
818
+
819
+ txt = Keys.input :chars=>1, :prompt=>'Enter a character: '
820
+ expanded = Notes.expand_if_action_abbrev txt
821
+
822
+ # If on blank line, just insert it
823
+ if ! Line.blank?
824
+ line = Line.value
825
+ indent, first_char = line.match(/^( *)(.)/)[1..2]
826
+
827
+ Move.to_axis
828
+ $el.open_line(1)
829
+ end
830
+
831
+ if txt == " "
832
+ View << "#{indent}- !"
833
+ ControlLock.disable
834
+ return View.column = -1
835
+ end
836
+
837
+ if expanded
838
+ View << "#{indent}- #{expanded}!"
839
+ Line.to_beginning
840
+ else
841
+ View << "#{indent}- !"
842
+ Move.backward
843
+ View << txt
844
+ end
845
+
846
+ nil
847
+ end
848
+
849
+ def self.drill file, heading=nil, *content
850
+
851
+ prefix = Keys.prefix :clear=>true
852
+ content = content.any? ? content.join('/') : nil
853
+
854
+ file_orig = file.dup
855
+ file = Bookmarks[file]
856
+
857
+ # If bookmark wasn't found, complain
858
+ if file =~ /^\$(\w+)/
859
+ bm = $1
860
+ return "| Set the following bookmark first. Then you'll be able to use this menu to\n| browse the file. The file should have '> ...' headings.\n\n@ $#{bm}\n"
861
+ end
862
+
863
+ # If docs/, output docs string...
864
+
865
+ if heading == "docs"
866
+ message = "
867
+ > Summary
868
+ | Convenient way for browsing the headings in this file:
869
+ |
870
+ - @ #{file}
871
+ ".unindent
872
+ return message
873
+ end
874
+
875
+ if ! File.exists? file
876
+ return "
877
+ | File doesn't exist yet, do as+update to create it:
878
+ @ #{file}
879
+ | > Heading
880
+ | Stuff
881
+ "
882
+ end
883
+
884
+ txt = File.read file
885
+
886
+ # If just file passed, headings
887
+
888
+ if ! heading
889
+
890
+ return View.open file if prefix == "open" # If as+open, just jump there
891
+
892
+ txt = txt.grep /^\>( .+)/
893
+ return "| This file has no '>...' headings:\n@ #{file}" if txt.empty?
894
+ return txt.join('') #.gsub /^> /, '| '
895
+ end
896
+
897
+ # If just heading passed, show text under heading
898
+
899
+ heading.sub!(/^\| /, '> ')
900
+ escaped_heading = Regexp.escape heading
901
+ if ! content
902
+
903
+ if prefix == :u || prefix == "open" # If C-u on a heading, just jump there
904
+ View.open file
905
+ View.to_highest
906
+ Search.forward "^#{$el.regexp_quote heading}$", :beginning=>1
907
+ View.recenter_top
908
+ return
909
+ end
910
+
911
+ txt = self.extract_block txt, heading
912
+ return txt.gsub(/^/, '| ').gsub(/^\| $/, '|')
913
+ end
914
+
915
+ # If content passed
916
+
917
+ # If C-4, grab text and save it to file / update
918
+ if prefix == "update"
919
+ # Update difflog
920
+
921
+ # Grab before and after
922
+ index = txt.index /^#{escaped_heading}$/
923
+ index += heading.length
924
+
925
+ before = txt[0..index]
926
+
927
+ after = txt[index..-1].sub(/.*?^>( |$)/m, ">\\1")
928
+
929
+ content = Tree.siblings :string=>1
930
+
931
+ txt = "#{before}#{content}#{after}"
932
+
933
+ DiffLog.save_diffs :patha=>file, :textb=>txt
934
+
935
+ # return
936
+ File.open(file, "w") { |f| f << txt }
937
+
938
+ # Revert file if it's open?
939
+
940
+ View.flash "- Saved!"
941
+ return
942
+ end
943
+
944
+ # Navigate to heading, then content
945
+
946
+ View.open file
947
+ View.to_highest
948
+ Search.forward "^#{$el.regexp_quote heading}$"
949
+ View.recenter_top
950
+ Search.forward "^#{$el.regexp_quote content.sub(/^\| /, '')}"
951
+ Move.to_axis
952
+ nil
953
+ end
954
+
955
+ def self.extract_block txt, heading
956
+ txt = txt.sub /.*^#{Regexp.escape heading}\n/m, '' # Delete before block
957
+ txt.sub! /^>( |$).*/m, '' # Delete after block
958
+ txt # = txt.gsub(/^.?/, "|\\1") # Escape with pipes
959
+ end
960
+
961
+ def self.read_block file, heading
962
+ self.extract_block File.read(file), heading
963
+ end
964
+
965
+ def self.tab_key
966
+ indent = Line.indent(Line.value 0)
967
+ Line.sub! /^ */, indent
968
+ Line.to_beginning
969
+ end
970
+
971
+ @@single_letter_abbrev = {
972
+ "f"=>"fix",
973
+ "b"=>"borrow",
974
+ "i"=>"implement",
975
+ "d"=>"delete",
976
+ "r"=>"rename",
977
+ "t"=>"todo",
978
+ "e"=>"extract",
979
+ }
980
+
981
+ # If the string is "t" or "i", or a few others, return "todo" or "imprement" etc. respectively.
982
+ def self.expand_if_action_abbrev txt
983
+ @@single_letter_abbrev[txt] || txt
984
+ end
985
+
986
+ def self.do_as_quote
987
+ # Make this add or remove quotes
988
+ end
989
+ end
990
+
991
+ Notes.define_styles
992
+ Notes.init
993
+ Notes.keys # Define local keys
994
+
995
+ # TODO - how to turn these on conditionally?
996
+ # What's the best approach for presentations?
997
+ # Probably make .deck files use notes mode
998
+ # Why wasn't working before?
999
+ # require 'deck'
1000
+ # Deck.keys :notes_mode_map # Temporary - only when doing presentations