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,30 @@
1
+ class Foo
2
+ def self.menu
3
+ "
4
+ - sammiches/
5
+ - ham/
6
+ - .buy/
7
+ - tofu/
8
+ - .buy/
9
+ - .checkout/
10
+ - cash/
11
+ - credit/
12
+ "
13
+ end
14
+ def self.buy category, item
15
+ "- buying #{item} #{category}"
16
+ end
17
+
18
+ def self.checkout kind
19
+ "- checking out as #{kind}..."
20
+ end
21
+
22
+ def self.admin
23
+ "
24
+ - reports/
25
+ - .profit/
26
+ - .loss/
27
+ - .restart_server/
28
+ "
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ class French
2
+ def self.menu txt=nil
3
+ return "| Type something here to translate from french" if txt.nil?
4
+ url = "http://translate.google.com/#fr|en|#{CGI.escape ENV['txt']}"
5
+ Browser.url url
6
+ end
7
+ end
@@ -0,0 +1,185 @@
1
+ class Git
2
+ def self.menu_before *args
3
+
4
+ trunk = Xiki.trunk
5
+
6
+ # If not nested, show docs
7
+ # TODO: restore this
8
+ # return Menu['git/docs'] if trunk.size < 2
9
+
10
+ return self.docs if trunk.size < 2
11
+
12
+ branch = self.branch_name
13
+
14
+ if args[0] != "setup" && branch.nil?
15
+ return "| Not a git repository. Create a new one here?\n- setup/create/"
16
+ end
17
+
18
+ # Handle routing of .push manually, since routing requires linebreaks
19
+ if args[0] == "push"
20
+ return self.push branch, *args[1..-1]
21
+ end
22
+
23
+ nil
24
+ end
25
+
26
+ def self.menu
27
+
28
+ branch = self.branch_name
29
+
30
+
31
+ "
32
+ - .push/#{branch}/
33
+ - .diff/
34
+ - .log/
35
+ - .setup/
36
+ - .create/
37
+ - .make sample files/
38
+ - github/
39
+ @ % git remote add origin git@github.com:trogdoro/foo.git
40
+ - .status/
41
+ - .docs/
42
+ "
43
+ end
44
+
45
+ def self.docs
46
+ "
47
+ > How to use
48
+ | Put the @git menu under a path that has or will have a git repo, like
49
+ | so:
50
+ |
51
+ | - /tmp/myproject/
52
+ | - @git/
53
+ "
54
+ end
55
+
56
+ def self.status
57
+
58
+ # Limit to just file, if nested under file - different command?!
59
+ file = Tree.file
60
+ path = File.file?(file) ? file : "."
61
+
62
+ result = Console.sync "git status #{path}", :dir=>Dir.pwd
63
+ Tree.quote result
64
+ end
65
+
66
+ def self.create
67
+
68
+ result = Console.sync 'git init', :dir=>Dir.pwd
69
+ "
70
+ | #{result.strip}
71
+ "
72
+ end
73
+
74
+ def self.make_sample_files
75
+
76
+ Dir.mkdir "d" rescue nil
77
+
78
+ txt = "hello\nhi again\n"
79
+ ["a.txt", "b.txt", "d/aa.txt"].each { |path| File.open(path, "w") { |f| f << txt } }
80
+
81
+ "
82
+ | Created these files:
83
+ | - a.txt
84
+ | - b.txt
85
+ | - d/
86
+ | - aa.txt
87
+ "
88
+
89
+ end
90
+
91
+ def self.if_not_repository branch
92
+ return nil if branch # Fine if there's a branch
93
+
94
+ Xiki.quote "
95
+ > Not a repository
96
+ This dir isn't a git repository.
97
+ |
98
+ > Create a repository?
99
+ - setup/create/
100
+ "
101
+ end
102
+
103
+ def self.push default_branch, branch=nil
104
+ # If no branch, use default
105
+ if branch.nil?
106
+ return "- #{default_branch}/"
107
+ end
108
+
109
+ Gito.push branch, "project - #{Dir.pwd}"
110
+ nil
111
+ end
112
+
113
+ def self.branch_name dir=nil
114
+ dir ||= Dir.pwd
115
+ Console.run("git status", :sync=>true, :dir=>dir)[/# On branch (.+)/, 1]
116
+ end
117
+
118
+ def self.diff *args
119
+ if args == [".commit"]
120
+ return View.prompt "Type a commit message."
121
+ end
122
+
123
+ path, quote = nil, nil
124
+ if args.any?
125
+ args = args.join "/"
126
+ path, quote = args =~ /\|/ ?
127
+ args.match(/(.+?)\|(.+)/)[1..2] :
128
+ args
129
+ end
130
+
131
+ Gito.diff :expand, "project - #{Dir.pwd}", path, quote
132
+ nil
133
+ end
134
+
135
+ def self.log *args
136
+ search = "" # Don't handle this for now
137
+ Gito.log search, "project - #{Dir.pwd}", *args
138
+ end
139
+
140
+ def self.add
141
+ Gito.add "project - #{Dir.pwd}"
142
+ end
143
+
144
+ def self.commit message=nil
145
+ return View.prompt "Enter a commit message" if message.nil?
146
+
147
+ Gito.commit message, "project - #{Dir.pwd}"
148
+ end
149
+
150
+ def self.show_log_one_file
151
+ Gito.show_log_one_file
152
+ end
153
+
154
+ def self.methods_by_date path
155
+ txt = Console.sync "git blame \"#{path}\""
156
+ txt = txt.split "\n"
157
+
158
+ txt = txt.select{|o| o =~ /\) *def /} # Remove all but method definitions
159
+ txt.sort!{|a, b| a[/....-..-.. ..:..:../] <=> b[/....-..-.. ..:..:../]} # Sort by date
160
+ txt.each{|o| o.sub! /.+?\) /, ''}
161
+ txt = txt.reverse
162
+ end
163
+
164
+ end
165
+
166
+
167
+ # Old git menu
168
+ # - Gito.menu/
169
+ # - project - /projects/xiki/xiki_git/
170
+ # + .create/
171
+ # + .diff_unadded/
172
+ # + .diff_unadded :expand/
173
+ # + .diff/
174
+ # + .diff :expand/
175
+ # + .push "master"
176
+ # + .pull
177
+ # + .log ""/
178
+ # + .log :expand/
179
+ # + .log_by_file/
180
+ # + .status/
181
+ # + .status_tree/
182
+ # + .branches/
183
+ # + .stash/
184
+ # - .files/
185
+ # - .format_diff_command "git diff 2b58e1e3b59ff8b5a6c5baf355501c0771b53097 code.rb"/
@@ -0,0 +1,785 @@
1
+ # Note:
2
+ # This file (git.rb) has sort a a weird implementation currently, because
3
+ # repository.rb was recently mergend into git.rb. Repository.rb used to be
4
+ # separate and behaved as a common interface to git.rb and svn.rb.
5
+
6
+ class Gito
7
+
8
+ def self.diff_internal command, dir
9
+ txt = Console.run(command, :sync => true, :dir => dir)
10
+
11
+ if Keys.prefix_u
12
+ txt.gsub!(/\c[\[31m(.*?)\c[\[m/, "\(\-\\1\-\)")
13
+ txt.gsub!(/\c[\[32m(.*?)\c[\[m/, "\(\+\\1\+\)")
14
+ txt.gsub!(/\c[\[\d*m/, '')
15
+ txt.gsub!("\-\)\(\-", '') # Merge adjacent areas
16
+ txt.gsub!("\+\)\(\+", '')
17
+ txt.gsub!(/^./, " \\0") # Add space at beginning of all non-blank lines
18
+ txt.gsub!(/^ @/, '@')
19
+ # Find whole lines
20
+ txt.gsub!(/^ \(\+(.*)\+\)$/) {|m| $1.index("\(\+") ? m : "+#{$1}" }
21
+ txt.gsub!(/^ \(\-(.*)\-\)$/) {|m| $1.index("\(\-") ? m : "-#{$1}" }
22
+ # Remove empty (--)'s
23
+ txt.gsub! /\([+-][+-]\)/, ''
24
+ else
25
+ txt.gsub! /^ $/, ''
26
+ end
27
+
28
+ txt
29
+ end
30
+
31
+ def self.status_internal txt
32
+ txt.gsub!(/^#\t(.+?): +/, "- \\1: ")
33
+ txt.gsub!(/^#\t/, "- ")
34
+ txt.gsub!(/^#\n/, '')
35
+ txt.gsub!(/^#/, '|')
36
+ txt.gsub! /.+ \.\..+\n/, ""
37
+ txt
38
+ end
39
+
40
+ # Takes as input the output of .status_internal.
41
+ def self.status_to_hash txt
42
+ result = {}
43
+
44
+ # Pull out unadded
45
+ unadded = txt[/^\| Changed but not updated:.+/m]
46
+ result[:unadded] =
47
+ if unadded
48
+ unadded.sub! /\A(^\|[^\n]+\n)+/m, '' # Remove first few headings
49
+ unadded.sub! /^\|.+/m, '' # Remove future sections
50
+ unadded.scan(/^- (.+?): (.+)/)
51
+ else
52
+ []
53
+ end
54
+
55
+ # Pull out added
56
+ added = txt[/^\| Changes to be committed:.+/m]
57
+ result[:added] =
58
+ if added
59
+ added.sub! /\A(^\|[^\n]+\n)+/m, '' # Remove first few headings
60
+ added.sub! /^\|.+/m, '' # Remove future sections
61
+ added.scan(/^- (.+?): (.+)/)
62
+ else
63
+ []
64
+ end
65
+
66
+ # Pull out untracked
67
+ untracked = txt[/^\| Untracked files:.+/m]
68
+ result[:untracked] =
69
+ if untracked
70
+ files = untracked.scan(/^- (.+)/)
71
+ files.map!{|i| ['untracked', i[0]]}
72
+ else
73
+ []
74
+ end
75
+
76
+ result
77
+ end
78
+
79
+
80
+
81
+ # Reusable - used to be in repository.rb
82
+
83
+ @@git_diff_options = ' -U2 '
84
+ #@@git_diff_options = ' -U2 -w ' # -w caused a git segfault :/
85
+
86
+ def self.svn?
87
+ File.exists?("#{View.dir}.svn")
88
+ end
89
+
90
+ def self.tag to, from=nil
91
+ unless self.url
92
+ return "Error: Git.url isn't set!"
93
+ end
94
+ from ||= "trunk"
95
+ command = "svn -m \"Tag: Create #{from} tag\" cp #{Gito.url}/#{from} #{Gito.url}/#{to}"
96
+ Console.run(command)
97
+ end
98
+
99
+ def self.url= url
100
+ @@url = url
101
+ end
102
+
103
+ def self.url
104
+ @@url
105
+ end
106
+
107
+ def self.menu project=nil
108
+ dir = self.extract_dir project
109
+
110
+ # If no project, show all projects
111
+ if project.nil?
112
+ result = []
113
+
114
+ # If current dir is in a repos, add it
115
+ current_dir_repos = self.git_path
116
+ result << FileTree.add_slash_maybe("current dir - #{current_dir_repos ? current_dir_repos : View.dir}")
117
+
118
+ # If current dir isn't one, try after bar
119
+ if ! current_dir_repos and View.bar?
120
+ after_bar = View.dir_of_after_bar
121
+ current_dir_repos = self.git_path(after_bar)
122
+ result << FileTree.add_slash_maybe(
123
+ "upper - #{current_dir_repos ? current_dir_repos : after_bar}")
124
+ end
125
+
126
+ result << "tmp dir - /tmp/t1/"
127
+
128
+ return result
129
+ end
130
+
131
+ branch = self.branch_name dir
132
+ # If project, show options
133
+ %Q[
134
+ + .create/
135
+ + .diff_unadded/
136
+ + .diff_unadded :expand/
137
+ + .diff/
138
+ + .diff :expand/
139
+ + .push "#{branch}"
140
+ + .pull
141
+ + .log ""/
142
+ + .log :expand/
143
+ + .log_by_file/
144
+ + .status/
145
+ + .status_tree/
146
+ + .branches/
147
+ + .stash/
148
+ - .files/
149
+ - .format_diff_command "git diff 2b58e1e3b59ff8b5a6c5baf355501c0771b53097 code.rb"/
150
+ ].unindent
151
+ end
152
+
153
+ def self.branch_name dir=nil
154
+ dir ||= View.dir
155
+ Console.run("git status", :sync=>true, :dir=>dir)[/# On branch (.+)/, 1]
156
+ end
157
+
158
+ # Shows revs for one file
159
+ def self.log_by_file search, limit, project, file=nil, rev=nil, line=nil
160
+ dir = self.extract_dir project
161
+ if file.nil? # If no file, tell them they have to paste it
162
+ return "- Replace this line with a path - I'm normally called via Keys.show_log_one_file"
163
+ end
164
+
165
+ if rev.nil? # If no rev, list all revs
166
+ search = "-S'#{search}'" unless search.empty?
167
+ txt = Console.run "git log -#{limit} --pretty=oneline #{search} #{file}", :sync=>true, :dir=>dir
168
+ txt.gsub! ':', '-'
169
+ txt.gsub! /(.+?) (.+)/, "\\2) \\1"
170
+ txt.gsub! /^- /, ''
171
+ return txt.gsub!(/^/, '+ ')
172
+ end
173
+
174
+ if line.nil? # If no diff, show diff
175
+ # File passed, show diff
176
+ txt = Gito.diff_internal "git show #{@@git_diff_options} --pretty=oneline #{rev} #{file}", dir
177
+ txt.sub!(/.+?@@/m, '@@')
178
+ return txt.gsub /^/, '|'
179
+ end
180
+
181
+ # Line passed, so jump to it
182
+ project.sub! /^project - /, ''
183
+ self.jump_to_file_in_tree project
184
+ nil
185
+ end
186
+
187
+ def self.log search, project, rev=nil, file=nil, *line
188
+ dir = self.extract_dir project
189
+
190
+ if search == :expand
191
+ return "- implement!"
192
+ end
193
+
194
+ if rev.nil? # If no rev, list all revs
195
+ search = "-S'#{search}'" unless search.empty?
196
+ txt = Console.run "git log -1000 --pretty=oneline #{search}", :sync=>true, :dir=>dir
197
+ txt.gsub! ':', '-'
198
+ txt.gsub! /(.+?) (.+)/, "\\2) \\1/"
199
+ txt.gsub! /^- /, ''
200
+ return txt.gsub!(/^/, '+ ')
201
+ end
202
+ if file.nil? # If no file, show files for rev
203
+ # Rev passed, so show all diffs
204
+ txt = Gito.diff_internal "git show --pretty=oneline --name-status #{rev}", dir
205
+ txt.sub! /^.+\n/, '' # Remove 1st line?
206
+ txt.gsub! /^([A-Z])\t/, "\\1) "
207
+ txt.gsub! /^M\) /, ''
208
+ return txt.split("\n").sort.map{|l| "+ #{l}\n"}.join('')
209
+ end
210
+ if line.empty? # If no line but file passed, show diff
211
+ txt = Gito.diff_internal "git show #{@@git_diff_options} --pretty=oneline #{rev} #{file}", dir
212
+ txt.sub!(/.+?@@/m, '@@')
213
+ txt.gsub! /^/, '|'
214
+ ENV['no_slash'] = "1"
215
+ return txt
216
+ end
217
+
218
+ # Line was passed
219
+
220
+ # Line passed, so jump to file
221
+ project.sub! /^project - /, ''
222
+ self.jump_to_file_in_tree project
223
+ nil
224
+ end
225
+
226
+ def self.diff_one_file
227
+ self.git_diff_one_file
228
+ end
229
+
230
+ def self.git_diff_one_file
231
+
232
+ repos = self.git_path # Get root of repos
233
+ relative = View.file.sub(/^#{repos}/, '') # Split off root from relative path
234
+ relative.sub! /^\//, ''
235
+
236
+ prefix = Keys.prefix :clear=>true
237
+
238
+ if prefix == :u
239
+ orig_path = "/tmp/#{View.file_name}__orig"
240
+
241
+ # Get relative path
242
+ txt = Console.run "git show HEAD:#{relative}", :sync=>true, :dir=>repos
243
+ File.open(orig_path, "w") { |f| f << txt }
244
+
245
+ $el.ediff_files orig_path, View.file
246
+
247
+ return
248
+ end
249
+
250
+ # Insert codetree
251
+ Launcher.open(
252
+ "- Gito.menu/\n - project - #{repos}\n - .diff #{Line.number}/\n - #{relative}",
253
+ :no_search=>true
254
+ )
255
+ end
256
+
257
+ def self.show_log
258
+ dir = Keys.bookmark_as_path :prompt=>"Enter a bookmark to show the log for: "
259
+ Launcher.open("- Gito.menu/\n - project - #{dir}\n - .log ''/")
260
+ end
261
+
262
+ def self.show_log_one_file
263
+ repos = self.git_path # Get root of repos
264
+ relative = View.file.sub(/^#{repos}/, '') # Split off root from relative path
265
+ relative.sub! /^\//, '' # Insert codetree
266
+
267
+ Launcher.open(
268
+ "- Gito.menu/\n - project - #{repos}\n - .log_by_file \"\", 10/\n - #{relative}"
269
+ )
270
+ end
271
+
272
+ def self.jump_to_file_in_tree dir, options={}
273
+ orig = View.cursor
274
+
275
+ Search.backward "^ +\|@@" unless Line.matches(/^ +\|@@/)
276
+ inbetween = View.txt(orig, View.cursor)
277
+ inbetween.gsub!(/^ +\|-.*\n/, '')
278
+ inbetween = inbetween.count("\n")
279
+ line = Line.value[/\+(\d+)/, 1]
280
+
281
+ Search.backward "^ +[+-] "
282
+ file = options[:file] || Line.without_label
283
+
284
+ $el.goto_char orig
285
+
286
+ View.open("#{dir}/#{file}")
287
+ View.to_line(line.to_i + (inbetween - 1))
288
+ Color.colorize :l
289
+ end
290
+
291
+ def self.styles_define
292
+ Styles.define :face_difflog_path_outline_rest,
293
+ :fg => "000077",
294
+ :bg => "7070bb",
295
+ :font => "arial"
296
+
297
+ # - foo (r): <here>
298
+ Styles.define :diff_subhead,
299
+ :bg => "333366", :fg => "88b", :size => "-3"
300
+
301
+ end
302
+
303
+ def self.styles
304
+ $el.cm_universal_diff_format
305
+ $el.difflog_highlight
306
+ Styles.apply "^diff.+\n", :diff_subhead
307
+ Styles.apply "^Index:? .+\n", :diff_subhead
308
+ Styles.apply "^===+\n", :diff_subhead
309
+ Styles.apply "^--- .+\n", :diff_subhead
310
+ Styles.apply "^\\+\\+\\+ .+\n", :notes_h1
311
+ Styles.apply "^\\\\.+", :cm_lighter_bold
312
+ #Styles.apply "^\\*.+\n", :treels_f_blank
313
+ Styles.apply "^@@.+\n", :diff_subhead
314
+
315
+ end
316
+
317
+ def self.git? dir
318
+ git_status = Gito.diff_internal "git status", dir
319
+ git_status !~ /^fatal: Not a git repository/
320
+ end
321
+
322
+ def self.git_path dir=nil
323
+ dir ||= View.dir
324
+ return nil unless self.git?(dir)
325
+ dir = Console.run("git rev-parse --git-dir", :sync=>true,
326
+ :dir=>dir
327
+ ).sub(".git\n", '')
328
+ dir = View.dir if dir == "" # Empty actually means it found it
329
+ FileTree.add_slash_maybe dir
330
+ end
331
+
332
+ def self.determine_dir dir
333
+ self.git_path(dir)# || Bookmarks['$tr']
334
+ end
335
+
336
+ # Called by code tree directly
337
+ def self.status_tree project
338
+ dir = self.extract_dir project
339
+ dir = Bookmarks.expand(dir)
340
+ CodeTree.tree_search_option + self.status_tree_internal(dir)
341
+ end
342
+
343
+ def self.status_tree_internal dir
344
+
345
+ if self.svn?
346
+ status = Console.run "svn st", :dir => dir, :sync => true
347
+ # Remove question files
348
+ status = status.split("\n")#.select{|l| l !~ /^\?/}
349
+ status = status.each{|l| l.sub!(/^. +/, dir)}
350
+ Tree.paths_to_tree(status)
351
+ else # git
352
+ status = Console.run "git status", :dir => dir, :sync => true
353
+
354
+ # Grab out modified:...
355
+ found = status.scan(/^#\s+modified: +(.+)/)
356
+ result = []
357
+ found.each do |m|
358
+ result << "#{dir}#{m[0]}"
359
+ end
360
+ Tree.paths_to_tree(result)
361
+ end
362
+ end
363
+
364
+ def self.clean! txt
365
+ txt.gsub!(/^ ?index .+\n/, '')
366
+ txt.gsub!(/^ ?--- .+\n/, '')
367
+ txt.gsub!(/^ ?\+\+\+ .+\n/, '')
368
+ end
369
+
370
+ def self.extract_dir project
371
+ project.sub(/.+? - /, '').sub(/\/$/, '')
372
+ end
373
+
374
+ def self.status project, file=nil
375
+ dir = self.extract_dir project
376
+
377
+ if file
378
+ return View.open("#{dir}/#{file}") # If file, open it
379
+ end
380
+
381
+ # If no file, show status
382
+ txt = Console.run("git status", :sync => true, :dir => dir)
383
+
384
+ txt.gsub /^/, '| '
385
+
386
+ end
387
+
388
+ def self.diff_unadded *args
389
+ expand = args.shift if args.first.is_a? Symbol # Pull out :expand if 1st arg
390
+ project, file, line = args
391
+ dir = self.extract_dir project
392
+
393
+ self.git_diff_unadded(expand, dir, file, line)
394
+ end
395
+
396
+ def self.git_diff_unadded expand, dir, file, line
397
+ self.git_diff_or_diff_unadded true, expand, dir, file, line
398
+ end
399
+
400
+ def self.diff *args
401
+ # Parse args
402
+ expand = args.shift if args.first.is_a? Symbol # Pull out :expand if 2nd arg
403
+ line_number = args.shift if args.first.is_a? Fixnum # Pull out :expand if 2nd arg
404
+
405
+ project, file, line = args
406
+ dir = self.extract_dir project
407
+
408
+ result = if self.git?(dir)
409
+ self.git_diff expand, dir, file, line
410
+ else
411
+ self.svn_diff expand, dir, file, line
412
+ end
413
+
414
+ return nil if line
415
+
416
+ last = 0
417
+ if line_number
418
+ target_line, target_boundary = 0, 0
419
+ result.split("\n").each_with_index do |o, i|
420
+ target_line += 1 if o =~ /^\|[+ ]/
421
+ match = o[/^\|@@ .+\+(\d+)/, 1]
422
+ if target_line >= line_number
423
+ break
424
+ end
425
+ if match
426
+ target_boundary = target_line = match.to_i
427
+ last = i
428
+ end
429
+ end
430
+ last += 2
431
+ last += (target_line - target_boundary)
432
+ end
433
+
434
+ last = nil if last <= 0
435
+ Tree.<< result, :line_found=>last, :no_slash=>1
436
+ nil
437
+ end
438
+
439
+ def self.git_diff expand, dir, file, line
440
+ self.git_diff_or_diff_unadded false, expand, dir, file, line
441
+ end
442
+
443
+ def self.git_diff_or_diff_unadded is_unadded, expand, dir, file, line
444
+ if file.nil? # If launching .diff/.diff_unadded directly (not a file)
445
+
446
+ txt = Console.run "git status", :dir=>dir, :sync=>true
447
+
448
+ hash = Gito.status_to_hash(Gito.status_internal(txt))
449
+
450
+ untracked = hash[:untracked].map{|i| i[1]}
451
+ untracked.map!{|i| "+ untracked) #{i}\n"}
452
+
453
+ option = is_unadded ? "- .add\n" : "- .commit/\n"
454
+ if expand # If showing diffs right away
455
+ txt = Gito.diff_internal "git diff --patience --relative #{self.git_diff_options}#{is_unadded ? '' : ' HEAD'}", dir
456
+
457
+ if txt =~ /^fatal: ambiguous argument 'HEAD': unknown revision/
458
+ txt = self.status_hash_to_bullets hash, is_unadded
459
+ else
460
+ unless txt.empty?
461
+ self.clean! txt
462
+ txt.gsub!(/^/, ' |')
463
+ txt.gsub!(/^ \| ?diff --git .+ b\//, '- ')
464
+ end
465
+ end
466
+ else # If just showing list of files
467
+ txt = self.status_hash_to_bullets hash, is_unadded
468
+ end
469
+
470
+ # Add labels back
471
+ if is_unadded # If unadded, add labels from added (if they exist there)
472
+ hash[:added].each {|i| txt.sub! /^([+-]) #{i[1]}$/, "\\1 #{i[0]}) #{i[1]}"}
473
+ else # If added, add your label also unadded (or special)
474
+ unadded = hash[:unadded].map{|i| i[1]}
475
+ hash[:added].each do |i|
476
+ # Only add label if file is also unadded, or if label isn't 'modified'
477
+ next unless unadded.member?(i[1]) or i[0] != 'modified'
478
+ txt.sub! /^([+-]) #{i[1]}$/, "\\1 #{i[0]}) #{i[1]}"
479
+ end
480
+ end
481
+
482
+ txt << untracked.join("")
483
+
484
+ txt = "| There were no differences. Try modifying a file first.\n" if ! txt.any?
485
+ return option + txt + "- .add/\n- .delete/\n- .revert/\n"
486
+ end
487
+
488
+ if line.nil? # If no line passed, re-do diff for 1 file
489
+ # If untracked, show whole file
490
+ if Line.label =~ /^untracked/
491
+ return "|@@ +1\n" + IO.read(Bookmarks.expand("#{dir}/#{file}")).gsub(/^/, '|+').gsub("\c@", '.')
492
+ end
493
+
494
+ txt = is_unadded ?
495
+ Gito.diff_internal("git diff --patience --relative #{self.git_diff_options} #{file}", dir) :
496
+ Gito.diff_internal("git diff --patience --relative #{self.git_diff_options} HEAD #{file}", dir)
497
+ self.clean! txt
498
+ txt.gsub!(/^ ?diff .+\n/, '')
499
+ txt.gsub!(/^/, '|')
500
+ return txt
501
+ end
502
+
503
+ # If line passed, jump to it
504
+ self.jump_to_file_in_tree dir
505
+ nil
506
+ end
507
+
508
+ def self.status_hash_to_bullets hash, is_unadded
509
+ if is_unadded # If unadded, simply use unadded
510
+ return hash[:unadded].map{|i| "+ #{i[1]}\n"}.join('')
511
+ end
512
+
513
+ txt = (hash[:unadded].map{|i| "+ #{i[1]}\n"} +
514
+ hash[:added].map{|i| "+ #{i[1]}\n"}).sort.uniq.join('')
515
+
516
+ end
517
+
518
+
519
+ def self.format_diff_command command, project, line=nil
520
+ dir = self.extract_dir project
521
+
522
+ # If no line, just do diff
523
+ if line.nil?
524
+ txt = Console.run command, :dir=>dir, :sync=>true
525
+ return txt.gsub!(/^/, ' |')
526
+ end
527
+
528
+ self.jump_to_file_in_tree dir, :file=>command[/.+ (.+)/, 1]
529
+ nil
530
+ end
531
+
532
+ def self.push dest, project
533
+ dir = self.extract_dir project
534
+
535
+ Console.run "git push origin #{dest}", :dir=>dir
536
+ nil
537
+ end
538
+
539
+ def self.pull project
540
+ dir = self.extract_dir project
541
+ Console.run "git pull", :dir=>dir
542
+ nil
543
+ end
544
+
545
+ def self.code_tree_diff options={}
546
+
547
+ dir = Keys.bookmark_as_path :prompt=>"Enter a bookmark to git diff in: "
548
+ branch = self.branch_name dir
549
+
550
+ prefix = Keys.prefix :clear=>true
551
+ expand = prefix == :uu ? "" : ", :expand"
552
+
553
+ # If C-u, use new gitt menu
554
+ if prefix != :u
555
+
556
+ menu = "
557
+ - #{dir}
558
+ - @git/
559
+ ".unindent
560
+
561
+ if prefix != 8
562
+ menu << "
563
+ - push/#{branch}/
564
+ - diff/
565
+ ".unindent.gsub(/^/, " ")
566
+ end
567
+ menu.strip!
568
+
569
+ if options[:enter]
570
+ View.insert(menu)
571
+ Launcher.launch
572
+ else
573
+ View.bar if prefix == "outline"
574
+ Launcher.open(menu)
575
+ end
576
+ return
577
+ end
578
+
579
+
580
+ # TODO: Deprecated, so delete:
581
+ menu = "
582
+ - Gito.menu/
583
+ - project - #{dir}
584
+ ".unindent
585
+
586
+ if prefix != 8
587
+ menu << "
588
+ - .push \"#{branch}\"/
589
+ - .diff#{expand}/
590
+ ".unindent.gsub(/^/, " ")
591
+ end
592
+ menu.strip!
593
+
594
+ if options[:enter]
595
+ View.insert(menu)
596
+ Launcher.launch
597
+ else
598
+ View.bar if prefix == "outline"
599
+ Launcher.open(menu)
600
+ end
601
+ end
602
+
603
+ def self.code_tree_diff_unadded options={}
604
+ dir = Keys.bookmark_as_path
605
+ menu = "- Gito.menu/\n - project - #{dir}\n - .diff_unadded :expand/"
606
+ if options[:enter]
607
+ View.insert(menu)
608
+ Launcher.launch
609
+ else
610
+ Launcher.open(menu)
611
+ end
612
+ end
613
+
614
+ def self.svn_diff expand, dir, file, line, children
615
+ if file.nil? # If launching .commit directly (no file)
616
+
617
+ if expand
618
+ txt = Console.run("svn diff #{file}", :sync => true, :dir => dir)
619
+
620
+ txt.gsub!(/^===+\n/, '')
621
+ txt.gsub!(/^--- .+\n/, '')
622
+ txt.gsub!(/^\+\+\+ .+\n/, '')
623
+ txt.gsub!(/^/, ' |')
624
+ txt.gsub!(/^ \|Index: /, '- ')
625
+ return txt
626
+
627
+ else
628
+ txt = Console.run "svn status", :dir=>dir, :sync=>true
629
+
630
+ modified = txt.scan(/^M +(.+)/).map{|i| i.first}
631
+ new_files = txt.scan(/^A +(.+)/).map{|i| "new: " + i.first}
632
+
633
+ return new_files + modified
634
+ end
635
+ end
636
+
637
+ if line.nil? # If no line passed, re-do diff for 1 file
638
+ txt = Console.run("svn diff #{file}", :sync => true, :dir => dir)
639
+
640
+ txt.gsub!(/^Index: .+\n/, '')
641
+ txt.gsub!(/^===+\n/, '')
642
+ txt.gsub!(/^--- .+\n/, '')
643
+ txt.gsub!(/^\+\+\+ .+\n/, '')
644
+ txt.gsub!(/^/, '|')
645
+ return txt
646
+ end
647
+
648
+ self.jump_to_file_in_tree dir # If line passed, jump to it
649
+
650
+ nil # Be sure to have no return value
651
+
652
+ end
653
+
654
+ def self.remove_options siblings
655
+ siblings.select{|o| o !~ /^\.(commit|delete|revert|add)\// && o !~ /^\|/ }
656
+ end
657
+
658
+ def self.add project
659
+ dir = self.extract_dir project
660
+
661
+ siblings = Tree.siblings
662
+ # Error if no siblings
663
+ unless siblings.any?
664
+ return "- No files to add (they should be siblings of .add)!"
665
+ end
666
+
667
+ siblings = self.remove_options siblings
668
+ Console.run("git add #{siblings.join(' ')}", :dir=>dir)
669
+ end
670
+
671
+ def self.commit message, project
672
+ dir = self.extract_dir project
673
+
674
+ siblings = Tree.siblings :include_label=>true
675
+ # Remove "untracked (ignore)"
676
+ siblings = siblings.select{|i| i !~ /^. untracked \(ignore\)/}.map{|i| Line.without_label(:line=>i)}
677
+ siblings = self.remove_options siblings
678
+
679
+ unless siblings.any? # Error if no siblings
680
+ return ".flash - You didn't provide any files to commit (on lines next to this menu, with no blank lines)"
681
+ end
682
+
683
+ Console.run "git commit -m \"#{message}\" #{siblings.join(' ')}", :dir=>dir#, :no_enter=>true
684
+ end
685
+
686
+ def self.revert project#, file=nil
687
+ dir = self.extract_dir project
688
+
689
+ siblings = Tree.siblings :include_label=>true
690
+ siblings.map!{|i| Line.without_label(:line=>i)}
691
+
692
+ unless siblings.any? # Error if no siblings
693
+ return "- Error: No files to revert\n" +
694
+ "- They should be siblings of .revert!"
695
+ end
696
+
697
+ Console.run "git checkout #{siblings.join(' ')}", :dir=>dir #, :no_enter=>true
698
+ end
699
+
700
+ def self.delete project
701
+ dir = self.extract_dir project
702
+
703
+ siblings = Tree.siblings :include_label=>true
704
+ siblings.map!{|i| Line.without_label(:line=>i)}
705
+
706
+ unless siblings.any? # Error if no siblings
707
+ return "- Error: No files to delete\n" +
708
+ "- They should be siblings of .delete!"
709
+ end
710
+
711
+ Console.run "rm #{siblings.join(' ')}", :dir=>dir #, :no_enter=>true
712
+ end
713
+
714
+ def self.create project
715
+ "
716
+ - #{self.extract_dir(project)}/
717
+ - create: ! git init
718
+ - make test files: ! echo 'a\\na\\na' > a.txt; echo 'b\\nb\\nb' > b.txt
719
+ - add files: ! git add .
720
+ - commit: ! git commit -m \"First commit.\"
721
+ "
722
+ end
723
+
724
+ def self.files project
725
+ "- #{self.extract_dir(project)}/"
726
+ end
727
+
728
+ def self.branches project
729
+ "
730
+ - #{self.extract_dir(project)}/
731
+ - list branches:
732
+ ! git branch
733
+ ! git branch -r
734
+ - create branch:
735
+ ! git branch foo
736
+ - switch to:
737
+ ! git checkout foo
738
+ - delete:
739
+ ! git branch -d foo
740
+ - switch to main branch:
741
+ ! git checkout master
742
+ - delete remote branch:
743
+ ! git push origin :my_branch
744
+ "
745
+ end
746
+
747
+ def self.stash project
748
+ "
749
+ - #{self.extract_dir(project)}/
750
+ - Temporarily put away uncommitted changes:
751
+ ! git stash
752
+ ! git stash save \"message\"
753
+ - Restore uncommitted changes:
754
+ ! git stash apply
755
+ ! git stash pop
756
+ ! git stash drop
757
+ - list: ! git stash list
758
+ - files: ! git stash show
759
+ - diff most recest: ! git stash show --patience
760
+ ".unindent
761
+ end
762
+
763
+ def self.git_diff_options
764
+ @@git_diff_options + (Keys.prefix_u ? ' --color-words ' : '')
765
+
766
+ # Doesn't work:
767
+ # + (Keys.prefix_uu ? ' --name-only ' : '')
768
+ end
769
+
770
+ def self.search_just_push
771
+ match = Search.stop
772
+
773
+ Gito.code_tree_diff
774
+ View.to_highest
775
+
776
+ Search.isearch match
777
+ end
778
+
779
+ def self.search_repository
780
+ Gito.code_tree_diff
781
+ end
782
+
783
+ end
784
+
785
+ Gito.styles_define