soywiki 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/MIT-LICENSE.txt +21 -0
- data/README.markdown +356 -0
- data/Rakefile +25 -4
- data/bin/soywiki +1 -1
- data/bin/soywiki-expand +56 -0
- data/bin/soywiki-ls-t +10 -0
- data/bin/soywiki-pages-linking-in +14 -13
- data/bin/soywiki-rename +75 -36
- data/lib/soywiki.rb +53 -4
- data/lib/soywiki.vim +195 -58
- data/soywiki.gemspec +2 -1
- metadata +9 -6
- data/README.md +0 -3
- data/bin/soywiki-unfurl +0 -36
data/.gitignore
CHANGED
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2011 Daniel Choi, http://danielchoi.com/software/
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,356 @@
|
|
1
|
+
# SoyWiki
|
2
|
+
|
3
|
+
SoyWiki is lightweight application that turns Vim into a fast and
|
4
|
+
powerful wiki.
|
5
|
+
|
6
|
+
A quick overview of its characteristics and features:
|
7
|
+
|
8
|
+
* flat text files
|
9
|
+
* maximum data portability
|
10
|
+
* high interoperability with Unix tools
|
11
|
+
* Vim text editing power
|
12
|
+
* super-efficient modes of wiki traversal
|
13
|
+
* Git for versioning, distributed workflows, and blaming
|
14
|
+
* CamelCase wiki words
|
15
|
+
* namespaced wiki words
|
16
|
+
* autocompletion of wiki words
|
17
|
+
* automated global renaming of wiki words
|
18
|
+
* syntax colored wiki words
|
19
|
+
* outliner-like capability with expansion commands
|
20
|
+
* operates on all POSIX systems (e.g. OS X, Linux, FreeBSD)
|
21
|
+
|
22
|
+
SoyWiki builds on Vim's strengths as a text editor and interface to the
|
23
|
+
Unix operating system, SoyWiki makes it possible to create, navigate,
|
24
|
+
and refactor wiki content at the speed of thought.
|
25
|
+
|
26
|
+
SoyWiki is good for tracking projects, contacts, ideas, and collecting
|
27
|
+
and organizing research. SoyWiki combines the affordances of notebooks,
|
28
|
+
index cards, and Post-it notes, and adds the power of hyperlinks and
|
29
|
+
automatic indexing.
|
30
|
+
|
31
|
+
SoyWiki makes a great writing aid, especially if you do your writing in
|
32
|
+
Vim. You can have SoyWiki open in multiple Vim windows, tabs, and
|
33
|
+
buffers, alongside any number of regular Vim windows. Throw in a bunch
|
34
|
+
of Vim abbreviations (`:help abbreviations`), a large monitor, and a
|
35
|
+
teapot, and you'll have your paper, essay, book, or screenplay written
|
36
|
+
in record time.
|
37
|
+
|
38
|
+
You don't need to shell out $$ for tools like [Scrivener][scriv] if you
|
39
|
+
appreciate how much more powerful Vim is for editing and navigating text
|
40
|
+
and how liberating it is to be able to store your content in the
|
41
|
+
non-proprietary, universal plain-text format. Proprietary tools and
|
42
|
+
formats will come and go every few years, but the plain text file format
|
43
|
+
and Vim are forever.
|
44
|
+
|
45
|
+
SoyWiki is free and open source.
|
46
|
+
|
47
|
+
[scriv]:http://www.literatureandlatte.com/scrivener.php
|
48
|
+
|
49
|
+
## Prerequisites
|
50
|
+
|
51
|
+
* a recent version of Vim (SoyWiki is developed against Vim 7.2 and 7.3)
|
52
|
+
* a recent version of Ruby (SoyWiki is developed using Ruby 1.9.2)
|
53
|
+
* RubyGems (if Ruby version is older than 1.9)
|
54
|
+
* a recent version of Git (1.7.0.4 or above to be safe)
|
55
|
+
|
56
|
+
The current version of SoyWiki assumes a Unix environment.
|
57
|
+
|
58
|
+
To use SoyWiki you should be fairly good at using Vim. More than 80
|
59
|
+
percent of the SoyWiki codebase implements the VimScript interface
|
60
|
+
layer.
|
61
|
+
|
62
|
+
## Installation
|
63
|
+
|
64
|
+
gem install soywiki
|
65
|
+
|
66
|
+
Test your installation by typing `soywiki -h`. You should see SoyWiki's help.
|
67
|
+
|
68
|
+
On some systems you may run into a PATH issue, where the system can't find the
|
69
|
+
`soywiki` command after installation. Please report this if you encounter this
|
70
|
+
problem, and mention what system you're using. You might want to try
|
71
|
+
|
72
|
+
sudo gem install soywiki
|
73
|
+
|
74
|
+
If you ever want to uninstall SoyWiki from your system, execute this command:
|
75
|
+
|
76
|
+
gem uninstall soywiki
|
77
|
+
|
78
|
+
... and all traces of SoyWiki will removed.
|
79
|
+
|
80
|
+
New and improved versions of SoyWiki will be released over time. To install the
|
81
|
+
latest version, just type `gem install soywiki` again.
|
82
|
+
|
83
|
+
|
84
|
+
## Starting SoyWiki
|
85
|
+
|
86
|
+
Before you start SoyWiki, create a directory that will hold your wiki
|
87
|
+
files and `cd` into it. Then you can start SoyWiki with
|
88
|
+
|
89
|
+
soywiki
|
90
|
+
|
91
|
+
You can make as many SoyWiki wikis on your system as you want just by
|
92
|
+
creating directories for them. It's not a good idea however to nest
|
93
|
+
SoyWiki wiki directories within each other, for reasons that will become
|
94
|
+
clear below.
|
95
|
+
|
96
|
+
To use MacVim as your SoyWiki Vim engine, you can run soywiki like this
|
97
|
+
|
98
|
+
SOYWIKI_VIM=mvim soywiki
|
99
|
+
|
100
|
+
or you can `export SOYWIKI_VIM=mvim` in your `~/.bash_profile` and then
|
101
|
+
just run `soywiki`.
|
102
|
+
|
103
|
+
## Basic usage
|
104
|
+
|
105
|
+
For basic use, SoyWiki works exactly like a typical wiki.
|
106
|
+
|
107
|
+
You write text, and when you want to create a new wiki page, you come up
|
108
|
+
with a WikiWord for it and format it in CamelCase. The wiki-link you
|
109
|
+
just typed will automatically be syntax-highlighted, and pressing ENTER
|
110
|
+
on it will take you to the new page. Creating WikiWords and pressing
|
111
|
+
ENTER on them is the main way of linking wiki pages together. You'll be
|
112
|
+
surprised at how powerful this simple mechanism is for organizing your
|
113
|
+
notes.
|
114
|
+
|
115
|
+
That's all you need to know to get started.
|
116
|
+
|
117
|
+
## Wiki navigation
|
118
|
+
|
119
|
+
Because SoyWiki is not just wiki but a Vim program, it lets you work a
|
120
|
+
lot faster and with more economy than browser-based wikis.
|
121
|
+
|
122
|
+
You can navigate a SoyWiki wiki very quickly with the following
|
123
|
+
commands.
|
124
|
+
|
125
|
+
* `CTRL-n` and `CTRL-p` move the cursor directly to the next or previous wiki-link on the page
|
126
|
+
* `ENTER` follows the wiki-link under the cursor
|
127
|
+
* `,f` follows the first wiki-link after the cursor
|
128
|
+
* `,-` opens a wiki-link in a split window
|
129
|
+
* `,|` does the same, but in a vertical split window
|
130
|
+
|
131
|
+
You can also use Vim's jump motions `CTRL-o` and `CTRL-i` to move back
|
132
|
+
and forth in your jump history. See `:help jump-motions` for more on
|
133
|
+
this. You can press `CTRL-^` to toggle between the current page and the
|
134
|
+
last page you looked at.
|
135
|
+
|
136
|
+
You can view all the pages in your wiki, most recently modified first,
|
137
|
+
by press `,m`. This opens both a page list and autocompletion window.
|
138
|
+
You can use the standard Vim autocompletion commands here to find the
|
139
|
+
page you want and call it up. See Vim's `:help ins-completion-menu` for
|
140
|
+
further instructions.
|
141
|
+
|
142
|
+
When you're on a wiki page and you want to see all the other wiki pages
|
143
|
+
that link in to it, press `,M`. If there is only one page that links in,
|
144
|
+
you'll be taken there automatically.
|
145
|
+
|
146
|
+
`,o` opens the first normal web hyperlink -- the ones that begin with http://
|
147
|
+
or https:// -- on or after the cursor in your default web browser.
|
148
|
+
|
149
|
+
Under the covers, SoyWiki uses the command `gnome-open` or `open` to
|
150
|
+
launch your web browser. This should cover Linux Gnome desktop and OS X
|
151
|
+
users. You can change the command SoyWiki uses to open a hyperlink by
|
152
|
+
adding this to your `~/.vimrc`:
|
153
|
+
|
154
|
+
let g:SoyWiki#browser_command = "your browser command here"
|
155
|
+
|
156
|
+
If your Vim has `netrw`, you can open a hyperlink directly in same Vim
|
157
|
+
window by putting the cursor at the beginning of a hyperlink and typing
|
158
|
+
`gf`, or `C-w f` if you want to open the webpage in a split window. See
|
159
|
+
`:help netrw` for more information.
|
160
|
+
|
161
|
+
## Wiki-link autocompletion
|
162
|
+
|
163
|
+
When you're writing a wiki page and you want to link to another page,
|
164
|
+
SoyWiki can help you autocomplete your wiki-link. Press `CTRL-x CTRL-u`
|
165
|
+
in Vim insert mode to invoke it.
|
166
|
+
|
167
|
+
|
168
|
+
## Wiki refactoring
|
169
|
+
|
170
|
+
You can rename a wiki page with`,r`. You'll see a prompt asking
|
171
|
+
you for the new name. Make sure it is valid CamelCase. After you press
|
172
|
+
ENTER, SoyWiki will rename the page and update all the links on other
|
173
|
+
pages in your wiki that need updating because of the change.
|
174
|
+
|
175
|
+
You can delete a page with `,#`.
|
176
|
+
|
177
|
+
Beyond the standard cut and paste, SoyWiki gives you four fast ways of
|
178
|
+
shuttling text from one wiki page to another.
|
179
|
+
|
180
|
+
First, highlight the text you want to move with Vim's visual mode. (See
|
181
|
+
`:help visual-mode` for more info)
|
182
|
+
|
183
|
+
Then, type
|
184
|
+
|
185
|
+
* `:SWInsert [target]` to move the text to the top of target page
|
186
|
+
* `:SWAppend [target]` to move the text to the bottom of the target page
|
187
|
+
* `:SWLinkInsert [target]` performs `:SWInsert` and replaces the text with a WikiWord link
|
188
|
+
* `:SWLinkAppend [target]` performs `:SWAppend` and replaces the text with a WikiWord link
|
189
|
+
|
190
|
+
`[target]` is the name of the file that contains the wiki page you're
|
191
|
+
targeting. Press `TAB` for autocompletion help.
|
192
|
+
|
193
|
+
These commands will open the target page (if it isn't open already) in a
|
194
|
+
split window and insert or append the selected text into it. If the
|
195
|
+
target page doesn't exist, it will be created.
|
196
|
+
|
197
|
+
You can use these shortcuts:
|
198
|
+
|
199
|
+
* `:SWInsert` → `:SWI`
|
200
|
+
* `:SWAppend` → `:SWA`
|
201
|
+
|
202
|
+
With `:SWLinkInsert` and `:SWLinkAppend` you can use tab-autocompletion
|
203
|
+
to avoid typing out the whole command name.
|
204
|
+
|
205
|
+
|
206
|
+
## Search
|
207
|
+
|
208
|
+
To search your SoyWiki wiki, type `:SWSearch [search term]`. Vim will
|
209
|
+
load any matches in the quickfix list window. If there are matches, you
|
210
|
+
can use `:cn` and `:cp` to go from match to match. See `:help quickfix`
|
211
|
+
for more QuickFix commands.
|
212
|
+
|
213
|
+
Searches are case-insensitve by default. To do a case-sensitive search,
|
214
|
+
add a `\C` to your search string, e.g.:
|
215
|
+
|
216
|
+
:SWSearch Gnu\C
|
217
|
+
|
218
|
+
Again, you can use `:SWS` as a shortcut.
|
219
|
+
|
220
|
+
Under the hood, `:SWSearch` is just a thin wrapper around the `:vimgrep`
|
221
|
+
command.
|
222
|
+
|
223
|
+
|
224
|
+
## Revision history and distributed workflows
|
225
|
+
|
226
|
+
SoyWiki delegates revision-tracking, syncing, and collaboration
|
227
|
+
workflows to Git. SoyWiki automatically creates a Git repository in
|
228
|
+
your wiki directory and automatically commits all the edits you make to
|
229
|
+
it. You can sync a SoyWiki wiki between two computers using the
|
230
|
+
standard Git push and pull commands. Collaborators can also edit a
|
231
|
+
common wiki this way, in peer to peer fashion.
|
232
|
+
|
233
|
+
SoyWiki provides a few convenient key mappings to view the revision
|
234
|
+
history of a wiki page:
|
235
|
+
|
236
|
+
* `,l` shows a `git-log` view of the revision history of the current page
|
237
|
+
* `,b` shows a `git-blame` view of the current page, which shows when each line was added and by whom.
|
238
|
+
* `:SWLogStat` shows a `git log --stat` view of the current page's revision history
|
239
|
+
|
240
|
+
You can always bypass Vim and SoyWiki altogether and use Git directly to
|
241
|
+
inspect your revision history. The Git repo for your SoyWiki wiki will
|
242
|
+
be located in the same directory as your wiki files.
|
243
|
+
|
244
|
+
To sync your SoyWiki wiki between two personal computers, just follow
|
245
|
+
the general instructions [here][git-sync].
|
246
|
+
|
247
|
+
[git-sync]:http://www-cs-students.stanford.edu/~blynn/gitmagic/ch03.html
|
248
|
+
|
249
|
+
|
250
|
+
## Namespaced WikiWords
|
251
|
+
|
252
|
+
You can get very far with SoyWiki using normal CamelCase WikiWords.
|
253
|
+
|
254
|
+
NormalWikiWord
|
255
|
+
|
256
|
+
But if you want, you can also namespace your WikiWords, like so:
|
257
|
+
|
258
|
+
namespaced.WikiWord
|
259
|
+
|
260
|
+
A namespaced WikiWord is a WikiWord prefixed by a namespace. The
|
261
|
+
namespace word must start with a lower-case letter and consist
|
262
|
+
only of letters, numbers, and underscore characters. You can't chain
|
263
|
+
namespace words together: the maximum nesting level is 1.
|
264
|
+
|
265
|
+
Namespaced WikiWords help organize your conceptual wiki space. They also
|
266
|
+
have two other benefits:
|
267
|
+
|
268
|
+
First, wiki pages that represent a namespaced WikiWord are stored under a
|
269
|
+
subdirectory named after the namespace. This can help reduce the clutter in
|
270
|
+
your wiki directory.
|
271
|
+
|
272
|
+
Second, a WikiWord namespace lets you use abbreviated links within that
|
273
|
+
namespace. For example, if you are editing a page called
|
274
|
+
`recipes.SoyMacaroni` and you want to link to another page in the same
|
275
|
+
namespace called `recipes.SoyRaspberrySmoothie` you can type the link in
|
276
|
+
this special abbreviated form:
|
277
|
+
|
278
|
+
.SoyRaspberrySmoothie
|
279
|
+
|
280
|
+
SoyWiki will know from the leading period that this is a link to another
|
281
|
+
page in the same namespace.
|
282
|
+
|
283
|
+
WikiLink autocompletion also works with abbreviated namespaced links. Just type a
|
284
|
+
period, and invoke autocompletion with `CTRL-x CTRL-u`.
|
285
|
+
|
286
|
+
|
287
|
+
## Expanding a Wiki page
|
288
|
+
|
289
|
+
SoyWiki lets you render a wiki page in "expanded" form. What this does
|
290
|
+
is expand all the wiki links on the page that appear alone on a line to
|
291
|
+
include their content inline. This works recursively in all the included
|
292
|
+
wiki pages (though it does not go into vicious circles because it only
|
293
|
+
expands each link once).
|
294
|
+
|
295
|
+
The rendered page appears in a Vim scratch buffer. From there you can
|
296
|
+
write it out to a new text file, pipe it to `lpr` to print it, or
|
297
|
+
whatever you like.
|
298
|
+
|
299
|
+
There are two forms of expansion: seamful and seamless. Seamful
|
300
|
+
expansion expands wiki links into wiki pages and clearly marks where
|
301
|
+
this has happened by including markers along with the WikiWord that was
|
302
|
+
expanded. Seamless expansion does not mark a point of expansion with
|
303
|
+
anything, and it erases the WikiWord that got expanded.
|
304
|
+
|
305
|
+
* `,x` expands a wiki page seamfully
|
306
|
+
* `,X` expands a wiki page seamlessly
|
307
|
+
|
308
|
+
Both modes of expansion are useful when you want to assemble a long
|
309
|
+
piece of writing by using one page as a master outline and linking from
|
310
|
+
this to other wiki pages that include the real content. And since
|
311
|
+
expansion is recursive, you can effectively nest outlines within
|
312
|
+
outlines, like dreams within dreams.
|
313
|
+
|
314
|
+
|
315
|
+
## Why CamelCase WikiLinks rule
|
316
|
+
|
317
|
+
Some people don't like the CamelCase (a.k.a. WikiCase) wiki link
|
318
|
+
pattern. But SoyWiki embraces it and wants everyone to adopt it, for the
|
319
|
+
following reasons:
|
320
|
+
|
321
|
+
* Besides being the original, CamelCase is the most elegantly minimalist approach to linking wiki pages together -- "with no additional markup whatsoever," as [Ward Cunningham put it][ward].
|
322
|
+
* It encourages you more than other wiki link patterns to create wiki pages with succinctly descriptive names.
|
323
|
+
* Because the link pattern is so minimal and succinct, inserting them in
|
324
|
+
your notes interrupts your flow of
|
325
|
+
thought a lot less than other wiki patterns.
|
326
|
+
* It is very conducive to storing
|
327
|
+
wiki pages in plain text files: the page names can map directly to Unix
|
328
|
+
file names without any awkward character escaping.
|
329
|
+
|
330
|
+
[ward]:http://c2.com/cgi/wiki?WikiCase
|
331
|
+
|
332
|
+
|
333
|
+
## Why name a wiki engine after a legume?
|
334
|
+
|
335
|
+
I am a fan of food made of [soy][soylink]: soy ice cream, soy milk, soy
|
336
|
+
burgers, soy butter, you name it. The word "soy" has come to signify a
|
337
|
+
newer, lighter, healthier alternative to the same old same old. SoyWiki
|
338
|
+
may not be an actual soy product, but it tries to be a wiki engine with
|
339
|
+
soy-like benefits.
|
340
|
+
|
341
|
+
[soylink]:http://www.mayoclinic.com/health/soy/NS_patient-soy
|
342
|
+
|
343
|
+
## How to contact the developer
|
344
|
+
|
345
|
+
My name is Daniel Choi. I am based in Cambridge, Massachusetts, USA, and you
|
346
|
+
can email me at dhchoi {at} gmail.com.
|
347
|
+
|
348
|
+
## How to support the SoyWiki project
|
349
|
+
|
350
|
+
If you find SoyWiki very useful, feel free to drop me a note to say so. If you
|
351
|
+
have a bug to report or a good feature to suggest, please file it on the [issue
|
352
|
+
tracker][1].
|
353
|
+
|
354
|
+
[1]:https://github.com/danchoi/soywiki/issues
|
355
|
+
|
356
|
+
|
data/Rakefile
CHANGED
@@ -5,13 +5,34 @@ require 'json'
|
|
5
5
|
require 'rake'
|
6
6
|
require 'rake/testtask'
|
7
7
|
require 'bundler'
|
8
|
-
|
8
|
+
require 'soywiki'
|
9
9
|
|
10
10
|
Bundler::GemHelper.install_tasks
|
11
11
|
|
12
|
-
desc "
|
13
|
-
task :
|
14
|
-
|
12
|
+
desc "build and push website"
|
13
|
+
task :web do
|
14
|
+
version = Soywiki::VERSION
|
15
|
+
Dir.chdir("website") do
|
16
|
+
puts "updating website"
|
17
|
+
puts `./run.sh #{Soywiki::VERSION}`
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "build website locally"
|
22
|
+
task :weblocal => :build_webpage do
|
23
|
+
Dir.chdir("website") do
|
24
|
+
`open soywiki.html`
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "build webpage"
|
29
|
+
task :build_webpage do
|
30
|
+
$LOAD_PATH.unshift 'website'
|
31
|
+
require 'gen'
|
32
|
+
Dir.chdir("website") do
|
33
|
+
html = Webpage.generate(Soywiki::VERSION)
|
34
|
+
File.open('soywiki.html', 'w') {|f| f.puts html}
|
35
|
+
end
|
15
36
|
end
|
16
37
|
|
17
38
|
desc "Run tests"
|
data/bin/soywiki
CHANGED
data/bin/soywiki-expand
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'soywiki'
|
3
|
+
|
4
|
+
# Takes any wiki link that stands alone on a line and expands it
|
5
|
+
|
6
|
+
WIKI_LINK_PATTERN = /^\s*(([a-z]\w+\.)?[A-Z][a-z]+[A-Z]\w*|\.[A-Z][a-z]+[A-Z]\w*)\s*$/
|
7
|
+
|
8
|
+
PROCESSED_FILES = []
|
9
|
+
|
10
|
+
def indent(text, level, mode)
|
11
|
+
return text if mode == 'seamless'
|
12
|
+
return text if level == 0
|
13
|
+
(': ' * level) + text
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def expand(file, mode, level=0)
|
18
|
+
PROCESSED_FILES << file
|
19
|
+
lines = File.readlines(file)
|
20
|
+
if mode == 'seamless'
|
21
|
+
lines.shift 2 # strips title
|
22
|
+
end
|
23
|
+
lines = lines.join.strip.split("\n")
|
24
|
+
lines.each do |line|
|
25
|
+
# note that the wiki link must be alone on the line to be expanded
|
26
|
+
if line =~ WIKI_LINK_PATTERN
|
27
|
+
link = line.strip
|
28
|
+
if link =~ /^\./ # short link in namespace (relative link)
|
29
|
+
namespace = file.namespace
|
30
|
+
link = [namespace, link].join
|
31
|
+
end
|
32
|
+
if File.file?(link.to_file_path) && !PROCESSED_FILES.include?(link.to_file_path)
|
33
|
+
if mode == 'seamful'
|
34
|
+
puts '.' * 10
|
35
|
+
end
|
36
|
+
expand(link.to_file_path, mode, level + 1) # recursive call
|
37
|
+
if mode == 'seamful'
|
38
|
+
puts '.' * 10
|
39
|
+
end
|
40
|
+
|
41
|
+
elsif PROCESSED_FILES.include?(link)
|
42
|
+
puts indent("#{link} [[already expanded]]", level, mode)
|
43
|
+
else
|
44
|
+
puts indent("#{link} [[no file found]]", level, mode)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
puts indent(line, level, mode)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
mode, file = *ARGV
|
53
|
+
|
54
|
+
expand(file, mode)
|
55
|
+
|
56
|
+
|
data/bin/soywiki-ls-t
ADDED
@@ -1,29 +1,30 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
|
-
|
4
|
-
class String
|
5
|
-
def is_namespaced?
|
6
|
-
self.split(".").size == 2
|
7
|
-
end
|
8
|
-
end
|
3
|
+
require 'soywiki'
|
9
4
|
|
10
5
|
def inbound_links_to?(file, page_title)
|
11
6
|
return false unless File.file?(file)
|
12
7
|
return false if (file =~ /(\.swo|\.swp)$/ || file =~ /^\./)
|
13
8
|
body = File.read(file)
|
14
|
-
body =~ /[\A\s\n\b]#{page_title}\b/
|
9
|
+
body =~ /[\A\s\n\b]#{page_title.gsub(".", "\.")}\b/
|
15
10
|
end
|
16
11
|
|
17
12
|
target_page = ARGV.first
|
18
13
|
|
19
|
-
if target_page.
|
14
|
+
if target_page.namespaced?
|
20
15
|
namespace, page = *target_page.split(".")
|
21
|
-
# find all files in this
|
22
|
-
Dir.glob("#{namespace}
|
16
|
+
# find all files in this namespace
|
17
|
+
xs = Dir.glob(File.join("#{namespace}", "*")).select do |file|
|
23
18
|
inbound_links_to?(file, target_page) || inbound_links_to?(file, ".#{page}")
|
24
|
-
end
|
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
25
|
else
|
26
|
-
Dir.glob("*
|
26
|
+
Dir.glob(File.join("**", '*')).select do |file|
|
27
27
|
inbound_links_to?(file, target_page)
|
28
|
-
end.
|
28
|
+
end.
|
29
|
+
each {|file| puts file.to_page_title}
|
29
30
|
end
|
data/bin/soywiki-rename
CHANGED
@@ -1,53 +1,92 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'soywiki'
|
3
|
+
|
2
4
|
oldname, newname = *ARGV
|
3
5
|
|
4
|
-
class String
|
5
|
-
def is_namespaced?
|
6
|
-
self.split(".").size == 2
|
7
|
-
end
|
8
|
-
end
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
File.open(file, 'w') {|f| f.puts text}
|
7
|
+
MEMO = ["Updating inbound and outbound links..."]
|
8
|
+
|
9
|
+
def report(file, oldname, newname)
|
10
|
+
MEMO << " - In #{file}: #{oldname.to_page_title} -> #{newname.to_page_title}"
|
15
11
|
end
|
16
12
|
|
17
|
-
|
13
|
+
def change_all_absolute_links(oldname, newname)
|
14
|
+
MEMO << "- Updating all absolute links"
|
15
|
+
target_files = `grep -rlF '#{oldname.to_page_title}' *`.strip.split(/\n/)
|
16
|
+
target_files.each do |file|
|
17
|
+
text = File.read(file)
|
18
|
+
text.gsub!(/\b#{oldname.to_page_title}\b/, newname.to_page_title)
|
19
|
+
File.open(file, 'w') {|f| f.puts text}
|
20
|
+
report file, oldname.to_page_title, newname.to_page_title
|
21
|
+
end
|
22
|
+
end
|
18
23
|
|
19
|
-
|
20
|
-
|
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
|
21
30
|
|
22
|
-
if
|
23
|
-
|
24
|
-
|
25
|
-
target_files = `grep -lF '\<#{old_short}\>' *`.strip.split(/\n/)
|
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/)
|
26
34
|
target_files.each do |file|
|
27
35
|
text = File.read(file)
|
28
|
-
text.gsub!(
|
36
|
+
text.gsub!(/([\b\s\n]\.)(#{oldname.short_page_title})\b/, '\1' + newname.short_page_title)
|
29
37
|
File.open(file, 'w') {|f| f.puts text}
|
38
|
+
report file, oldname.short_page_title, newname.short_page_title
|
30
39
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
text.gsub!(/([\A\s\n\b])\.([A-Z][a-z]+[A-Z]\w*)/, '\1' + newname.downcase + '.\2')
|
38
|
-
File.open(newname, 'w') {|f| f.puts text}
|
39
|
-
end
|
40
|
-
elsif !old_short && new_short
|
41
|
-
# where going from a top-level name to a namespaced one
|
42
|
-
# no action needed
|
43
|
-
elsif !old_short && !new_short
|
44
|
-
# no action needed
|
45
|
-
elsif old_short && new_short
|
46
|
-
target_files = `grep -lF '#{old_short}' *`.strip.split(/\n/)
|
47
|
-
puts target_files.inspect
|
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/)
|
48
46
|
target_files.each do |file|
|
49
47
|
text = File.read(file)
|
50
|
-
text.gsub!(
|
48
|
+
text.gsub!(/[\b\s\n]\.(#{oldname.short_page_title})\b/, "." + newname)
|
51
49
|
File.open(file, 'w') {|f| f.puts text}
|
50
|
+
report file, oldname.short_page_title, newname
|
52
51
|
end
|
53
52
|
end
|
53
|
+
|
54
|
+
RELATIVE_LINK_REGEX =/([\A\s\n\b])\.([A-Z][a-z]+[A-Z]\w*)/
|
55
|
+
|
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)
|
60
|
+
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}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
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)
|
76
|
+
end
|
77
|
+
|
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)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Finally,
|
89
|
+
|
90
|
+
change_all_absolute_links oldname, newname
|
91
|
+
|
92
|
+
puts MEMO.join("\n")
|
data/lib/soywiki.rb
CHANGED
@@ -1,8 +1,57 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
class String
|
3
|
+
def is_namespaced?
|
4
|
+
self.split(/\.|\//).size == 2
|
5
|
+
end
|
3
6
|
|
4
|
-
|
7
|
+
alias :namespaced? :is_namespaced?
|
5
8
|
|
6
|
-
|
9
|
+
# TODO change this to a Windows compatible approach
|
10
|
+
def to_file_path
|
11
|
+
self.gsub(".", "/")
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_page_title
|
15
|
+
self.gsub("/", ".")
|
16
|
+
end
|
17
|
+
|
18
|
+
def short_page_title
|
19
|
+
self.to_page_title.split('.')[1]
|
20
|
+
end
|
21
|
+
|
22
|
+
def namespace
|
23
|
+
return nil unless self.namespaced?
|
24
|
+
self.to_page_title.split('.')[0]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
module Soywiki
|
30
|
+
VERSION = '0.0.2'
|
31
|
+
WIKI_WORD = /\b([a-z][\w_]+\.)?[A-Z][a-z]+[A-Z]\w*\b|\.[A-Z][a-z]+[A-Z]\w*\b/
|
32
|
+
|
33
|
+
def self.run
|
34
|
+
if %W( -v --version -h --help).include?(ARGV.first)
|
35
|
+
puts "soywiki #{Soywiki::VERSION}"
|
36
|
+
puts "by Daniel Choi dhchoi@gmail.com"
|
37
|
+
puts
|
38
|
+
puts <<END
|
39
|
+
---
|
40
|
+
Usage: soywiki [wiki file]
|
41
|
+
|
42
|
+
Run the command in a directory you've made to contain soywiki files.
|
43
|
+
|
44
|
+
Specifying a wiki file is optional. If you don't specify a file, soywiki will
|
45
|
+
open the most recently modified wiki file.
|
46
|
+
---
|
47
|
+
END
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
vim = ENV['SOYWIKI_VIM'] || 'vim'
|
52
|
+
vimscript = File.expand_path("../soywiki.vim", __FILE__)
|
53
|
+
vim_command = "#{vim} -S #{vimscript} #{ARGV.first}"
|
54
|
+
exec vim_command
|
55
|
+
end
|
56
|
+
end
|
7
57
|
|
8
|
-
exec vim_command
|
data/lib/soywiki.vim
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
" Maintainer: Daniel Choi <dhchoi@gmail.com>
|
3
3
|
" License: MIT License (c) 2011 Daniel Choi
|
4
4
|
|
5
|
-
"
|
6
|
-
" namespace
|
7
|
-
let s:wiki_link_pattern = '\C\<\([a-z]\+\.\)\?[A-Z][a-z]\+[A-Z]\w*\>\|\.[A-Z][a-z]\+[A-Z]\w*\>'
|
5
|
+
" This regex matches namedspaced WikiWords, top-level WikiWords, and relative
|
6
|
+
" .WikiWords in a namespace
|
7
|
+
let s:wiki_link_pattern = '\C\<\([a-z][[:alnum:]_]\+\.\)\?[A-Z][a-z]\+[A-Z]\w*\>\|\.[A-Z][a-z]\+[A-Z]\w*\>'
|
8
8
|
|
9
9
|
let s:rename_links_command = 'soywiki-rename '
|
10
10
|
let s:find_pages_linking_in_command = 'soywiki-pages-linking-in '
|
11
|
+
let s:expand_command = 'soywiki-expand '
|
12
|
+
let s:ls_command = 'soywiki-ls-t '
|
11
13
|
let s:search_for_link = ""
|
12
14
|
|
13
|
-
|
14
15
|
func! s:trimString(string)
|
15
16
|
let string = substitute(a:string, '\s\+$', '', '')
|
16
17
|
return substitute(string, '^\s\+', '', '')
|
@@ -34,12 +35,25 @@ func! s:title_without_namespace(page_title)
|
|
34
35
|
endif
|
35
36
|
endfunc
|
36
37
|
|
38
|
+
func! s:namespace_of_title(page_title)
|
39
|
+
if len(split(a:page_title, '\.')) == 2
|
40
|
+
return get(split(a:page_title, '\.'), 0)
|
41
|
+
else
|
42
|
+
""
|
43
|
+
endif
|
44
|
+
endfunc
|
45
|
+
|
46
|
+
|
37
47
|
func! s:is_wiki_page()
|
38
|
-
|
39
|
-
return (match(title_line, s:wiki_link_pattern) == 0)
|
48
|
+
return (match(getline(1), s:wiki_link_pattern) == 0)
|
40
49
|
endfunc
|
41
|
-
|
42
|
-
|
50
|
+
|
51
|
+
func! s:page_title2file(page)
|
52
|
+
return substitute(a:page, '\.', '/', 'g')
|
53
|
+
endfunc
|
54
|
+
|
55
|
+
func! s:filename2pagetitle(page)
|
56
|
+
return substitute(a:page, '/', '.', 'g')
|
43
57
|
endfunc
|
44
58
|
|
45
59
|
func! s:list_pages()
|
@@ -50,13 +64,13 @@ endfunc
|
|
50
64
|
|
51
65
|
func! s:link_under_cursor()
|
52
66
|
let link = expand("<cWORD>")
|
67
|
+
" strip off non-letters at the end (e.g., a comma)
|
53
68
|
let link = substitute(link, '[^[:alnum:]]*$', '', '')
|
54
|
-
" see if
|
69
|
+
" see if we have a link relative to the namespace
|
55
70
|
if (match(link, '^\.')) == 0
|
56
71
|
" find the namespace from the page title
|
57
|
-
let link = s:page_namespace() . link
|
72
|
+
let link = s:page_namespace() . link " this link already has a period at the beginning
|
58
73
|
endif
|
59
|
-
|
60
74
|
let link = substitute(link, '^[^\.[:alnum:]]', '', '') " link may begin with period
|
61
75
|
return link
|
62
76
|
endfunc
|
@@ -89,23 +103,40 @@ func! s:find_next_wiki_link(backward)
|
|
89
103
|
endfunc
|
90
104
|
|
91
105
|
func! s:load_page(page, split)
|
92
|
-
let page = a:page
|
93
106
|
if (s:is_wiki_page())
|
94
107
|
write
|
95
108
|
endif
|
96
|
-
|
109
|
+
|
110
|
+
let file = s:page_title2file(a:page)
|
111
|
+
|
112
|
+
if (!filereadable(file))
|
97
113
|
" create the file
|
98
|
-
|
114
|
+
let namespace = s:namespace_of_title(a:page)
|
115
|
+
if len(namespace) > 0
|
116
|
+
call system("mkdir -p " . namespace)
|
117
|
+
endif
|
118
|
+
call writefile([a:page, '', ''], file)
|
99
119
|
endif
|
100
120
|
if (a:split == 2)
|
101
|
-
exec "vsplit ".
|
121
|
+
exec "vsplit ". file
|
102
122
|
else
|
103
|
-
exec "split ".
|
123
|
+
exec "split ". file
|
104
124
|
endif
|
105
125
|
if (a:split == 0)
|
106
126
|
wincmd p
|
107
127
|
close
|
108
128
|
endif
|
129
|
+
|
130
|
+
if len(s:search_for_link) > 0
|
131
|
+
let res = search(s:search_for_link, 'cw')
|
132
|
+
let s:search_for_link = ''
|
133
|
+
endif
|
134
|
+
endfunc
|
135
|
+
|
136
|
+
func! s:load_most_recently_modified_page()
|
137
|
+
let pages = split(system(s:ls_command), "\n")
|
138
|
+
let start_page = len(pages) > 0 ? get(pages, 0) : "HomePage"
|
139
|
+
call s:load_page(start_page, 0)
|
109
140
|
endfunc
|
110
141
|
|
111
142
|
func! s:delete_page()
|
@@ -114,12 +145,12 @@ func! s:delete_page()
|
|
114
145
|
call delete(file)
|
115
146
|
call system("git commit " . bufname('%') . " -m 'deletion'")
|
116
147
|
" go to most recently saved
|
117
|
-
|
118
|
-
let target = s:trimString(system("ls -t | head -1"))
|
148
|
+
let target = s:trimString(system(s:ls_command . " | head -1"))
|
119
149
|
exec "e " . target
|
120
150
|
exec "bdelete " . bufnr
|
121
151
|
redraw
|
122
152
|
echom "Deleted " . file
|
153
|
+
call s:load_most_recently_modified_page()
|
123
154
|
endfunc
|
124
155
|
|
125
156
|
func! s:prompt_for_wiki_word(prompt, default)
|
@@ -131,29 +162,34 @@ func! s:prompt_for_wiki_word(prompt, default)
|
|
131
162
|
endfunc
|
132
163
|
|
133
164
|
func! s:rename_page()
|
134
|
-
let
|
135
|
-
let
|
136
|
-
if (
|
137
|
-
|
165
|
+
let oldfile = bufname('%')
|
166
|
+
let newfile = s:page_title2file( s:prompt_for_wiki_word("Rename oldfile: ", l:oldfile) )
|
167
|
+
if (oldfile == newfile)
|
168
|
+
echo "Canceled"
|
169
|
+
return
|
170
|
+
endif
|
171
|
+
if (filereadable(newfile))
|
172
|
+
exe "echom '" . newfile . " already exists!'"
|
138
173
|
return
|
139
174
|
endif
|
140
|
-
call system("git mv " . l:
|
141
|
-
exec "e ".
|
175
|
+
call system("git mv " . l:oldfile . " " . newfile)
|
176
|
+
exec "e ". newfile
|
142
177
|
" replace all existing inbound links
|
143
178
|
" TODO replace this with a ruby script
|
144
|
-
|
179
|
+
exec "! " . s:rename_links_command . oldfile . " " . newfile
|
145
180
|
call system("git commit -am 'rename wiki page'")
|
146
181
|
e!
|
147
182
|
endfunc
|
148
183
|
|
149
184
|
func! s:create_page()
|
150
|
-
let
|
151
|
-
|
152
|
-
|
185
|
+
let title = s:prompt_for_wiki_word("New page title: ", "")
|
186
|
+
let newfile = s:page_title2file(title)
|
187
|
+
if (filereadable(newfile))
|
188
|
+
exe "echom '" . newfile . " already exists!'"
|
153
189
|
return
|
154
190
|
endif
|
155
|
-
call writefile([
|
156
|
-
exec "e ".
|
191
|
+
call writefile([s:filename2pagetitle(title), '', ''], newfile)
|
192
|
+
exec "e ". newfile
|
157
193
|
endfunc
|
158
194
|
|
159
195
|
func! s:save_revision()
|
@@ -171,7 +207,7 @@ func! s:show_revision_history(stat)
|
|
171
207
|
endfunc
|
172
208
|
|
173
209
|
func! s:show_blame()
|
174
|
-
exec ":!git blame " . bufname('%')
|
210
|
+
exec ":! git blame --date=relative " . bufname('%')
|
175
211
|
endfunc
|
176
212
|
|
177
213
|
|
@@ -180,9 +216,9 @@ endfunc
|
|
180
216
|
|
181
217
|
func! s:get_page_list()
|
182
218
|
if len(bufname('%')) == 0
|
183
|
-
let s:page_list = split(system(
|
219
|
+
let s:page_list = split(system(s:ls_command), "\n")
|
184
220
|
else
|
185
|
-
let s:page_list = split(system("
|
221
|
+
let s:page_list = split(system(s:ls_command . " | grep -vF '" . bufname('%') . "'" ), "\n")
|
186
222
|
endif
|
187
223
|
endfunction
|
188
224
|
|
@@ -216,6 +252,8 @@ func! s:reduce_matches()
|
|
216
252
|
endfunc
|
217
253
|
|
218
254
|
function! s:page_list_window(complete_function, prompt)
|
255
|
+
" remember the original window
|
256
|
+
let s:return_to_winnr = winnr()
|
219
257
|
topleft split page-list-buffer
|
220
258
|
setlocal buftype=nofile
|
221
259
|
setlocal noswapfile
|
@@ -224,6 +262,7 @@ function! s:page_list_window(complete_function, prompt)
|
|
224
262
|
inoremap <silent> <buffer> <cr> <Esc>:call <SID>select_page()<CR>
|
225
263
|
inoremap <buffer> <Tab> <Esc>:call <SID>reduce_matches()<cr>
|
226
264
|
noremap <buffer> q <Esc>:close<cr>
|
265
|
+
inoremap <buffer> <Esc> <Esc>:close<cr>
|
227
266
|
exec "setlocal completefunc=" . a:complete_function
|
228
267
|
" c-p clears the line
|
229
268
|
call setline(1, a:prompt)
|
@@ -292,6 +331,7 @@ endfun
|
|
292
331
|
function! s:select_page()
|
293
332
|
let page = s:trimString( get(split(getline(line('.')), ": "), 1) )
|
294
333
|
close
|
334
|
+
exe s:return_to_winnr . "wincmd w"
|
295
335
|
if (page == '0' || page == '') " no selection
|
296
336
|
return
|
297
337
|
end
|
@@ -299,14 +339,9 @@ function! s:select_page()
|
|
299
339
|
for item in s:matching_pages
|
300
340
|
if (item == page)
|
301
341
|
call s:load_page(page, 0)
|
302
|
-
|
303
342
|
break
|
304
343
|
end
|
305
344
|
endfor
|
306
|
-
echo s:search_for_link
|
307
|
-
if len(s:search_for_link) > 0
|
308
|
-
call search('\<' . s:search_for_link . '\>')
|
309
|
-
endif
|
310
345
|
endfunction
|
311
346
|
|
312
347
|
"------------------------------------------------------------------------
|
@@ -319,11 +354,7 @@ func! s:list_pages_linking_in()
|
|
319
354
|
let s:pages_linking_in = split(system(s:find_pages_linking_in_command . s:page_title()), "\n")
|
320
355
|
let s:search_for_link = s:title_without_namespace( s:page_title())
|
321
356
|
if len(s:pages_linking_in) == 1
|
322
|
-
|
323
|
-
write
|
324
|
-
exec "e " . file
|
325
|
-
" not perfectly targeted but OK for now
|
326
|
-
call search(s:search_for_link)
|
357
|
+
call s:load_page(get(s:pages_linking_in, 0), 0)
|
327
358
|
elseif len(s:pages_linking_in) == 0
|
328
359
|
echom "No pages link to " . s:page_title() . "!"
|
329
360
|
else
|
@@ -358,17 +389,101 @@ function! CompletePagesLinkingIn_InSelectionWindow(findstart, base)
|
|
358
389
|
endif
|
359
390
|
endfun
|
360
391
|
|
392
|
+
"------------------------------------------------------------------------
|
393
|
+
" This appends the selected text (use visual-mode) to the page selected
|
394
|
+
" in the page selection window.
|
395
|
+
func! s:extract(...) range
|
396
|
+
if a:0 != 3
|
397
|
+
return s:error("Incorrect number of arguments")
|
398
|
+
endif
|
399
|
+
|
400
|
+
let first = a:firstline
|
401
|
+
let last = a:lastline
|
402
|
+
let file = a:1
|
403
|
+
|
404
|
+
if match(file, s:wiki_link_pattern) == -1
|
405
|
+
echom "Target page must be a WikiWord!"
|
406
|
+
return
|
407
|
+
endif
|
408
|
+
|
409
|
+
let mode = a:2 " append or insert
|
410
|
+
let link = a:3 " replace with link ?
|
411
|
+
let range = first.",".last
|
412
|
+
silent exe range."yank"
|
413
|
+
if link
|
414
|
+
let replacement = s:filename2pagetitle(file)
|
415
|
+
silent exe "norm! :".first.",".last."change\<CR>".replacement."\<CR>.\<CR>"
|
416
|
+
else
|
417
|
+
" this one just deletes the line
|
418
|
+
silent exe "norm! :".first.",".last."change\<CR>.\<CR>"
|
419
|
+
endif
|
420
|
+
if bufnr(file) == -1 || bufwinnr(bufnr(file)) == -1
|
421
|
+
if !filereadable(file)
|
422
|
+
" create the file
|
423
|
+
let page_title = s:filename2pagetitle(file)
|
424
|
+
let namespace = s:namespace_of_title(page_title)
|
425
|
+
if len(namespace) > 0
|
426
|
+
call system("mkdir -p " . namespace)
|
427
|
+
endif
|
428
|
+
call writefile([page_title, '', ''], file)
|
429
|
+
endif
|
430
|
+
exec "split ".file
|
431
|
+
else
|
432
|
+
let targetWindow = bufwinnr(bufnr(file))
|
433
|
+
exe targetWindow."wincmd w"
|
434
|
+
end
|
435
|
+
if mode == 'append'
|
436
|
+
normal G
|
437
|
+
silent put
|
438
|
+
silent put= ''
|
439
|
+
elseif mode == 'insert'
|
440
|
+
call cursor(2, 0)
|
441
|
+
silent put
|
442
|
+
end
|
443
|
+
write!
|
444
|
+
endfunc
|
445
|
+
|
446
|
+
|
447
|
+
func! s:error(str)
|
448
|
+
echohl ErrorMsg
|
449
|
+
echomsg a:str
|
450
|
+
echohl None
|
451
|
+
endfunction
|
452
|
+
|
453
|
+
func! s:insert_divider()
|
454
|
+
let divider = '------------------------------------------------------------------------'
|
455
|
+
silent put! =divider
|
456
|
+
silent put=''
|
457
|
+
endfunc
|
458
|
+
"------------------------------------------------------------------------
|
459
|
+
" SEARCH
|
460
|
+
func! s:wiki_search(pattern)
|
461
|
+
|
462
|
+
let pattern = (empty(a:pattern) ? @/ : a:pattern)
|
463
|
+
execute printf('vimgrep/%s/ %s', pattern, "**/*")
|
464
|
+
endfunc
|
465
|
+
|
361
466
|
"------------------------------------------------------------------------
|
362
467
|
" This opens a new buffer with all the lines with just WikiLinks on them
|
363
468
|
" expanded (recursively). This is not a wiki buffer but a text buffer
|
364
469
|
|
365
|
-
func! s:
|
366
|
-
|
470
|
+
func! s:expand(seamless)
|
471
|
+
if a:seamless == 1
|
472
|
+
" seamful, the default
|
473
|
+
echom "Expanding seamfully. Please wait."
|
474
|
+
let res = system(s:expand_command . " seamless " . bufname('%'))
|
475
|
+
else " seamless
|
476
|
+
echom "Expanding seamlessly. Please wait."
|
477
|
+
let res = system(s:expand_command . " seamful " . bufname('%'))
|
478
|
+
endif
|
367
479
|
vertical botright new
|
368
480
|
setlocal buftype=nofile "scratch buffer for viewing; user can write
|
369
|
-
put =res
|
370
|
-
1delete
|
371
|
-
normal 1G
|
481
|
+
silent! put =res
|
482
|
+
silent! 1delete
|
483
|
+
silent! normal 1G
|
484
|
+
redraw
|
485
|
+
echom "Expanded " . (a:seamless == 0 ? 'seamfully' : 'seamlessly') . "."
|
486
|
+
|
372
487
|
endfunc
|
373
488
|
|
374
489
|
"------------------------------------------------------------------------
|
@@ -388,6 +503,13 @@ func! s:global_mappings()
|
|
388
503
|
noremap <leader>m :call <SID>list_pages()<CR>
|
389
504
|
noremap <leader>M :call <SID>list_pages_linking_in()<CR>
|
390
505
|
noremap <silent> <leader>o :call <SID>open_href()<cr>
|
506
|
+
|
507
|
+
command! -bar -nargs=1 -range -complete=file SWAppend :<line1>,<line2>call s:extract(<f-args>, 'append', 0)
|
508
|
+
command! -bar -nargs=1 -range -complete=file SWInsert :<line1>,<line2>call s:extract(<f-args>, 'insert', 0)
|
509
|
+
command! -bar -nargs=1 -range -complete=file SWLinkAppend :<line1>,<line2>call s:extract(<f-args>, 'append', 1)
|
510
|
+
command! -bar -nargs=1 -range -complete=file SWLinkInsert :<line1>,<line2>call s:extract(<f-args>, 'insert', 1)
|
511
|
+
|
512
|
+
command! -bar -nargs=1 SWSearch :call s:wiki_search(<f-args>)
|
391
513
|
endfunc
|
392
514
|
|
393
515
|
" this checks if the buffer is a SoyWiki file (from firstline)
|
@@ -399,16 +521,27 @@ func! s:prep_buffer()
|
|
399
521
|
nnoremap <buffer> - :call <SID>follow_link_under_cursor(1)<cr>
|
400
522
|
nnoremap <buffer> \| :call <SID>follow_link_under_cursor(2)<cr>
|
401
523
|
noremap <buffer> <leader>f :call <SID>follow_link(0)<CR>
|
402
|
-
noremap <buffer> <
|
403
|
-
noremap <buffer> <
|
524
|
+
noremap <buffer> <c-n> :call <SID>find_next_wiki_link(0)<CR>
|
525
|
+
noremap <buffer> <c-p> :call <SID>find_next_wiki_link(1)<CR>
|
526
|
+
|
404
527
|
noremap <leader>c :call <SID>create_page()<CR>
|
405
|
-
command! -buffer SWDelete :call s:delete_page()
|
406
528
|
command! -buffer SWRename :call s:rename_page()
|
529
|
+
|
530
|
+
noremap <buffer> <leader>r :call <SID>rename_page()<CR>
|
531
|
+
command! -buffer SWDelete :call s:delete_page()
|
532
|
+
noremap <buffer> <leader># :call <SID>delete_page()<CR>
|
533
|
+
|
407
534
|
command! -buffer SWLog :call s:show_revision_history(0)
|
408
535
|
noremap <buffer> <leader>l :call <SID>show_revision_history(0)<CR>
|
409
536
|
command! -buffer SWLogStat :call s:show_revision_history(1)
|
410
537
|
command! -buffer SWBlame :call s:show_blame()
|
411
|
-
noremap <buffer> <leader>
|
538
|
+
noremap <buffer> <leader>b :call <SID>show_blame()<CR>
|
539
|
+
|
540
|
+
|
541
|
+
|
542
|
+
noremap <buffer> <leader>x :call <SID>expand(0)<CR>
|
543
|
+
noremap <buffer> <leader>X :call <SID>expand(1)<CR>
|
544
|
+
|
412
545
|
set nu
|
413
546
|
setlocal completefunc=CompletePage
|
414
547
|
augroup <buffer>
|
@@ -428,14 +561,9 @@ endfunc
|
|
428
561
|
|
429
562
|
call s:global_mappings()
|
430
563
|
|
431
|
-
autocmd WinEnter * call s:highlight_wikiwords()
|
564
|
+
autocmd BufReadPost,BufNewFile,WinEnter * call s:highlight_wikiwords()
|
432
565
|
autocmd BufEnter * call s:prep_buffer()
|
433
566
|
|
434
|
-
" load most recent page
|
435
|
-
let pages = split(system("ls -t" ), "\n")
|
436
|
-
let start_page = len(pages) > 0 ? get(pages, 0) : "HomePage"
|
437
|
-
call s:load_page(start_page, 0)
|
438
|
-
|
439
567
|
if (!isdirectory(".git"))
|
440
568
|
call system("git init")
|
441
569
|
echom "Created .git repository to store revisions"
|
@@ -453,3 +581,12 @@ if !exists("g:SoyWiki#browser_command")
|
|
453
581
|
endif
|
454
582
|
endif
|
455
583
|
|
584
|
+
if len(bufname("%")) == 0
|
585
|
+
call s:load_most_recently_modified_page()
|
586
|
+
else
|
587
|
+
call s:load_page(bufname("%"), 0)
|
588
|
+
endif
|
589
|
+
|
590
|
+
call s:get_page_list()
|
591
|
+
syntax on
|
592
|
+
let mapleader = ','
|
data/soywiki.gemspec
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
3
|
|
4
|
+
require 'soywiki'
|
4
5
|
Gem::Specification.new do |s|
|
5
6
|
s.name = "soywiki"
|
6
|
-
s.version =
|
7
|
+
s.version = Soywiki::VERSION
|
7
8
|
s.platform = Gem::Platform::RUBY
|
8
9
|
s.authors = ["Daniel Choi"]
|
9
10
|
s.email = ["dhchoi@gmail.com"]
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Daniel Choi
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-02-
|
17
|
+
date: 2011-02-09 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -35,9 +35,10 @@ email:
|
|
35
35
|
- dhchoi@gmail.com
|
36
36
|
executables:
|
37
37
|
- soywiki
|
38
|
+
- soywiki-expand
|
39
|
+
- soywiki-ls-t
|
38
40
|
- soywiki-pages-linking-in
|
39
41
|
- soywiki-rename
|
40
|
-
- soywiki-unfurl
|
41
42
|
extensions: []
|
42
43
|
|
43
44
|
extra_rdoc_files: []
|
@@ -46,12 +47,14 @@ files:
|
|
46
47
|
- .gitignore
|
47
48
|
- Gemfile
|
48
49
|
- Gemfile.lock
|
49
|
-
-
|
50
|
+
- MIT-LICENSE.txt
|
51
|
+
- README.markdown
|
50
52
|
- Rakefile
|
51
53
|
- bin/soywiki
|
54
|
+
- bin/soywiki-expand
|
55
|
+
- bin/soywiki-ls-t
|
52
56
|
- bin/soywiki-pages-linking-in
|
53
57
|
- bin/soywiki-rename
|
54
|
-
- bin/soywiki-unfurl
|
55
58
|
- lib/soywiki.rb
|
56
59
|
- lib/soywiki.vim
|
57
60
|
- soywiki.gemspec
|
data/README.md
DELETED
data/bin/soywiki-unfurl
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# takes any wiki link that stands alone on a line and expands it
|
4
|
-
#
|
5
|
-
WIKI_LINK_PATTERN = /^\s*(([a-z]+\.)?[A-Z][a-z]+[A-Z]\w*|\.[A-Z][a-z]+[A-Z]\w*)\s*$/
|
6
|
-
|
7
|
-
PROCESSED_FILES = []
|
8
|
-
def unfurl(file)
|
9
|
-
PROCESSED_FILES << file
|
10
|
-
lines = File.readlines(file)
|
11
|
-
lines.shift 2
|
12
|
-
lines = lines.join.strip.split("\n")
|
13
|
-
lines.each do |line|
|
14
|
-
if line =~ WIKI_LINK_PATTERN
|
15
|
-
link = line.strip
|
16
|
-
if link =~ /^\./ # short link in namespace (relative link)
|
17
|
-
namespace = file.split(".")[0]
|
18
|
-
link = [namespace, link].join
|
19
|
-
end
|
20
|
-
if File.file?(link) && !PROCESSED_FILES.include?(link)
|
21
|
-
unfurl link # recursive
|
22
|
-
elsif PROCESSED_FILES.include?(link)
|
23
|
-
puts "#{link} [already expanded]"
|
24
|
-
else
|
25
|
-
puts "#{link} [no file found]"
|
26
|
-
end
|
27
|
-
else
|
28
|
-
puts line
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
ARGV.each do |file|
|
34
|
-
unfurl(file)
|
35
|
-
end
|
36
|
-
|