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,9 @@
1
+ # Simple wrapper around control_lock.el to turne
2
+ # it on and off (and handle the case where it's not)
3
+ # installed.
4
+ class ControlLock
5
+
6
+ def self.disable
7
+ $el.control_lock_enable if $el.boundp(:control_lock_mode_p) and $el.elvar.control_lock_mode_p
8
+ end
9
+ end
@@ -0,0 +1,176 @@
1
+ # Helps you switch between files, in a way very similar to how Ctrl-tab
2
+ # switches between windows in most operating systems. Call #keys
3
+ # to map it to Ctrl-tab in emacs.
4
+ class ControlTab
5
+
6
+ @@edited = nil
7
+
8
+ @@switch_index = 0
9
+
10
+ # Primary method. Is mapped to C-tab and does the switching.
11
+ def self.go
12
+
13
+ prefix = Keys.prefix :clear=>1
14
+
15
+ first_tab_in_sequence = Keys.before_last !~ /\btab$/ # If first tab, clear edited
16
+ @@edited = @@dash_prefix = @@nine_prefix = nil if first_tab_in_sequence
17
+
18
+ if prefix == :- || @@dash_prefix # Go to next quote in $f
19
+ View.layout_files :no_blink=>1
20
+ Move.to_quote
21
+ Effects.blink
22
+ Launcher.launch
23
+ @@dash_prefix = true
24
+ return
25
+ end
26
+
27
+ if prefix == 9 || @@nine_prefix # Navigate to next Ol line in *ol buffer
28
+
29
+ View.layout_output :dont_highlight=>1
30
+
31
+ Move.to_end
32
+ Search.forward "^-", :go_anyway=>1
33
+ if View.cursor == View.bottom
34
+ Move.to_previous_paragraph
35
+ Line.next
36
+ end
37
+ Effects.blink
38
+ Launcher.launch
39
+ @@nine_prefix = true
40
+ return
41
+ end
42
+
43
+ # if prefix == 9 # If __ prefix, just burry buffer
44
+ # $el.bury_buffer
45
+ # # Store original order, and windows originally opened
46
+ # @@original = buffer_list.to_a # Hide evidence that we were on top (lest it restore us)
47
+ # @@open_windows = window_list.collect {|b| window_buffer b}
48
+ # @@consider_test = lambda{|b| ! buffer_name(b)[/Minibuf/] }
49
+ # return
50
+ # end
51
+
52
+ if prefix == :u # If U prefix (must be first alt-tab in sequence)
53
+ # Go to last edited file, and store list
54
+ @@edited = $el.elvar.editedhistory_history.to_a
55
+ @@edited -= View.files :visible=>1 # Exclude currently visible files
56
+ $el.find_file @@edited.shift
57
+
58
+ return
59
+ elsif @@edited # Subsequent alt-tab
60
+ $el.find_file @@edited.shift
61
+ return
62
+ end
63
+
64
+ # If this was the first tab in this sequence
65
+ if first_tab_in_sequence# || last_was_modeline_click
66
+
67
+ # Store original order, and windows originally opened
68
+ @@original = $el.buffer_list.to_a
69
+ @@open_windows = $el.window_list.collect {|b| $el.window_buffer b}
70
+
71
+ # Check for prefix, and store correct test for files to go through accordingly
72
+ case prefix
73
+ when 0 # Non-files
74
+ @@consider_test = lambda{|b| ! $el.buffer_file_name(b) && ! $el.buffer_name(b)[/Minibuf/]}
75
+ when 1 # Only files
76
+ @@consider_test = lambda{|b| $el.buffer_file_name(b)}
77
+ # when 3 # ...css
78
+ # @@consider_test = lambda{|b| buffer_name(b) =~ /\.(css|sass)/}
79
+ when 2 # .notes files
80
+ @@consider_test = lambda{|b| $el.buffer_file_name(b) =~ /\.deck$/}
81
+ when 3 # ...css
82
+ @@consider_test = lambda{|b| $el.buffer_name(b) =~ /^#/}
83
+ when 4 # haml.html files
84
+ @@consider_test = lambda{|b| $el.buffer_file_name(b) =~ /\.html/}
85
+ when 5 # Consoles
86
+ @@consider_test = lambda{|b|
87
+ next if $el.buffer_file_name b
88
+ $el.set_buffer b
89
+ next if $el.elvar.major_mode.to_s != 'shell-mode'
90
+ name = $el.buffer_name b
91
+ next if name == "*ol"
92
+ true
93
+ }
94
+ # @@consider_test = lambda{|b| buffer_name(b) =~ /^(\*console|\*merb) /i}
95
+ when 6 # Ruby files only
96
+ @@consider_test = lambda{|b| $el.buffer_file_name(b) =~ /\.rb$/}
97
+ when 68 # controller
98
+ @@consider_test = lambda{|b| $el.buffer_file_name(b) =~ /\/app\/controllers\//}
99
+ when 66 # Models
100
+ @@consider_test = lambda{|b| $el.buffer_file_name(b) =~ /\/app\/models\//}
101
+ when 67 # Tests
102
+ @@consider_test = lambda{|b| $el.buffer_file_name(b) =~ /_(spec|test)\.rb$/}
103
+ when 7 # .notes files
104
+ @@consider_test = lambda{|b| $el.buffer_file_name(b) =~ /\.notes$/}
105
+ when 8 # Anything (just like no arg)
106
+ @@consider_test = lambda{|b| ! $el.buffer_name(b)[/Minibuf/] }
107
+ # when 9 # js
108
+ # @@consider_test = lambda{|b| buffer_file_name(b) =~ /\.js$/}
109
+ else # Anything (except minibuffer)
110
+ @@consider_test = lambda{|b| ! $el.buffer_name(b)[/Minibuf/] }
111
+ end
112
+
113
+ # Remember we're starting at the top of the buffer list
114
+ @@switch_index = 0
115
+
116
+ # Go to next eligible buffer
117
+ self.move_to_next
118
+
119
+ $el.switch_to_buffer(@@original[@@switch_index])
120
+
121
+ # If we've been typing tabs
122
+ else
123
+ self.restore_original_order # Restore order up to this buffer
124
+ self.move_to_next # Point to next eligible buffer
125
+ $el.switch_to_buffer(@@original[@@switch_index]) # Switch to eligible
126
+
127
+ end
128
+ end
129
+
130
+ def self.restore_original_order
131
+ # Move backwards through original list, moving each to front
132
+ (0..(@@switch_index)).each do |i|
133
+ $el.switch_to_buffer(@@original[@@switch_index-i])
134
+ end
135
+ end
136
+
137
+ # Advances @@switch_index to next eligible buffer
138
+ def self.move_to_next
139
+ buffer_started_at = @@switch_index
140
+
141
+ @@switch_index += 1 # Move to next
142
+ self.to_next_unless_nil # Go there so test can look at buffer mode, etc
143
+
144
+ # Keep moving until we find an eligible buffer (that isn't already viewed)
145
+ while(
146
+ @@open_windows.member?(@@original[@@switch_index]) || # Already viewed
147
+ ! @@consider_test[@@original[@@switch_index]] # Not what we're looking for
148
+ )
149
+ @@switch_index += 1
150
+
151
+ # Stop moving forward if we're at end
152
+ if @@switch_index >= @@original.size
153
+ @@switch_index = buffer_started_at
154
+ # View.to_buffer buffer_started_at
155
+ View.beep 'None left'
156
+ break
157
+ end
158
+
159
+ self.to_next_unless_nil
160
+ end
161
+ end
162
+
163
+ def self.to_next_unless_nil
164
+ to_buffer = @@original[@@switch_index]
165
+ if to_buffer.nil?
166
+ View.beep 'None left'
167
+ end
168
+ $el.set_buffer(to_buffer) # Go there so test can look at buffer mode, etc
169
+ end
170
+
171
+ def self.keys
172
+ Keys.set("C-<tab>") do
173
+ ControlTab.go
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,31 @@
1
+ require 'text_util'
2
+
3
+ class Array
4
+ def blank?
5
+ self.empty?
6
+ end
7
+ end
8
+
9
+ class NilClass
10
+ def empty?
11
+ self.nil?
12
+ end
13
+
14
+ def blank?
15
+ self.nil?
16
+ end
17
+ end
18
+
19
+ class String
20
+ def blank?
21
+ self.nil? || self.empty?
22
+ end
23
+
24
+ def present?
25
+ ! self.nil?
26
+ end
27
+
28
+ def unindent
29
+ TextUtil.unindent(to_s)
30
+ end
31
+ end
@@ -0,0 +1,111 @@
1
+ class Cursor
2
+
3
+ @@remember = {}
4
+
5
+ def self.menu
6
+ %`
7
+ > Summary
8
+ | Api for changing the cursor
9
+ |
10
+ - Colors/
11
+ @Cursor.white
12
+ @Cursor.red
13
+ @Cursor.green
14
+ @Cursor.blue
15
+ @Cursor.color "#80f"
16
+ - Shapes/
17
+ @Cursor.bar
18
+ @Cursor.underscore
19
+ @Cursor.hollow
20
+ @Cursor.box
21
+ - Colors and Shapes/
22
+ @Cursor.red_bar
23
+ @Cursor.green_underscore
24
+ @Cursor.blue_hollow
25
+ @Cursor.black_box
26
+ - Remembering and restoring cursor/
27
+ @Cursor.remember :a
28
+ @Cursor.restore :a
29
+ `
30
+
31
+ end
32
+
33
+ def self.bar
34
+ $el.el4r_lisp_eval "(customize-set-variable 'cursor-type '(bar . 2))"
35
+ nil
36
+ end
37
+ def self.box
38
+ $el.customize_set_variable :cursor_type, :box
39
+ nil
40
+ end
41
+ def self.underscore
42
+ $el.el4r_lisp_eval "(customize-set-variable 'cursor-type '(hbar . 3))"
43
+ nil
44
+ end
45
+ def self.hollow
46
+ $el.customize_set_variable :cursor_type, :hollow
47
+ nil
48
+ end
49
+
50
+ def self.color color
51
+ $el.set_face_background :cursor, color
52
+ nil
53
+ end
54
+
55
+ def self.blue
56
+ $el.set_face_background :cursor, "#0099ff"
57
+ nil
58
+ end
59
+ def self.red
60
+ $el.set_face_background :cursor, "#ff3300"
61
+ nil
62
+ end
63
+ def self.green
64
+ $el.set_face_background :cursor, "#33bb00"
65
+ nil
66
+ end
67
+ def self.white
68
+ $el.set_face_background :cursor, "#ffffff"
69
+ nil
70
+ end
71
+ def self.black
72
+ $el.set_face_background :cursor, "#000000"
73
+ nil
74
+ end
75
+
76
+ def self.red_bar
77
+ self.red
78
+ self.bar
79
+ end
80
+ def self.blue_hollow
81
+ self.blue
82
+ self.hollow
83
+ end
84
+ def self.green_underscore
85
+ self.green
86
+ self.underscore
87
+ end
88
+ def self.blue_underscore
89
+ self.blue
90
+ self.underscore
91
+ end
92
+ def self.black_box
93
+ self.black
94
+ self.box
95
+ end
96
+
97
+ def self.remember symbol=:default
98
+ # Save is hash for later restoring (only if not there yet)
99
+ @@remember[symbol] = [$el.elvar.cursor_type, $el.face_background(:cursor)]
100
+ end
101
+
102
+ def self.restore symbol=:default
103
+ before = @@remember[symbol]
104
+ return Cursor.black_box unless before # Black if not found
105
+ type, color = before
106
+ $el.set_face_background :cursor, color
107
+ $el.customize_set_variable :cursor_type, type
108
+ end
109
+
110
+ end
111
+
@@ -0,0 +1,65 @@
1
+ class Deletes
2
+ def self.delete_whitespace
3
+
4
+ prefix = Keys.prefix(:clear=>true) # Number prefix means add that many lines after deleting
5
+
6
+ if prefix == :u # If U, remove whitespace within region
7
+ txt = View.selection :delete=>true
8
+ linebreak_on_end = txt[/\n\z/]
9
+ txt.gsub! /^ *[+-] /, ''
10
+ txt.gsub! /[\n\t ]/, ''
11
+ View.insert("#{txt}#{linebreak_on_end}", :dont_move=>true)
12
+ return
13
+ end
14
+
15
+ # If at end of line, go forward, and remember to delete backward
16
+ was_blank = Line.blank?
17
+ was_at_end = (Line.at_right? and (! was_blank))
18
+ was_at_beginning = (Line.at_left? and (! was_blank))
19
+ if was_blank # If blank, stay on line
20
+ # Do nothing
21
+ elsif was_at_end
22
+ $el.forward_char
23
+ elsif was_at_beginning and not View.char =~ /\s/
24
+ $el.backward_char
25
+ else # If not at end of a line, simply delete horizontal
26
+ $el.delete_horizontal_space
27
+ View.insert(" " * prefix) if prefix
28
+ return
29
+ end
30
+
31
+ # Delete any blank lines
32
+ $el.delete_blank_lines if Line.blank?
33
+ $el.delete_char(1) if Line.blank? # Delete line if left
34
+
35
+ Deletes.backward if was_at_end
36
+ if was_at_beginning
37
+ Deletes.backward if Line.at_left?
38
+ $el.delete_char(1) if Line.at_right?
39
+ end
40
+ if was_blank
41
+ if prefix
42
+ View.insert("\n" * prefix)
43
+ Move.backward prefix
44
+ end
45
+ else
46
+ $el.delete_horizontal_space
47
+ View.insert(" " * prefix) if prefix
48
+ end
49
+ end
50
+
51
+
52
+ def self.backward
53
+ prefix = Keys.prefix
54
+ case prefix
55
+ when :u
56
+ $el.backward_kill_word 1
57
+ when :uu
58
+ $el.backward_kill_word 2
59
+ when :uuu
60
+ $el.backward_kill_word 3
61
+ else
62
+ $el.delete_backward_char(prefix || 1)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,297 @@
1
+ require 'hide'
2
+
3
+ # Will store a diff each time a file is saved.
4
+ class DiffLog
5
+
6
+ @@log = File.expand_path("~/.emacs.d/difflog.notes")
7
+ @@temp_path = "/tmp/saved.txt"
8
+
9
+ def self.menu
10
+ "
11
+ .open/
12
+ .diffs/
13
+ .diffs/$p/
14
+ docs/
15
+ > Summary
16
+ | The difflog tracks diffs of all the changes you make to file
17
+ | (assuming you save using as+file).
18
+ |
19
+ > Keys
20
+ | open+diffs - open the difflog
21
+ | search+diffs - search the difflog from the bottom
22
+ "
23
+ end
24
+
25
+ # Open file having difflog
26
+ def self.open
27
+ View.to_after_bar if View.in_bar?
28
+
29
+ # If open, just switch to it and revert
30
+ if View.buffer_open?("difflog.notes")
31
+ View.to_buffer("difflog.notes")
32
+ $el.revert_buffer true, true, true
33
+ else # Otherwise, open it
34
+ View.open(@@log)
35
+ end
36
+ View.to_bottom
37
+ Line.previous
38
+ Line.to_words
39
+ $el.recenter -4
40
+ end
41
+
42
+ def self.diffs path=nil
43
+
44
+ txt = File.read @@log
45
+ txt = txt.sub(/\A- /, '').split(/^- /).reverse.uniq
46
+
47
+ path ||= Tree.dir # Pull from tree if there
48
+
49
+ path = Bookmarks[path] if path
50
+
51
+ if ! path
52
+ regex = /^\//
53
+ elsif File.file? path # File
54
+ regex = /^#{Regexp.escape File.dirname path}\/\n - #{Regexp.escape File.basename path}/
55
+ else # Dir
56
+ regex = /^#{Regexp.escape path}/
57
+ path = "#{path}/" if path !~ /\/$/
58
+ end
59
+
60
+ txt = txt.select{|o| o =~ regex}
61
+
62
+ "- @#{txt.join("- @")}"
63
+ end
64
+
65
+ # Insert old text deleted during last save
66
+ def self.last_diff
67
+ $el.with(:save_window_excursion) do
68
+ DiffLog.open
69
+ Search.backward "^-"
70
+ txt = View.txt View.cursor, View.bottom
71
+ end
72
+ end
73
+
74
+ def self.is_one_line_change? txt
75
+ txt.scan(/^ +\|\-/).length == 1 &&
76
+ txt.scan(/^ +\|\+/).length == 1 &&
77
+ txt.scan(/^ +:/).length
78
+ end
79
+
80
+ # Insert new text added during last save
81
+ def self.enter_new
82
+ self.enter_old_or_new :new
83
+ end
84
+
85
+ def self.enter_old
86
+ self.enter_old_or_new :old
87
+ end
88
+
89
+ def self.enter_old_or_new old_or_new
90
+
91
+ diff = DiffLog.last_diff
92
+ one_line_change = DiffLog.is_one_line_change? diff
93
+
94
+ # Show intraline change if changed just one line and not up+
95
+
96
+ if ! Keys.up? && one_line_change
97
+ View.<< DiffLog.last_intraline_diff[old_or_new == :old ? 0 : 1] rescue View.beep $!
98
+ return
99
+ end
100
+
101
+ # Show lines
102
+
103
+ diff.gsub! /^ *[+:-].*\n/, "" # Only leave red and green lines
104
+ if old_or_new == :old
105
+ diff.gsub! /^ +\|\+.*\n/, ""
106
+ diff.gsub! /^ +\|\-/, ""
107
+ else
108
+ diff.gsub! /^ +\|\-.*\n/, ""
109
+ diff.gsub! /^ +\|\+/, ""
110
+ end
111
+ View << diff
112
+
113
+ end
114
+
115
+ # Appends diff to difflog, then saves. Mapped to as_file.
116
+ def self.save
117
+ return if View.file_name == "difflog.notes"
118
+
119
+ prefix = Keys.prefix :clear=>1
120
+
121
+ self.save_diffs
122
+
123
+ $el.save_buffer
124
+
125
+ if prefix == :u
126
+ sleep(0.3)
127
+ Firefox.reload
128
+ elsif prefix == 9
129
+ Launcher.do_last_launch
130
+ end
131
+ end
132
+
133
+ def self.format raw
134
+ path, file = raw.match(/--- (.+\/)(.+?)\t/)[1..2]
135
+
136
+ # Delete paths at top
137
+ raw.sub!(/.+\n.+\n/, '')
138
+
139
+ # Make @@... lines into lines having numbers
140
+ raw.gsub!(/^@@ -(\d+).* \+(\d+).+@@$/) {
141
+ a, b = $1.to_i, $2.to_i
142
+ highest = a > b ? a : b
143
+ " :#{highest}"
144
+ }
145
+
146
+ # Make - and + lines into -| and +| lines
147
+ raw.gsub!(/^\+(.*)/, " |+\\1")
148
+ raw.gsub!(/^-(.*)/, " |-\\1")
149
+
150
+ # Return with path
151
+ "- #{path}\n" +
152
+ " - #{file}\n" +
153
+ raw
154
+ end
155
+
156
+ def self.compare_with_saved
157
+
158
+ if Keys.prefix_u
159
+
160
+ buffer_unsaved = View.buffer
161
+
162
+ path = View.file
163
+
164
+ View.to_buffer "untitled"
165
+ $el.rename_uniquely
166
+ View << File.read(path)
167
+
168
+ return $el.ediff_buffers View.buffer, buffer_unsaved
169
+
170
+ end
171
+
172
+ diff = self.save_diffs :dont_log=>1
173
+ diff = "" if diff.nil?
174
+
175
+ View.to_buffer("*diff with saved*")
176
+ View.clear
177
+ Notes.mode
178
+
179
+ View.insert diff.count("\n") > 2 ?
180
+ diff :
181
+ "> Note\n- No Differences!\n"
182
+ end
183
+
184
+ def self.enter_from_difflog
185
+ Location.as_spot
186
+ View.to_after_bar if View.in_bar?
187
+ DiffLog.open
188
+ $el.isearch_backward
189
+ end
190
+
191
+ # Util function used by public functions
192
+ def self.save_diffs options={}
193
+ if options[:patha] && options[:textb]
194
+ patha = options[:patha]
195
+ File.open(@@temp_path, "w") { |f| f << options[:textb] }
196
+ else
197
+ patha = View.file
198
+ $el.write_region nil, nil, @@temp_path
199
+ end
200
+
201
+ diff = Console.sync "diff -U 0 \"#{patha}\" \"#{@@temp_path}\""
202
+ return if diff.empty? || diff =~ /: No such file or directory\n/ # Fail quietly if file didn't exist
203
+
204
+ diff = self.format diff
205
+ return diff if options[:dont_log]
206
+
207
+ File.open(@@log, "a") { |f| f << diff } unless diff.count("\n") <= 2
208
+ end
209
+
210
+ def self.parse_tree_diffs txt
211
+ result = [[], []]
212
+
213
+ txt = txt.split("\n")
214
+ i, length = 0, txt.length
215
+
216
+ while i < length
217
+ line = txt[i]
218
+ # a_or_d = line[/^[ad]/]
219
+ match = line.match(/^(.)(\d+) (\d+)/)
220
+ raise "Line #{line} unexpected by DiffLog.parse_tree_diffs" if ! match
221
+ a_or_d, line_number, many = match[1..3]
222
+ line_number, many = line_number.to_i, many.to_i
223
+
224
+ if a_or_d == "d"
225
+ i += 1
226
+ many.times do |n|
227
+ result[1] << line_number + n
228
+ end
229
+ next
230
+ end
231
+
232
+ if a_or_d == "a"
233
+ i += 1
234
+ many.times do |n|
235
+ result[0] << line_number + n
236
+ end
237
+ next
238
+ end
239
+
240
+ raise "DiffLog.parse_tree_diffs doesn't know what to do with #{line}"
241
+ end
242
+
243
+ result
244
+ end
245
+
246
+ def self.do_compare_with
247
+ prefix = Keys.prefix :clear=>1
248
+
249
+ # up+ means compare buffers in first two views
250
+
251
+ return $el.ediff_buffers( $el.window_buffer($el.nth(0, $el.window_list)), $el.window_buffer($el.nth(1, $el.window_list))) if prefix == :u
252
+
253
+ # Save place and grab file at spot
254
+
255
+ source_path = Tree.dir_at_spot
256
+ dest_path = Tree.dir :file=>1
257
+ $el.ediff_files source_path, dest_path
258
+
259
+ end
260
+
261
+ #
262
+ # Grabs last diff from difflog, and calculates exactly what changed. Whithin the line.
263
+ # So, it performs a single-line diff
264
+ #
265
+ # It presumes a single-line change, and a change at only one point on the line.
266
+ #
267
+ # DiffLog.last_intraline_diff
268
+ #
269
+ def self.last_intraline_diff txt=nil
270
+ txt ||= DiffLog.last_diff
271
+
272
+ linea = txt[/ +\|\-(.+)/, 1]
273
+ lineb = txt[/ +\|\+(.+)/, 1]
274
+
275
+ raise "The last diff in the difflog didn't have a red and a green." if linea.nil? || lineb.nil?
276
+
277
+ linea_length, lineb_length = linea.length, lineb.length
278
+
279
+ from_start = 0
280
+ while from_start < linea_length
281
+ break if linea[from_start] != lineb[from_start]
282
+ from_start += 1
283
+ end
284
+
285
+ from_end = 1
286
+ while from_end < linea_length
287
+ break if from_end > linea_length || from_end > lineb_length || linea[linea_length-from_end] != lineb[lineb_length-from_end]
288
+ from_end += 1
289
+ end
290
+
291
+ deltaa = from_end > linea_length ? "" : linea[from_start..(linea_length-from_end)]
292
+ delteab = from_end > lineb_length ? "" : lineb[from_start..(lineb_length-from_end)]
293
+
294
+ [deltaa, delteab]
295
+ end
296
+
297
+ end