soywiki 0.0.9 → 0.1.1
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.
- data/.gitignore +1 -0
- data/README.markdown +77 -24
- data/bin/soywiki-expand +5 -2
- data/bin/soywiki-ls-t +8 -6
- data/bin/soywiki-pages-linking-in +14 -18
- data/bin/soywiki-rename +40 -50
- data/lib/soywiki.rb +2 -9
- data/lib/soywiki.vim +171 -178
- metadata +4 -5
- data/website/soywiki.html +0 -446
data/.gitignore
CHANGED
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
|
-
|
101
|
-
|
102
|
-
|
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-
|
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
|
-
*
|
120
|
-
*
|
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
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
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
|
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
|
202
|
-
|
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-
|
205
|
-
add a `\
|
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\
|
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
|
-
|
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
|
-
(':
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
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!(/
|
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 =/(
|
36
|
+
RELATIVE_LINK_REGEX =/(\A\s)([A-Z][a-z]+[A-Z]\w*)/
|
55
37
|
|
56
|
-
def
|
57
|
-
MEMO << "Absolutizing
|
58
|
-
|
59
|
-
|
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,
|
62
|
-
File.open(
|
63
|
-
MEMO << " - In file #{
|
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
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
79
|
-
if oldname.
|
80
|
-
# In the directory for OldName's namespace, change all references to
|
81
|
-
#
|
82
|
-
|
83
|
-
# And in the renamed file, change all
|
84
|
-
#
|
85
|
-
|
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.
|
31
|
-
WIKI_WORD = /\b([a-z][\w_]+\.)?[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)
|