soywiki 0.0.1 → 0.0.2
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 +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
|
-
|