soywiki 0.0.9 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -8,3 +8,4 @@ pkg/
8
8
  notes.txt
9
9
  *buffer
10
10
  wiki/
11
+ soywiki.html
data/README.markdown CHANGED
@@ -44,12 +44,17 @@ SoyWiki is free and open source.
44
44
  * a recent version of Vim (SoyWiki is developed against Vim 7.2 and 7.3)
45
45
  * a recent version of Ruby (SoyWiki is developed using Ruby 1.9.2)
46
46
  * RubyGems (if Ruby version is older than 1.9)
47
- * a recent version of Git (1.7.0.4 or above to be safe)
47
+ * a recent version of [Git][git] (1.7.0.4 or above to be safe)
48
+
49
+ [git]:http://git-scm.com/
48
50
 
49
51
  The current version of SoyWiki assumes a Unix environment.
50
52
 
51
53
  To use SoyWiki you should be fairly good at using Vim.
52
54
 
55
+ Most of SoyWiki's commands should work even if you don't have Git
56
+ installed. But the revision history commands will not.
57
+
53
58
  ## Installation
54
59
 
55
60
  gem install soywiki
@@ -96,28 +101,37 @@ just run `soywiki`.
96
101
  For basic use, SoyWiki works exactly like a typical wiki.
97
102
 
98
103
  You write text, and when you want to create a new wiki page, you come up
99
- with a WikiWord for it and format it in CamelCase. The WikiLink you
100
- just typed will automatically be syntax-highlighted, and pressing ENTER
101
- on it will take you to the new page. Creating WikiWords and pressing
102
- ENTER on them is the main way of linking wiki pages together. You'll be
104
+ with a WikiWord for it and format it in CamelCase. The WikiLink you just
105
+ typed will automatically be syntax-highlighted, and pressing ENTER on it
106
+ will take you to the new page. Creating WikiWords and pressing ENTER on
107
+ them is how you create wiki pages and link them together. You'll be
103
108
  surprised at how powerful this simple mechanism is for organizing your
104
109
  notes.
105
110
 
111
+ In SoyWiki, a wiki page is a simple text file that has a WikiWord title
112
+ on the first line (don't alter this line) and any text your want to
113
+ insert below that. SoyWiki will create stub WikiPages for you
114
+ automatically as you traverse WikiLinks that don't yet reference any
115
+ content.
116
+
106
117
  That's all you need to know to get started.
107
118
 
108
119
  ## Wiki navigation
109
120
 
110
- Because SoyWiki is not just wiki but also a Vim program, it lets you
111
- work a lot faster and with more economy than browser-based wikis.
112
-
113
121
  You can navigate a SoyWiki wiki very quickly with the following
114
- commands.
122
+ commands:
115
123
 
116
- * `CTRL-n` and `CTRL-p` move the cursor directly to the next or previous WikiLink on the page
124
+ * `CTRL-k` and `CTRL-j` move the cursor directly to the next or previous WikiLink on the page
117
125
  * `ENTER` follows the WikiLink under the cursor
118
126
  * `,f` follows the first WikiLink after the cursor
119
- * `,-` opens a WikiLink in a split window
120
- * `,|` does the same, but in a vertical split window
127
+ * `CTRL-l` opens a WikiLink in a split window
128
+ * `CTRL-n` does the same, but in a vertical split window
129
+ * Both `q` and `CTRL-h` close a split window
130
+
131
+ These key mappings may not be very mnemonic, but they are easy to
132
+ memorize through muscle memory and were chosen to keep the hands
133
+ stationary and the fingers near home position on a QWERTY keyboard while
134
+ navigating the wiki.
121
135
 
122
136
  You can also use Vim's jump motions `CTRL-o` and `CTRL-i` to move back
123
137
  and forth in your jump history. See `:help jump-motions` for more on
@@ -158,12 +172,22 @@ in Vim insert mode to invoke it.
158
172
 
159
173
  ## Wiki refactoring
160
174
 
161
- You can rename a wiki page with`,r`. You'll see a prompt asking
162
- you for the new name. Make sure it is valid CamelCase. After you press
163
- ENTER, SoyWiki will rename the page and update all the links on other
164
- pages in your wiki that need updating because of the change.
175
+ You can delete the current page with `:SWDelete` (shortcut: `:SWD`).
176
+
177
+ `:SWRenameTo [new name]` renames the current page. Make sure the new name
178
+ is valid CamelCase. You can put a namespace in front of the new name
179
+ as `namespace.` or `namespace/`. If you omit the namespace, the current
180
+ namespace is assumed.
181
+
182
+ When you rename a page, SoyWiki will update all the links on other pages
183
+ in your wiki that need to be updated in light of the change. (You'll see
184
+ the other links that were updated in the output.)
165
185
 
166
- You can delete a page with `,#`.
186
+ To create a wiki page directly, without first typing a WikiWord and
187
+ traversing it, type `:SWCreate` followed by the full path to the new
188
+ page. The form of the argument here should be `namespace/WikiWord`. You
189
+ may use command line file path autocomplete to fill out the namespace
190
+ subdirectory if it already exists.
167
191
 
168
192
  Beyond the standard cut and paste, SoyWiki gives you four fast ways of
169
193
  shuttling text from one wiki page to another.
@@ -190,27 +214,36 @@ You can use these shortcuts:
190
214
  * `:SWInsert` → `:SWI`
191
215
  * `:SWAppend` → `:SWA`
192
216
 
193
- With `:SWLinkInsert` and `:SWLinkAppend` you can use tab-autocompletion
194
- to avoid typing out the whole command name.
217
+ With `:SWLinkInsert` and `:SWLinkAppend` you can use Vim's command line
218
+ completion (`:help cmdline-completion`) to avoid typing out the whole command name.
219
+
220
+ Also, you can use Vim's command line history (`:help cmdline-history`)
221
+ and command line window (`:help cmdline-window`) to save keystrokes when
222
+ you want to repeatedly execute an insert or append command targeting the
223
+ same wiki page.
195
224
 
196
225
 
197
226
  ## Search
198
227
 
199
228
  To search your SoyWiki wiki, type `:SWSearch [search term]`. Vim will
200
229
  load any matches in the quickfix list window. If there are matches, you
201
- can use `:cn` and `:cp` to go from match to match. See `:help quickfix`
202
- for more QuickFix commands.
230
+ can use `:cn` and `:cp` to go from match to match, `:cl` to list the
231
+ matches, and `:cc [item number]` to see a particular match ln the list. See
232
+ `:help quickfix` to see the list of matches. for more QuickFix commands.
203
233
 
204
- Searches are case-insensitve by default. To do a case-sensitive search,
205
- add a `\C` to your search string, e.g.:
234
+ Searches are case-sensitve by default. To do a case-insensitive search,
235
+ add a `\c` to your search string, e.g.:
206
236
 
207
- :SWSearch Gnu\C
237
+ :SWSearch Gnu\c
208
238
 
209
239
  Again, you can use `:SWS` as a shortcut.
210
240
 
211
241
  Under the hood, `:SWSearch` is just a thin wrapper around the `:vimgrep`
212
242
  command.
213
243
 
244
+ Tip: You can flag important notes in your wiki content by typing flags
245
+ like TODO or IMPORTANT on the same line, and then use `:SWSearch` and
246
+ `:cl` to see all instances of them across your entire wiki.
214
247
 
215
248
  ## Revision history and distributed workflows
216
249
 
@@ -237,6 +270,14 @@ the general instructions [here][git-sync].
237
270
 
238
271
  [git-sync]:http://www-cs-students.stanford.edu/~blynn/gitmagic/ch03.html
239
272
 
273
+ If you want to edit a common SoyWiki with many other people, it's
274
+ probably best to set up a common upstream Git repository and to work
275
+ locally on a development branch before pulling the HEAD of the master
276
+ branch from origin, merging your edits into it, and pushing the merged
277
+ result back to origin. This process may be intimidating for
278
+ non-programmers, so a future version of SoyWiki may provide a more
279
+ user-friendly interface for distributed collaboration workflows.
280
+
240
281
 
241
282
  ## Namespaced WikiWords
242
283
 
@@ -306,6 +347,18 @@ other wiki pages that include the real content. And since expansion is
306
347
  recursive, you can effectively nest outlines within outlines, like
307
348
  dreams within dreams.
308
349
 
350
+
351
+ ## Extra macros
352
+
353
+ SoyWiki adds a few convenient Vim macros that you can use anytime.
354
+
355
+
356
+ * The `\` key in normal mode reformat the current paragraph. It is equivalent to
357
+ `gwap`. (`:help formatting`)
358
+ * `,-` inserts a long dashed line
359
+ * `,d` inserts the current date and time
360
+
361
+
309
362
  ## Getting help
310
363
 
311
364
  Typing `,?` will open the help webpage in a browser.
data/bin/soywiki-expand CHANGED
@@ -3,14 +3,17 @@ require 'soywiki'
3
3
 
4
4
  # Takes any wiki link that stands alone on a line and expands it
5
5
 
6
- WIKI_LINK_PATTERN = /^\s*(([a-z]\w+\.)?[A-Z][a-z]+[A-Z]\w*|\.[A-Z][a-z]+[A-Z]\w*)\s*$/
6
+ # this is different from Soywiki::WIKI_WORD in that it requires ^\s* before the
7
+ # first letter
8
+
9
+ WIKI_LINK_PATTERN = /^\s*([a-z]\w+\.)?[A-Z][a-z]+[A-Z]\w*/
7
10
 
8
11
  PROCESSED_FILES = []
9
12
 
10
13
  def indent(text, level, mode)
11
14
  return text if mode == 'seamless'
12
15
  return text if level == 0
13
- (': ' * level) + text
16
+ (':' * level) + ' ' + text
14
17
 
15
18
  end
16
19
 
data/bin/soywiki-ls-t CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'soywiki'
3
3
 
4
- xs = Dir.glob(File.join('**', '*')).select {|x|
5
- File.file?(x) &&
6
- x.gsub('/', '.') =~ Soywiki::WIKI_WORD
7
- }.sort_by {|x|
8
- File.stat(x).mtime
9
- }.reverse.map {|x| x.to_page_title}
4
+ # this emulates ls -t in unix, but searches subdirs and returns a flat list of
5
+ # files
6
+
7
+ xs = Dir.glob('*/*').
8
+ select {|x| File.file?(x) && x.gsub('/', '.') =~ Soywiki::WIKI_WORD }.
9
+ sort_by {|x| File.stat(x).mtime }.
10
+ reverse.map {|x| x.to_page_title }
11
+
10
12
  puts xs.join("\n")
@@ -2,29 +2,25 @@
2
2
  # encoding: utf-8
3
3
  require 'soywiki'
4
4
 
5
- def inbound_links_to?(file, page_title)
5
+ def contains_links_to?(file, page_title)
6
6
  return false unless File.file?(file)
7
7
  return false if (file =~ /(\.swo|\.swp)$/ || file =~ /^\./)
8
8
  body = File.read(file)
9
+ # '.' must be escaped in the regular expression to match literal
9
10
  body =~ /[\A\s\n\b]#{page_title.gsub(".", "\.")}\b/
10
11
  end
11
12
 
12
- target_page = ARGV.first
13
+ target_page = ARGV.first.dup
14
+ # make sure this is a title, not a path
15
+ target_page.gsub!("/", ".")
13
16
 
14
- if target_page.namespaced?
15
- namespace, page = *target_page.split(".")
16
- # find all files in this namespace
17
- xs = Dir.glob(File.join("#{namespace}", "*")).select do |file|
18
- inbound_links_to?(file, target_page) || inbound_links_to?(file, ".#{page}")
19
- end
20
- ys = Dir.glob(File.join("**", '*')).select do |file|
21
- inbound_links_to?(file, target_page)
22
- end
23
- (xs + ys).uniq.sort.
24
- each {|x| puts x.to_page_title}
25
- else
26
- Dir.glob(File.join("**", '*')).select do |file|
27
- inbound_links_to?(file, target_page)
28
- end.
29
- each {|file| puts file.to_page_title}
17
+
18
+ # find all files in this namespace
19
+ xs = Dir.glob("#{target_page.namespace}/*").select do |file|
20
+ contains_links_to?(file, target_page) || contains_links_to?(file, target_page.short_page_title)
21
+ end
22
+ ys = Dir.glob('*/*').select do |file|
23
+ contains_links_to?(file, target_page)
30
24
  end
25
+ (xs + ys).uniq.sort.each {|x| puts x.to_page_title}
26
+
data/bin/soywiki-rename CHANGED
@@ -3,7 +3,6 @@ require 'soywiki'
3
3
 
4
4
  oldname, newname = *ARGV
5
5
 
6
-
7
6
  MEMO = ["Updating inbound and outbound links..."]
8
7
 
9
8
  def report(file, oldname, newname)
@@ -15,78 +14,69 @@ def change_all_absolute_links(oldname, newname)
15
14
  target_files = `grep -rlF '#{oldname.to_page_title}' *`.strip.split(/\n/)
16
15
  target_files.each do |file|
17
16
  text = File.read(file)
18
- text.gsub!(/\b#{oldname.to_page_title}\b/, newname.to_page_title)
17
+ regex = /\b#{oldname.to_page_title}\b/
18
+ matches = text.scan(regex)
19
+ text.gsub!(regex, newname.to_page_title)
19
20
  File.open(file, 'w') {|f| f.puts text}
20
21
  report file, oldname.to_page_title, newname.to_page_title
21
22
  end
22
23
  end
23
24
 
24
- # Three other cases to cover, involving namespaces:
25
- #
26
- # Case 1: Oldname is namespaced, and Newname is in same namespace
27
- #
28
- # In the directory for OldName's namespace, change all referenecs to
29
- # .OldName to .NewName
30
-
31
- if oldname.namespaced? && (oldname.namespace == newname.namespace)
32
- MEMO << "- Updating relative links in same namespace"
33
- target_files = `grep -rlF '#{oldname.short_page_title}' #{oldname.namespace}/*`.strip.split(/\n/)
34
- target_files.each do |file|
35
- text = File.read(file)
36
- text.gsub!(/([\b\s\n]\.)(#{oldname.short_page_title})\b/, '\1' + newname.short_page_title)
37
- File.open(file, 'w') {|f| f.puts text}
38
- report file, oldname.short_page_title, newname.short_page_title
39
- end
40
- end
41
-
42
- # newname can be absolutized or top level or relative
43
- def change_relative_inbound_links(oldname, newname)
44
- MEMO << "- Updating relative inbound links"
45
- target_files = `grep -rlF '#{oldname.to_page_title}' #{oldname.namespace}/*`.strip.split(/\n/)
25
+ def change_unqualified_inbound_links_in_same_namespace(oldname, newname)
26
+ MEMO << "- Updating unqualified inbound links"
27
+ target_files = `grep -rlF '[^.]#{oldname.short_page_title}' #{oldname.namespace}/*`.strip.split(/\n/)
46
28
  target_files.each do |file|
47
29
  text = File.read(file)
48
- text.gsub!(/[\b\s\n]\.(#{oldname.short_page_title})\b/, "." + newname)
30
+ text.gsub!(/(\A|\s)#{oldname.short_page_title}\b/, "." + newname)
49
31
  File.open(file, 'w') {|f| f.puts text}
50
32
  report file, oldname.short_page_title, newname
51
33
  end
52
34
  end
53
35
 
54
- RELATIVE_LINK_REGEX =/([\A\s\n\b])\.([A-Z][a-z]+[A-Z]\w*)/
36
+ RELATIVE_LINK_REGEX =/(\A\s)([A-Z][a-z]+[A-Z]\w*)/
55
37
 
56
- def absolutize_relative_outbound_links(oldname, newname)
57
- MEMO << "Absolutizing relative inbound links"
58
- if File.exist?(newname.to_file_path)
59
- text = File.read(newname.to_file_path)
38
+ def absolutize_unqualified_outbound_links(oldname, newname)
39
+ MEMO << "Absolutizing unqualified inbound links"
40
+ target_file = newname.to_file_path
41
+ if File.exist?(target_file)
42
+ text = File.read(target_file)
60
43
  matches = text.scan(RELATIVE_LINK_REGEX)
61
- text.gsub!(RELATIVE_LINK_REGEX, '\1' + oldname.namespace + '.\2')
62
- File.open(newname.to_file_path, 'w') {|f| f.puts text}
63
- MEMO << " - In file #{file}: Absolutized these relative links: #{matches.inspect}"
44
+ text.gsub!(RELATIVE_LINK_REGEX, oldname.namespace + '.\1')
45
+ File.open(target_file, 'w') {|f| f.puts text}
46
+ MEMO << " - In file #{target_file}: Absolutized these unqualified links: #{matches.inspect}"
64
47
  end
65
48
  end
66
49
 
67
50
 
68
- # Case 2: Oldname is namespaced, and Newname is in different namespace
69
- if oldname.namespaced? && newname.namespaced? && (oldname.namespace != newname.namespace)
70
- # In the directory for OldName's namespace, change all references to
71
- # .OldName to newnamespace.NewName (i.e. NewName).
72
- change_relative_inbound_links(oldname, newname)
73
- # And in the renamed file, change all relative references to
74
- # .PageName to oldnamespace.PageName
75
- absolutize_relative_outbound_links(oldname, newname)
51
+ # Three other cases to cover, involving namespaces:
52
+ #
53
+ # Case 1: newname is in same namespace as oldname
54
+ #
55
+ # In the directory for OldName's namespace, change all unqualified referenecs to
56
+ # OldName to NewName
57
+
58
+ if oldname.namespace == newname.namespace
59
+ MEMO << "- Updating unqualified links in same namespace"
60
+ target_files = `grep -rlF '#{oldname.short_page_title}' #{oldname.namespace}/*`.strip.split(/\n/)
61
+ target_files.each do |file|
62
+ text = File.read(file)
63
+ text.gsub!(/(\A\s)(#{oldname.short_page_title})\b/, newname.short_page_title)
64
+ File.open(file, 'w') {|f| f.puts text}
65
+ report file, oldname.short_page_title, newname.short_page_title
66
+ end
76
67
  end
77
68
 
78
- # Case 3: Oldname is namespaced, and Newname is top level
79
- if oldname.namespaced? && !newname.namespaced?
80
- # In the directory for OldName's namespace, change all references to
81
- # .OldName to TopLevelNewName (i.e. NewName)
82
- change_relative_inbound_links(oldname, newname)
83
- # And in the renamed file, change all relative references to
84
- # .PageName to oldnamespace.PageName
85
- absolutize_relative_outbound_links(oldname, newname)
69
+ # Case 2: newname is in different namespace from oldname
70
+ if oldname.namespace != newname.namespace
71
+ # In the directory for OldName's namespace, change all unqualified references to
72
+ # OldName to newnamespace.NewName (i.e. NewName).
73
+ change_unqualified_inbound_links_in_same_namespace(oldname, newname)
74
+ # And in the renamed file, change all unqualified references to
75
+ # PageName to oldnamespace.PageName
76
+ absolutize_unqualified_outbound_links(oldname, newname)
86
77
  end
87
78
 
88
79
  # Finally,
89
-
90
80
  change_all_absolute_links oldname, newname
91
81
 
92
82
  puts MEMO.join("\n")
data/lib/soywiki.rb CHANGED
@@ -1,11 +1,5 @@
1
1
 
2
2
  class String
3
- def is_namespaced?
4
- self.split(/\.|\//).size == 2
5
- end
6
-
7
- alias :namespaced? :is_namespaced?
8
-
9
3
  # TODO change this to a Windows compatible approach
10
4
  def to_file_path
11
5
  self.gsub(".", "/")
@@ -20,15 +14,14 @@ class String
20
14
  end
21
15
 
22
16
  def namespace
23
- return nil unless self.namespaced?
24
17
  self.to_page_title.split('.')[0]
25
18
  end
26
19
  end
27
20
 
28
21
 
29
22
  module Soywiki
30
- VERSION = '0.0.9'
31
- WIKI_WORD = /\b([a-z][\w_]+\.)?[A-Z][a-z]+[A-Z]\w*\b|\.[A-Z][a-z]+[A-Z]\w*\b/
23
+ VERSION = '0.1.1'
24
+ WIKI_WORD = /\b([a-z][\w_]+\.)?[A-Z][a-z]+[A-Z]\w*\b/
32
25
 
33
26
  def self.run
34
27
  if %W( -v --version -h --help).include?(ARGV.first)