Add back vimoutliner
This commit is contained in:
parent
d79657f544
commit
540b341051
105 changed files with 19740 additions and 0 deletions
16
pack/acp/start/vimoutliner/.gitignore
vendored
Normal file
16
pack/acp/start/vimoutliner/.gitignore
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Vim
|
||||
*.sw?
|
||||
*.un?
|
||||
tags
|
||||
|
||||
# archives
|
||||
*.zip
|
||||
*.gz
|
||||
*.gzip
|
||||
|
||||
# osx noise
|
||||
.DS_Store
|
||||
|
||||
# Python
|
||||
*.pyc
|
||||
*~
|
1556
pack/acp/start/vimoutliner/CHANGELOG
Normal file
1556
pack/acp/start/vimoutliner/CHANGELOG
Normal file
File diff suppressed because it is too large
Load diff
137
pack/acp/start/vimoutliner/INSTALL
Normal file
137
pack/acp/start/vimoutliner/INSTALL
Normal file
|
@ -0,0 +1,137 @@
|
|||
Installing and Testing VimOutliner
|
||||
|
||||
|
||||
Automatic Method |vo-auto-install|
|
||||
Updating |vo-updating|
|
||||
Manual Method |vo-manual-install|
|
||||
Testing |vo-testing|
|
||||
|
||||
|
||||
Automatic Method
|
||||
|
||||
The automatic installation targets Unix-compatible platforms:
|
||||
|
||||
From tar archive
|
||||
|
||||
$ tar xzvf vimoutliner-0.3.x.tar.gz
|
||||
$ cd vimoutliner
|
||||
$ sh install.sh
|
||||
|
||||
From zip archive
|
||||
|
||||
$ unzip vimoutliner-0.3.x.zip
|
||||
$ cd vimoutliner-0.3.x
|
||||
$ sh install.sh
|
||||
|
||||
Installing with pathogen
|
||||
|
||||
If you have pathogen installed as your package manager you can clone the git repository in you
|
||||
pathogen directory:
|
||||
$ cd ~/.vim/bundle && git clone https://github.com/vimoutliner/vimoutliner.git
|
||||
|
||||
Installing using install.sh:
|
||||
|
||||
First you can decide whether to install the VimOutliner files or abort the
|
||||
process leaving everything unchanged. Assuming you confirmed the
|
||||
installation, the script creates the necessary directory tree and copies the
|
||||
files which provide the core functionality and documentation.
|
||||
|
||||
With the second question you decide whether you want to install some brand new
|
||||
add-ons, currently implementing checkboxes(enabled), hoisting(disabled)
|
||||
and smart paste(disabled), as well as several useful external scripts in the vimoutliner/scripts folder.
|
||||
|
||||
|
||||
Updating
|
||||
|
||||
Updating an existing installation might require some manual work.
|
||||
|
||||
If you are already working with a previous VimOutliner release, there is a
|
||||
slight chance that the current directory tree is different from your current
|
||||
one. In this case, you will have to manually migrate your files to the new
|
||||
locations.
|
||||
|
||||
The installation script creates unique backups of files being replaced with
|
||||
newer versions. So if you put some local customisations into, say
|
||||
$HOME/.vim/vimoutliner/vimoutlinerrc, you'll probably have to merge the backup
|
||||
with the new file by hand.
|
||||
|
||||
|
||||
Manual Method
|
||||
|
||||
You can also copy the files from the unpacked distribution tarball into their
|
||||
destination folders by yourself. The following steps are a description of what
|
||||
has to go where and assume some knowledge of your vim setup.
|
||||
|
||||
If you encounter problems, please contact the mailing list for an immediate
|
||||
solution and more complete future documentation. www.lists.vimoutliner.org
|
||||
|
||||
If you want to setup VimOutliner on a system running Microsoft Windows, the
|
||||
directory $HOME denotes the base folder of the vim installation. If you're on
|
||||
Unix based system, $HOME is as usual.
|
||||
|
||||
You need the following sub trees in your $HOME directory:
|
||||
|
||||
$HOME/.vim/
|
||||
doc/
|
||||
ftdetect/
|
||||
ftplugin/
|
||||
syntax/
|
||||
vimoutliner/
|
||||
plugins/
|
||||
scripts/
|
||||
|
||||
The distribution tarball unpacks into a directory vimoutliner with the
|
||||
following contents:
|
||||
|
||||
vimoutliner/
|
||||
plugins/ (1)
|
||||
scripts/ (1)
|
||||
doc/ (1)
|
||||
ftdetect/ (1)
|
||||
ftplugin/ (1)
|
||||
install.sh*
|
||||
syntax/ (1)
|
||||
syntax/ (1)
|
||||
vimoutlinerrc (1)
|
||||
|
||||
(1) The content of these folders should be copied to their namesakes in the
|
||||
$HOME/.vim folder
|
||||
|
||||
Your $HOME/.vimrc file should contain the lines
|
||||
|
||||
filetype plugin indent on
|
||||
syntax on
|
||||
|
||||
Finally, you need to integrate the online help provided with VimOutliner into
|
||||
the vim help system. Start vim and execute the following command:
|
||||
|
||||
:helptags $HOME/.vim/doc
|
||||
|
||||
At this point, VimOutliner should be functional. Type ":help vo" to get
|
||||
started. To get a quick overview of all VimOutliner commands you can view the
|
||||
cheatsheet with ":help votl_cheatsheet".
|
||||
|
||||
Testing Base Functionality
|
||||
|
||||
Create a text file and save it as a .otl file like vo_test.otl. Enter
|
||||
some text and verify the following:
|
||||
- Tabs indent the text
|
||||
- Different indent levels are different colors
|
||||
- Lines starting with a colon and space word-wrap
|
||||
|
||||
Lines starting with colons are body text. They should word wrap and
|
||||
should be a special color (typically green, but it can vary). Verify
|
||||
that paragraphs of body text can be reformatted with the Vim gq
|
||||
commands.
|
||||
|
||||
You can test the different VimOutliner commands by looking at the examples
|
||||
in the cheatsheet. "help votl_cheatsheet".
|
||||
|
||||
Debian Installation
|
||||
|
||||
Debian does include VimOutliner as a package. However some Debian versions
|
||||
require this line to be added to your .vimrc file:
|
||||
|
||||
syntax on
|
||||
|
||||
|
11
pack/acp/start/vimoutliner/LICENSE
Normal file
11
pack/acp/start/vimoutliner/LICENSE
Normal file
|
@ -0,0 +1,11 @@
|
|||
LICENSE
|
||||
|
||||
VimOutliner
|
||||
Copyright (C) 2001, 2003 by Steve Litt
|
||||
Copyright (C) 2004 by Noel Henson
|
||||
Licensed under the GNU General Public License (GPL), version 3
|
||||
Absolutely no warranty.
|
||||
|
||||
If your distro doesn't come with the GPL file you can find it here:
|
||||
HTML: http://www.gnu.org/copyleft/gpl.html
|
||||
Text: http://www.gnu.org/copyleft/gpl.txt
|
81
pack/acp/start/vimoutliner/README
Normal file
81
pack/acp/start/vimoutliner/README
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
VimOutliner README file
|
||||
|
||||
Introduction
|
||||
|
||||
VimOutliner is an outline processor with many of the same features
|
||||
as Grandview, More, Thinktank, Ecco, etc. Features include tree
|
||||
expand/collapse, tree promotion/demotion, level sensitive colors,
|
||||
interoutline linking, and body text.
|
||||
|
||||
What sets VimOutliner apart from the rest is that it's been constructed
|
||||
from the ground up for fast and easy authoring. Keystrokes are quick and
|
||||
easy, especially for someone knowing the Vim editor. VimOutliner can be
|
||||
used without the mouse (but is supported to the extent that Vim supports
|
||||
the mouse).
|
||||
|
||||
Many of the VimOutliner commands start with a double comma ",," because
|
||||
that's very quick to type. All VimOutliner files have the ".otl"
|
||||
extension. For help on VimOutliner type ":h vo". For an overview of
|
||||
all the most important VimOutliner commands you can type ":h votl_cheatsheet"
|
||||
when you have opened an otl file.
|
||||
|
||||
|
||||
* Usage
|
||||
|
||||
VimOutliner has been reported to help with the following tasks:
|
||||
|
||||
- Project management
|
||||
- Password wallet
|
||||
- To-do lists
|
||||
- Account and cash book
|
||||
- 'Plot device' for writing novels
|
||||
- Inventory control
|
||||
- Hierarchical database
|
||||
- Web site management
|
||||
|
||||
* Characteristics
|
||||
|
||||
- Fast and effective
|
||||
- Fully integrated with Vim
|
||||
- Extensible through plugins
|
||||
- Many post-processing scripts allow exporting to multiple formats
|
||||
- Extensive documentation
|
||||
|
||||
For more information on the use of VimOutliner see the README.detailed
|
||||
file in this directory.
|
||||
|
||||
|
||||
Installation details
|
||||
|
||||
1. Zip file
|
||||
|
||||
To install from the zip file do the following (exchange "x" with
|
||||
version number from the package you have downloaded):
|
||||
|
||||
$ unzip vimoutliner-0.3.x.zip $ cd vimoutliner-0.3.x $ sh install.sh
|
||||
|
||||
2. Gzip archive
|
||||
|
||||
To install from the gzip archive follow these steps:
|
||||
|
||||
$ tar -xzvf vimoutliner-0.3.x.tgz $ cd vimoutliner-0.3.x $ sh install.sh
|
||||
|
||||
Downloads
|
||||
|
||||
zip archives are available here:
|
||||
|
||||
https://github.com/vimoutliner/vimoutliner/downloads
|
||||
|
||||
Download of all packages can also be done from the Freshmeat site:
|
||||
|
||||
http://freecode.com/projects/vimoutliner
|
||||
|
||||
For more detailed installation instructions see the INSTALL file in
|
||||
this directory.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1
pack/acp/start/vimoutliner/README.detailed
Symbolic link
1
pack/acp/start/vimoutliner/README.detailed
Symbolic link
|
@ -0,0 +1 @@
|
|||
doc/votl.txt
|
27
pack/acp/start/vimoutliner/TODO.otl
Normal file
27
pack/acp/start/vimoutliner/TODO.otl
Normal file
|
@ -0,0 +1,27 @@
|
|||
TODO LIST
|
||||
Updated: 20140916
|
||||
:This is just a preliminary roadmap, use the issue list at
|
||||
:https://github.com/vimoutliner/vimoutliner/issues for suggesting new
|
||||
:features and register issues or bugs
|
||||
|
||||
Work planned for next version:
|
||||
Cleanup code in plugins to more efficient vim script
|
||||
Make plug mappings for all commands
|
||||
Decide on common script language, and write scripts in new language
|
||||
|
||||
Maybe/probably:
|
||||
Include a list of vim plugins that are useful with VimOutliner
|
||||
Templates
|
||||
More sort functionality
|
||||
Wiki plugin and documentation
|
||||
Documentation on how to convert VO files to mindmap programs, Grapviz and Lyx
|
||||
More colorschemes
|
||||
vimoutliner-tutor
|
||||
Documentation on how to use VO for writing
|
||||
MetaData?
|
||||
|
||||
Done:
|
||||
Remove included RCS,logs etc.
|
||||
|
||||
|
||||
|
81
pack/acp/start/vimoutliner/colors/votl_dark.vim
Normal file
81
pack/acp/start/vimoutliner/colors/votl_dark.vim
Normal file
|
@ -0,0 +1,81 @@
|
|||
let g:colors_name="VO Dark"
|
||||
hi normal guifg=white guibg=black ctermfg=gray ctermbg=black
|
||||
hi StatusLine guifg=white guibg=black ctermfg=gray ctermbg=black
|
||||
hi StatusLineNC guifg=white guibg=black ctermfg=gray ctermbg=black
|
||||
hi VertSplit guifg=white guibg=black ctermfg=gray ctermbg=black
|
||||
hi OL1 guifg=white ctermfg=gray
|
||||
hi OL2 guifg=red ctermfg=darkred
|
||||
hi OL3 guifg=lightblue ctermfg=darkblue
|
||||
hi OL4 guifg=violet ctermfg=darkmagenta
|
||||
hi OL5 guifg=white ctermfg=gray
|
||||
hi OL6 guifg=red ctermfg=darkred
|
||||
hi OL7 guifg=lightblue ctermfg=darkblue
|
||||
hi OL8 guifg=violet ctermfg=darkmagenta
|
||||
hi OL9 guifg=white ctermfg=gray
|
||||
|
||||
" colors for tags
|
||||
hi outlTags guifg=darkred ctermfg=darkred
|
||||
|
||||
" color for body text
|
||||
hi BT1 guifg=green ctermfg=darkgreen
|
||||
hi BT2 guifg=green ctermfg=darkgreen
|
||||
hi BT3 guifg=green ctermfg=darkgreen
|
||||
hi BT4 guifg=green ctermfg=darkgreen
|
||||
hi BT5 guifg=green ctermfg=darkgreen
|
||||
hi BT6 guifg=green ctermfg=darkgreen
|
||||
hi BT7 guifg=green ctermfg=darkgreen
|
||||
hi BT8 guifg=green ctermfg=darkgreen
|
||||
hi BT9 guifg=green ctermfg=darkgreen
|
||||
|
||||
" color for pre-formatted text
|
||||
hi PT1 guifg=blue ctermfg=darkcyan
|
||||
hi PT2 guifg=blue ctermfg=darkcyan
|
||||
hi PT3 guifg=blue ctermfg=darkcyan
|
||||
hi PT4 guifg=blue ctermfg=darkcyan
|
||||
hi PT5 guifg=blue ctermfg=darkcyan
|
||||
hi PT6 guifg=blue ctermfg=darkcyan
|
||||
hi PT7 guifg=blue ctermfg=darkcyan
|
||||
hi PT8 guifg=blue ctermfg=darkcyan
|
||||
hi PT9 guifg=blue ctermfg=darkcyan
|
||||
|
||||
" color for tables
|
||||
hi TA1 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA2 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA3 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA4 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA5 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA6 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA7 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA8 guifg=darkviolet ctermfg=darkcyan
|
||||
hi TA9 guifg=darkviolet ctermfg=darkcyan
|
||||
|
||||
" color for user text (wrapping)
|
||||
hi UT1 guifg=darkred ctermfg=darkcyan
|
||||
hi UT2 guifg=darkred ctermfg=darkcyan
|
||||
hi UT3 guifg=darkred ctermfg=darkcyan
|
||||
hi UT4 guifg=darkred ctermfg=darkcyan
|
||||
hi UT5 guifg=darkred ctermfg=darkcyan
|
||||
hi UT6 guifg=darkred ctermfg=darkcyan
|
||||
hi UT7 guifg=darkred ctermfg=darkcyan
|
||||
hi UT8 guifg=darkred ctermfg=darkcyan
|
||||
hi UT9 guifg=darkred ctermfg=darkcyan
|
||||
|
||||
" color for user text (non-wrapping)
|
||||
hi UB1 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB2 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB3 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB4 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB5 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB6 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB7 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB8 guifg=darkgray ctermfg=darkcyan
|
||||
hi UB9 guifg=darkgray ctermfg=darkcyan
|
||||
|
||||
" colors for folded sections
|
||||
hi Folded guifg=darkcyan guibg=bg ctermfg=darkcyan ctermbg=black
|
||||
hi FoldColumn guifg=darkcyan guibg=bg ctermfg=darkcyan ctermbg=black
|
||||
|
||||
" colors for experimental spelling error highlighting
|
||||
" this only works for spellfix.vim with will be cease to exist soon
|
||||
hi spellErr gui=underline guifg=yellow cterm=underline ctermfg=darkyellow
|
||||
hi BadWord gui=underline guifg=yellow cterm=underline ctermfg=darkyellow
|
81
pack/acp/start/vimoutliner/colors/votl_light.vim
Normal file
81
pack/acp/start/vimoutliner/colors/votl_light.vim
Normal file
|
@ -0,0 +1,81 @@
|
|||
let g:colors_name="VO Light"
|
||||
hi normal guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi StatusLine guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi StatusLineNC guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi VertSplit guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi OL1 guifg=black ctermfg=black
|
||||
hi OL2 guifg=red ctermfg=red
|
||||
hi OL3 guifg=blue ctermfg=blue
|
||||
hi OL4 guifg=darkviolet ctermfg=magenta
|
||||
hi OL5 guifg=black ctermfg=black
|
||||
hi OL6 guifg=red ctermfg=red
|
||||
hi OL7 guifg=blue ctermfg=blue
|
||||
hi OL8 guifg=darkviolet ctermfg=magenta
|
||||
hi OL9 guifg=black ctermfg=black
|
||||
|
||||
" colors for tags
|
||||
hi outlTags guifg=darkred ctermfg=darkred
|
||||
|
||||
" color for body text
|
||||
hi BT1 guifg=darkgreen ctermfg=green
|
||||
hi BT2 guifg=darkgreen ctermfg=green
|
||||
hi BT3 guifg=darkgreen ctermfg=green
|
||||
hi BT4 guifg=darkgreen ctermfg=green
|
||||
hi BT5 guifg=darkgreen ctermfg=green
|
||||
hi BT6 guifg=darkgreen ctermfg=green
|
||||
hi BT7 guifg=darkgreen ctermfg=green
|
||||
hi BT8 guifg=darkgreen ctermfg=green
|
||||
hi BT9 guifg=darkgreen ctermfg=green
|
||||
|
||||
" color for pre-formatted text
|
||||
hi PT1 guifg=darkblue ctermfg=cyan
|
||||
hi PT2 guifg=darkblue ctermfg=cyan
|
||||
hi PT3 guifg=darkblue ctermfg=cyan
|
||||
hi PT4 guifg=darkblue ctermfg=cyan
|
||||
hi PT5 guifg=darkblue ctermfg=cyan
|
||||
hi PT6 guifg=darkblue ctermfg=cyan
|
||||
hi PT7 guifg=darkblue ctermfg=cyan
|
||||
hi PT8 guifg=darkblue ctermfg=cyan
|
||||
hi PT9 guifg=darkblue ctermfg=cyan
|
||||
|
||||
" color for tables
|
||||
hi TA1 guifg=darkviolet ctermfg=cyan
|
||||
hi TA2 guifg=darkviolet ctermfg=cyan
|
||||
hi TA3 guifg=darkviolet ctermfg=cyan
|
||||
hi TA4 guifg=darkviolet ctermfg=cyan
|
||||
hi TA5 guifg=darkviolet ctermfg=cyan
|
||||
hi TA6 guifg=darkviolet ctermfg=cyan
|
||||
hi TA7 guifg=darkviolet ctermfg=cyan
|
||||
hi TA8 guifg=darkviolet ctermfg=cyan
|
||||
hi TA9 guifg=darkviolet ctermfg=cyan
|
||||
|
||||
" color for user text (wrapping)
|
||||
hi UT1 guifg=darkred ctermfg=cyan
|
||||
hi UT2 guifg=darkred ctermfg=cyan
|
||||
hi UT3 guifg=darkred ctermfg=cyan
|
||||
hi UT4 guifg=darkred ctermfg=cyan
|
||||
hi UT5 guifg=darkred ctermfg=cyan
|
||||
hi UT6 guifg=darkred ctermfg=cyan
|
||||
hi UT7 guifg=darkred ctermfg=cyan
|
||||
hi UT8 guifg=darkred ctermfg=cyan
|
||||
hi UT9 guifg=darkred ctermfg=cyan
|
||||
|
||||
" color for user text (non-wrapping)
|
||||
hi UB1 guifg=darkgray ctermfg=cyan
|
||||
hi UB2 guifg=darkgray ctermfg=cyan
|
||||
hi UB3 guifg=darkgray ctermfg=cyan
|
||||
hi UB4 guifg=darkgray ctermfg=cyan
|
||||
hi UB5 guifg=darkgray ctermfg=cyan
|
||||
hi UB6 guifg=darkgray ctermfg=cyan
|
||||
hi UB7 guifg=darkgray ctermfg=cyan
|
||||
hi UB8 guifg=darkgray ctermfg=cyan
|
||||
hi UB9 guifg=darkgray ctermfg=cyan
|
||||
|
||||
" colors for folded sections
|
||||
hi Folded guifg=darkcyan guibg=bg ctermfg=cyan ctermbg=white
|
||||
hi FoldColumn guifg=darkcyan guibg=bg ctermfg=cyan ctermbg=white
|
||||
|
||||
" colors for experimental spelling error highlighting
|
||||
" this only works for spellfix.vim with will be cease to exist soon
|
||||
hi spellErr gui=underline guifg=darkred cterm=underline ctermfg=darkred
|
||||
hi BadWord gui=underline guifg=darkred cterm=underline ctermfg=darkred
|
81
pack/acp/start/vimoutliner/colors/votl_test.vim
Normal file
81
pack/acp/start/vimoutliner/colors/votl_test.vim
Normal file
|
@ -0,0 +1,81 @@
|
|||
let g:colors_name="VO Light"
|
||||
hi normal guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi StatusLine guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi StatusLineNC guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi VertSplit guifg=black guibg=white ctermfg=white ctermbg=black
|
||||
hi OL1 guifg=black ctermfg=black
|
||||
hi OL2 guifg=red ctermfg=red
|
||||
hi OL3 guifg=blue ctermfg=blue
|
||||
hi OL4 guifg=darkviolet ctermfg=magenta
|
||||
hi OL5 guifg=black ctermfg=black
|
||||
hi OL6 guifg=red ctermfg=red
|
||||
hi OL7 guifg=blue ctermfg=blue
|
||||
hi OL8 guifg=darkviolet ctermfg=magenta
|
||||
hi OL9 guifg=black ctermfg=black
|
||||
|
||||
" colors for tags
|
||||
hi outlTags guifg=darkred ctermfg=darkred
|
||||
|
||||
" color for body text
|
||||
hi BT1 guifg=darkviolet ctermfg=magenta
|
||||
hi BT2 guifg=black ctermfg=black
|
||||
hi BT3 guifg=red ctermfg=red
|
||||
hi BT4 guifg=blue ctermfg=blue
|
||||
hi BT5 guifg=darkviolet ctermfg=magenta
|
||||
hi BT6 guifg=black ctermfg=black
|
||||
hi BT7 guifg=red ctermfg=red
|
||||
hi BT8 guifg=blue ctermfg=blue
|
||||
hi BT9 guifg=darkviolet ctermfg=magenta
|
||||
|
||||
" color for pre-formatted text
|
||||
hi PT1 guifg=darkblue ctermfg=cyan
|
||||
hi PT2 guifg=darkblue ctermfg=cyan
|
||||
hi PT3 guifg=darkblue ctermfg=cyan
|
||||
hi PT4 guifg=darkblue ctermfg=cyan
|
||||
hi PT5 guifg=darkblue ctermfg=cyan
|
||||
hi PT6 guifg=darkblue ctermfg=cyan
|
||||
hi PT7 guifg=darkblue ctermfg=cyan
|
||||
hi PT8 guifg=darkblue ctermfg=cyan
|
||||
hi PT9 guifg=darkblue ctermfg=cyan
|
||||
|
||||
" color for tables
|
||||
hi TA1 guifg=darkviolet ctermfg=cyan
|
||||
hi TA2 guifg=darkviolet ctermfg=cyan
|
||||
hi TA3 guifg=darkviolet ctermfg=cyan
|
||||
hi TA4 guifg=darkviolet ctermfg=cyan
|
||||
hi TA5 guifg=darkviolet ctermfg=cyan
|
||||
hi TA6 guifg=darkviolet ctermfg=cyan
|
||||
hi TA7 guifg=darkviolet ctermfg=cyan
|
||||
hi TA8 guifg=darkviolet ctermfg=cyan
|
||||
hi TA9 guifg=darkviolet ctermfg=cyan
|
||||
|
||||
" color for user text (wrapping)
|
||||
hi UT1 guifg=darkred ctermfg=cyan
|
||||
hi UT2 guifg=darkred ctermfg=cyan
|
||||
hi UT3 guifg=darkred ctermfg=cyan
|
||||
hi UT4 guifg=darkred ctermfg=cyan
|
||||
hi UT5 guifg=darkred ctermfg=cyan
|
||||
hi UT6 guifg=darkred ctermfg=cyan
|
||||
hi UT7 guifg=darkred ctermfg=cyan
|
||||
hi UT8 guifg=darkred ctermfg=cyan
|
||||
hi UT9 guifg=darkred ctermfg=cyan
|
||||
|
||||
" color for user text (non-wrapping)
|
||||
hi UB1 guifg=darkgray ctermfg=cyan
|
||||
hi UB2 guifg=darkgray ctermfg=cyan
|
||||
hi UB3 guifg=darkgray ctermfg=cyan
|
||||
hi UB4 guifg=darkgray ctermfg=cyan
|
||||
hi UB5 guifg=darkgray ctermfg=cyan
|
||||
hi UB6 guifg=darkgray ctermfg=cyan
|
||||
hi UB7 guifg=darkgray ctermfg=cyan
|
||||
hi UB8 guifg=darkgray ctermfg=cyan
|
||||
hi UB9 guifg=darkgray ctermfg=cyan
|
||||
|
||||
" colors for folded sections
|
||||
hi Folded guifg=darkcyan guibg=bg ctermfg=cyan ctermbg=white
|
||||
hi FoldColumn guifg=darkcyan guibg=bg ctermfg=cyan ctermbg=white
|
||||
|
||||
" colors for experimental spelling error highlighting
|
||||
" this only works for spellfix.vim with will be cease to exist soon
|
||||
hi spellErr gui=underline guifg=darkred cterm=underline ctermfg=darkred
|
||||
hi BadWord gui=underline guifg=darkred cterm=underline ctermfg=darkred
|
1331
pack/acp/start/vimoutliner/doc/votl.txt
Normal file
1331
pack/acp/start/vimoutliner/doc/votl.txt
Normal file
File diff suppressed because it is too large
Load diff
85
pack/acp/start/vimoutliner/doc/votl_cheatsheet.txt
Normal file
85
pack/acp/start/vimoutliner/doc/votl_cheatsheet.txt
Normal file
|
@ -0,0 +1,85 @@
|
|||
*votl_cheatsheet.txt* Last change: 2013-04-06
|
||||
|
||||
VIMOUTLINER CHEAT SHEET~
|
||||
|
||||
This overview has Vimoutliner specific commands for the available operations.
|
||||
Remember that all Vim commands can be performed in Vimoutliner files. This is
|
||||
especially useful for copying, pasting, moving around and similar commands.
|
||||
|
||||
For more extensive descriptions of command uses in Vimoutliner do ':h vo-command'. |vo-command|
|
||||
|
||||
List format explained: [command] [mode] [description]
|
||||
|
||||
|
||||
|
||||
CHECKBOXES~
|
||||
|
||||
,,cb normal Insert a check box on the current line/range
|
||||
,,cx normal Toggle check box state (percentage aware)
|
||||
,,cd normal Delete check boxes
|
||||
,,c% normal Create a check box with percentage placeholder
|
||||
,,cp normal Create a check box with percentage placeholder on all
|
||||
headings
|
||||
,,cz normal Compute completion for the tree below the current
|
||||
heading.
|
||||
|
||||
|
||||
EXECUTABLE LINES~
|
||||
|
||||
,,e normal Execute the executable tag line under cursor
|
||||
|
||||
|
||||
FOLDING~
|
||||
|
||||
,,1 all set foldlevel=0
|
||||
,,2 all set foldlevel=1
|
||||
,,3 all set foldlevel=2
|
||||
,,4 all set foldlevel=3
|
||||
,,5 all set foldlevel=4
|
||||
,,6 all set foldlevel=5
|
||||
,,7 all set foldlevel=6
|
||||
,,8 all set foldlevel=7
|
||||
,,9 all set foldlevel=8
|
||||
,,0 all set foldlevel=99999
|
||||
|
||||
|
||||
FORMATTING~
|
||||
|
||||
,,- all Draw dashed line
|
||||
,,s normal Sort sub-tree under cursor ascending
|
||||
,,S normal Sort sub-tree under cursor descending
|
||||
,,B normal Make body text start with a space
|
||||
,,b normal Make body text start with a colon and space
|
||||
>> normal Demote headline
|
||||
<< normal Promote headline
|
||||
<C-T> insert Demote headline
|
||||
<C-D> insert Promote headline
|
||||
Q normal Reformat (Synonym for gq)
|
||||
|
||||
|
||||
OTHER~
|
||||
|
||||
,,f normal Directory listing of the current directory
|
||||
,,w insert Save changes and return to insert mode
|
||||
,,D all VimOutliner reserved command
|
||||
|
||||
|
||||
TAGGING/INTEROUTLINE~
|
||||
|
||||
<C-K> normal Follow tag/interoutline (Synonym for Ctrl+])
|
||||
<C-N> normal Return from tag (Synonym for Ctrl+T)
|
||||
|
||||
|
||||
TIME AND DATE~
|
||||
|
||||
,,t normal Append timestamp (HH:MM:SS) to heading
|
||||
,,T normal Prepend timestamp (HH:MM:SS) to heading
|
||||
,,t insert Insert timestamp (HH:MM:SS) at cursor
|
||||
,,d normal Append datestamp (YYYY-MM-DD) to heading
|
||||
,,d insert Insert datestamp (YYYY-MM-DD) at cursor
|
||||
,,D normal Prepend datestamp (YYYY-MM-DD) to heading
|
||||
|
||||
|
||||
vim:set filetype=help textwidth=78:
|
||||
|
||||
|
26
pack/acp/start/vimoutliner/ftdetect/votl.vim
Normal file
26
pack/acp/start/vimoutliner/ftdetect/votl.vim
Normal file
|
@ -0,0 +1,26 @@
|
|||
"# #######################################################################
|
||||
"# filetype.vim: filetype loader
|
||||
"# version 0.4.0
|
||||
"# Copyright (C) 2001,2003 by Steve Litt (slitt@troubleshooters.com)
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"#
|
||||
"# You should have received a copy of the GNU General Public License
|
||||
"# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
"#
|
||||
"# Steve Litt, slitt@troubleshooters.com, http://www.troubleshooters.com
|
||||
"# #######################################################################
|
||||
|
||||
augroup filetypedetect
|
||||
au! BufRead,BufNewFile *.otl setfiletype votl
|
||||
au! BufRead,BufNewFile *.oln setfiletype xoutliner
|
||||
augroup END
|
||||
|
679
pack/acp/start/vimoutliner/ftplugin/votl.vim
Normal file
679
pack/acp/start/vimoutliner/ftplugin/votl.vim
Normal file
|
@ -0,0 +1,679 @@
|
|||
"#########################################################################
|
||||
"# ftplugin/votl.vim: VimOutliner functions, commands and settings
|
||||
"# version 0.4.0
|
||||
"# Copyright (C) 2001,2003 by Steve Litt (slitt@troubleshooters.com)
|
||||
"# Copyright (C) 2004,2014 by Noel Henson (noelwhenson@gmail.com)
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"#
|
||||
"# You should have received a copy of the GNU General Public License
|
||||
"# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
"#
|
||||
"# Steve Litt, slitt@troubleshooters.com, http://www.troubleshooters.com
|
||||
"#########################################################################
|
||||
|
||||
" Load the plugin {{{1
|
||||
" Prevent the plugin from being loaded twice
|
||||
"if exists("b:did_ftplugin")
|
||||
" finish
|
||||
"endif
|
||||
"let b:did_ftplugin = 1
|
||||
let b:current_syntax = "outliner"
|
||||
|
||||
" Default Preferences {{{1
|
||||
|
||||
let use_space_colon=0
|
||||
|
||||
" End User Preferences
|
||||
|
||||
" VimOutliner Standard Settings {{{1
|
||||
setlocal autoindent
|
||||
"setlocal backspace=2
|
||||
setlocal wrapmargin=5
|
||||
setlocal wrap
|
||||
setlocal tw=78
|
||||
setlocal noexpandtab
|
||||
setlocal tabstop=4 " tabstop and shiftwidth must match
|
||||
setlocal shiftwidth=4 " values from 2 to 8 work well
|
||||
"setlocal nosmarttab
|
||||
"setlocal softtabstop=0
|
||||
setlocal foldlevel=20
|
||||
setlocal foldcolumn=1 " turns on "+" at the beginning of close folds
|
||||
setlocal foldmethod=expr
|
||||
setlocal foldexpr=MyFoldLevel(v:lnum)
|
||||
setlocal indentexpr=
|
||||
setlocal nocindent
|
||||
setlocal iskeyword=@,39,45,48-57,_,129-255
|
||||
|
||||
" Vim Outliner Functions {{{1
|
||||
|
||||
if !exists("loaded_vimoutliner_functions")
|
||||
let loaded_vimoutliner_functions=1
|
||||
|
||||
" Sorting {{{2
|
||||
" IsParent(line) {{{3
|
||||
" Return 1 if this line is a parent
|
||||
function! IsParent(line)
|
||||
return (Ind(a:line)+1) == Ind(a:line+1)
|
||||
endfunction
|
||||
"}}}3
|
||||
" FindParent(line) {{{3
|
||||
" Return line if parent, parent line if not
|
||||
function! FindParent(line)
|
||||
if IsParent(a:line)
|
||||
return a:line
|
||||
else
|
||||
let l:parentindent = Ind(a:line)-1
|
||||
let l:searchline = a:line
|
||||
while (Ind(l:searchline) != l:parentindent) && (l:searchline > 0)
|
||||
let l:searchline = l:searchline-1
|
||||
endwhile
|
||||
return l:searchline
|
||||
endif
|
||||
endfunction
|
||||
"}}}3
|
||||
" FindLastChild(line) {{{3
|
||||
" Return the line number of the last decendent of parent line
|
||||
function! FindLastChild(line)
|
||||
let l:parentindent = Ind(a:line)
|
||||
let l:searchline = a:line+1
|
||||
while Ind(l:searchline) > l:parentindent
|
||||
let l:searchline = l:searchline+1
|
||||
endwhile
|
||||
return l:searchline-1
|
||||
endfunction
|
||||
"}}}3
|
||||
" MoveDown() {{{3
|
||||
" Move a heading down by one
|
||||
" Used for sorts and reordering of headings
|
||||
function! MoveDown()
|
||||
call cursor(line("."),0)
|
||||
del x
|
||||
put x
|
||||
endfunction
|
||||
"}}}3
|
||||
" DelHead() {{{3
|
||||
" Delete a heading
|
||||
" Used for sorts and reordering of headings
|
||||
function! DelHead(line)
|
||||
let l:fstart = foldclosed(a:line)
|
||||
if l:fstart == -1
|
||||
let l:execstr = a:line . "del x"
|
||||
else
|
||||
let l:fend = foldclosedend(a:line)
|
||||
let l:execstr = l:fstart . "," . l:fend . "del x"
|
||||
endif
|
||||
exec l:execstr
|
||||
endfunction
|
||||
" PutHead() {{{3
|
||||
" Put a heading
|
||||
" Used for sorts and reordering of headings
|
||||
function! PutHead(line)
|
||||
let l:fstart = foldclosed(a:line)
|
||||
if l:fstart == -1
|
||||
let l:execstr = a:line . "put x"
|
||||
exec l:execstr
|
||||
else
|
||||
let l:fend = foldclosedend(a:line)
|
||||
let l:execstr = l:fend . "put x"
|
||||
exec l:execstr
|
||||
endif
|
||||
endfunction
|
||||
"}}}3
|
||||
" NextHead(line) {{{3
|
||||
" Return line of next heading
|
||||
" Used for sorts and reordering of headings
|
||||
function! NextHead(line)
|
||||
let l:fend = foldclosedend(a:line)
|
||||
if l:fend == -1
|
||||
return a:line+1
|
||||
else
|
||||
return l:fend+1
|
||||
endif
|
||||
endfunction
|
||||
"}}}3
|
||||
" CompHead(line) {{{3
|
||||
" Compare this heading and the next
|
||||
" Return 1: next is greater, 0 next is same, -1 next is less
|
||||
function! CompHead(line)
|
||||
let nexthead = NextHead(a:line)
|
||||
let l:thisline=getline(a:line)
|
||||
let l:nextline=getline(nexthead)
|
||||
if indent(a:line) != indent(nexthead)
|
||||
return 0
|
||||
elseif l:thisline <# l:nextline
|
||||
return 1
|
||||
elseif l:thisline ># l:nextline
|
||||
return -1
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"}}}3
|
||||
" Sort1Line(line) {{{3
|
||||
" Compare this heading and the next and swap if out of order
|
||||
" Dir is 0 for forward, 1 for reverse
|
||||
" Return a 1 if a change was made
|
||||
function! Sort1Line(line,dir)
|
||||
if (CompHead(a:line) == -1) && (a:dir == 0)
|
||||
call DelHead(a:line)
|
||||
call PutHead(a:line)
|
||||
return 1
|
||||
elseif (CompHead(a:line) == 1) && (a:dir == 1)
|
||||
call DelHead(a:line)
|
||||
call PutHead(a:line)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
"}}}3
|
||||
" Sort1Pass(start,end,dir) {{{3
|
||||
" Compare this heading and the next and swap if out of order
|
||||
" Dir is 0 for forward, 1 for reverse
|
||||
" Return a 0 if no change was made, other wise return the change count
|
||||
function! Sort1Pass(fstart,fend,dir)
|
||||
let l:i = a:fstart
|
||||
let l:changed = 0
|
||||
while l:i < a:fend
|
||||
let l:changed = l:changed + Sort1Line(l:i,a:dir)
|
||||
let l:i = NextHead(l:i)
|
||||
endwhile
|
||||
return l:changed
|
||||
endfunction
|
||||
"}}}3
|
||||
" Sort(start,end,dir) {{{3
|
||||
" Sort this range of headings
|
||||
" dir: 0 = ascending, 1 = decending
|
||||
function! SortRange(fstart,fend,dir)
|
||||
let l:changed = 1
|
||||
while l:changed != 0
|
||||
let l:changed = Sort1Pass(a:fstart,a:fend,a:dir)
|
||||
endwhile
|
||||
endfunction
|
||||
"}}}3
|
||||
" SortChildren(dir) {{{3
|
||||
" Sort the children of a parent
|
||||
" dir: 0 = ascending, 1 = descending
|
||||
function! SortChildren(dir)
|
||||
let l:oldcursor = line(".")
|
||||
let l:fstart = FindParent(line("."))
|
||||
let l:fend = FindLastChild(l:fstart)
|
||||
let l:fstart = l:fstart
|
||||
if l:fend <= l:fstart + 1
|
||||
return
|
||||
endif
|
||||
call append(line("$"),"Temporary last line for sorting")
|
||||
mkview
|
||||
let l:execstr = "set foldlevel=" . foldlevel(l:fstart)
|
||||
exec l:execstr
|
||||
call SortRange(l:fstart + 1,l:fend,a:dir)
|
||||
call cursor(line("$"),0)
|
||||
del x
|
||||
loadview
|
||||
call cursor(l:oldcursor,0)
|
||||
endfunction
|
||||
"}}}3
|
||||
"}}}2
|
||||
" MakeChars() {{{2
|
||||
" Make a string of characters
|
||||
" Used for strings of repeated characters
|
||||
function MakeChars(count,char)
|
||||
let i = 0
|
||||
let l:chars=""
|
||||
while i < a:count
|
||||
let l:chars = l:chars . a:char
|
||||
let i = i + 1
|
||||
endwhile
|
||||
return l:chars
|
||||
endfunction
|
||||
"}}}2
|
||||
" MakeSpaces() {{{2
|
||||
" Make a string of spaces
|
||||
function MakeSpaces(count)
|
||||
return MakeChars(a:count," ")
|
||||
endfunction
|
||||
"}}}2
|
||||
" MakeDashes() {{{2
|
||||
" Make a string of dashes
|
||||
function MakeDashes(count)
|
||||
return MakeChars(a:count,"-")
|
||||
endfunction
|
||||
"}}}2
|
||||
" MyFoldText() {{{2
|
||||
" Create string used for folded text blocks
|
||||
function MyFoldText()
|
||||
if exists('g:vo_fold_length') && g:vo_fold_length == "max"
|
||||
let l:foldlength = winwidth(0) - 1 - &numberwidth - &foldcolumn
|
||||
elseif exists('g:vo_fold_length')
|
||||
let l:foldlength = g:vo_fold_length
|
||||
else
|
||||
let l:foldlength = 58
|
||||
endif
|
||||
" I have this as an option, if the user wants to set "…" as the padding
|
||||
" string, or some other string, like "(more)"
|
||||
if exists('g:vo_trim_string')
|
||||
let l:trimstr = g:vo_trim_string
|
||||
else
|
||||
let l:trimstr = "..."
|
||||
endif
|
||||
let l:MySpaces = MakeSpaces(&sw)
|
||||
let l:line = getline(v:foldstart)
|
||||
let l:bodyTextFlag=0
|
||||
if l:line =~ "^\t* \\S" || l:line =~ "^\t*\:"
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[TEXT]"
|
||||
elseif l:line =~ "^\t*\;"
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[TEXT BLOCK]"
|
||||
elseif l:line =~ "^\t*\> "
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER]"
|
||||
elseif l:line =~ "^\t*\>"
|
||||
let l:ls = stridx(l:line,">")
|
||||
let l:le = stridx(l:line," ")
|
||||
if l:le == -1
|
||||
let l:l = strpart(l:line, l:ls+1)
|
||||
else
|
||||
let l:l = strpart(l:line, l:ls+1, l:le-l:ls-1)
|
||||
endif
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER ".l:l."]"
|
||||
elseif l:line =~ "^\t*\< "
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER BLOCK]"
|
||||
elseif l:line =~ "^\t*\<"
|
||||
let l:ls = stridx(l:line,"<")
|
||||
let l:le = stridx(l:line," ")
|
||||
if l:le == -1
|
||||
let l:l = strpart(l:line, l:ls+1)
|
||||
else
|
||||
let l:l = strpart(l:line, l:ls+1, l:le-l:ls-1)
|
||||
endif
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER BLOCK ".l:l."]"
|
||||
elseif l:line =~ "^\t*\|"
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[TABLE]"
|
||||
endif
|
||||
let l:sub = substitute(l:line,'\t',l:MySpaces,'g')
|
||||
let l:sublen = strdisplaywidth(l:sub)
|
||||
let l:end = " (" . ((v:foldend + l:bodyTextFlag)- v:foldstart)
|
||||
if ((v:foldend + l:bodyTextFlag)- v:foldstart) == 1
|
||||
let l:end = l:end . " line)"
|
||||
else
|
||||
let l:end = l:end . " lines)"
|
||||
endif
|
||||
let l:endlen = strdisplaywidth(l:end)
|
||||
|
||||
" Multiple cases:
|
||||
" (1) Full padding with ellipse (...) or user defined string,
|
||||
" (2) No point in padding, pad would just obscure the end of text,
|
||||
" (3) Don't pad and use dashes to fill up the space.
|
||||
if l:endlen + l:sublen > l:foldlength
|
||||
let l:sub = strpart(l:sub, 0, l:foldlength - l:endlen - strdisplaywidth(l:trimstr))
|
||||
let l:sub = l:sub . l:trimstr
|
||||
let l:sublen = strdisplaywidth(l:sub)
|
||||
let l:sub = l:sub . l:end
|
||||
elseif l:endlen + l:sublen == l:foldlength
|
||||
let l:sub = l:sub . l:end
|
||||
else
|
||||
let l:sub = l:sub . " " . MakeDashes(l:foldlength - l:endlen - l:sublen - 1) . l:end
|
||||
endif
|
||||
return l:sub.repeat(' ', winwidth(0)-strdisplaywidth(l:sub))
|
||||
endfunction
|
||||
"}}}2
|
||||
" InsertDate() {{{2
|
||||
" Insert today's date.
|
||||
function InsertDate(ba)
|
||||
let @x = strftime("%Y-%m-%d")
|
||||
if a:ba == "0"
|
||||
normal! "xp
|
||||
else
|
||||
normal! "xP
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" InsertSpaceDate() {{{2
|
||||
" Insert a space, then today's date.
|
||||
function InsertSpaceDate()
|
||||
let @x = " "
|
||||
let @x = @x . strftime("%Y-%m-%d")
|
||||
normal! "xp
|
||||
endfunction
|
||||
"}}}2
|
||||
" InsertTime() {{{2
|
||||
" Insert the time.
|
||||
function InsertTime(ba)
|
||||
let @x = strftime("%H:%M:%S")
|
||||
if a:ba == "0"
|
||||
normal! "xp
|
||||
else
|
||||
normal! "xP
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" InsertSpaceTime() {{{2
|
||||
" Insert a space, then the time.
|
||||
function InsertSpaceTime()
|
||||
let @x = " "
|
||||
let @x = @x . strftime("%H:%M:%S")
|
||||
normal! "xp
|
||||
endfunction
|
||||
"}}}2
|
||||
" Ind(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
" Courtesy of Gabriel Horner
|
||||
function! Ind(line)
|
||||
return indent(a:line)/&tabstop
|
||||
endfunction
|
||||
"}}}2
|
||||
" BodyText(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! BodyText(line)
|
||||
return (match(getline(a:line),"^\t*:") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" PreformattedBodyText(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! PreformattedBodyText(line)
|
||||
return (match(getline(a:line),"^\t*;") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" PreformattedUserText(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! PreformattedUserText(line)
|
||||
return (match(getline(a:line),"^\t*<") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" PreformattedUserTextLabeled(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! PreformattedUserTextLabeled(line)
|
||||
return (match(getline(a:line),"^\t*<\S") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" PreformattedUserTextSpace(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! PreformattedUserTextSpace(line)
|
||||
return (match(getline(a:line),"^\t*< ") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" UserText(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! UserText(line)
|
||||
return (match(getline(a:line),"^\t*>") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" UserTextSpace(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! UserTextSpace(line)
|
||||
return (match(getline(a:line),"^\t*> ") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" UserTextLabeled(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! UserTextLabeled(line)
|
||||
return (match(getline(a:line),"^\t*>\S") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" PreformattedTable(line) {{{2
|
||||
" Determine the indent level of a line.
|
||||
function! PreformattedTable(line)
|
||||
return (match(getline(a:line),"^\t*|") == 0)
|
||||
endfunction
|
||||
"}}}2
|
||||
" MyFoldLevel(Line) {{{2
|
||||
" Determine the fold level of a line.
|
||||
function MyFoldLevel(line)
|
||||
let l:myindent = Ind(a:line)
|
||||
let l:nextindent = Ind(a:line+1)
|
||||
|
||||
if BodyText(a:line)
|
||||
if (BodyText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (BodyText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedBodyText(a:line)
|
||||
if (PreformattedBodyText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedBodyText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedTable(a:line)
|
||||
if (PreformattedTable(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedTable(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedUserText(a:line)
|
||||
if (PreformattedUserText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedUserTextSpace(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedUserTextLabeled(a:line)
|
||||
if (PreformattedUserTextLabeled(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedUserText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif UserText(a:line)
|
||||
if (UserText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (UserTextSpace(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif UserTextLabeled(a:line)
|
||||
if (UserTextLabeled(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (UserText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
else
|
||||
if l:myindent < l:nextindent
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if l:myindent > l:nextindent
|
||||
"return '<'.(l:nextindent+1)
|
||||
return (l:myindent)
|
||||
"return '<'.(l:nextindent-1)
|
||||
endif
|
||||
return l:myindent
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" Spawn(line) {{{2
|
||||
" Execute an executable line
|
||||
" Courtesy of Steve Litt
|
||||
if !exists("loaded_steveoutliner_functions")
|
||||
let loaded_steveoutliner_functions=1
|
||||
function Spawn()
|
||||
let theline=getline(line("."))
|
||||
let idx=matchend(theline, "_exe_\\s*")
|
||||
if idx == -1
|
||||
echo "Not an executable line"
|
||||
else
|
||||
let command=strpart(theline, idx)
|
||||
let command="!".command
|
||||
exec command
|
||||
endif
|
||||
endfunction
|
||||
endif
|
||||
"}}}2
|
||||
" This should be a setlocal but that doesn't work when switching to a new .otl file
|
||||
" within the same buffer. Using :e has demonstrated this.
|
||||
set foldtext=MyFoldText()
|
||||
|
||||
"setlocal fillchars=|,
|
||||
|
||||
endif " if !exists("loaded_vimoutliner_functions")
|
||||
" End Vim Outliner Functions
|
||||
|
||||
" Menu Entries {{{1
|
||||
" VO menu
|
||||
amenu &VO.Expand\ Level\ &1 :set foldlevel=0<cr>
|
||||
amenu &VO.Expand\ Level\ &2 :set foldlevel=1<cr>
|
||||
amenu &VO.Expand\ Level\ &3 :set foldlevel=2<cr>
|
||||
amenu &VO.Expand\ Level\ &4 :set foldlevel=3<cr>
|
||||
amenu &VO.Expand\ Level\ &5 :set foldlevel=4<cr>
|
||||
amenu &VO.Expand\ Level\ &6 :set foldlevel=5<cr>
|
||||
amenu &VO.Expand\ Level\ &7 :set foldlevel=6<cr>
|
||||
amenu &VO.Expand\ Level\ &8 :set foldlevel=7<cr>
|
||||
amenu &VO.Expand\ Level\ &9 :set foldlevel=8<cr>
|
||||
amenu &VO.Expand\ Level\ &All :set foldlevel=99999<cr>
|
||||
amenu &VO.-Sep1- :
|
||||
"Tools sub-menu
|
||||
let s:path2scripts = expand('<sfile>:p:h:h').'/vimoutliner/scripts'
|
||||
" otl2html
|
||||
exec 'amenu &VO.&Tools.otl2&html\.py\ (otl2html\.py\ thisfile\ -S\ html2otl_nnnnnn\.css\ >\ thisfile\.html) :!'.s:path2scripts.'/otl2html.py -S html2otl_nnnnnn.css % > %.html<CR>'
|
||||
" otl2docbook
|
||||
exec 'amenu &VO.&Tools.otl2&docbook\.pl\ (otl2docbook\.pl\ thisfile\ >\ thisfile\.dbk) :!'.s:path2scripts.'/otl2docbook.pl % > %.dbk<CR>'
|
||||
" otl2table
|
||||
exec 'amenu &VO.&Tools.otl2&table\.py\ (otl2table\.py\ thisfile\ >\ thisfile\.txt) :!'.s:path2scripts.'/otl2table.py % > %.txt<CR>'
|
||||
" otl2tags => FreeMind
|
||||
exec 'amenu &VO.&Tools.otl2tags\.py\ =>\ &FreeMind\ (otl2tags\.py\ \-c\ otl2tags_freemind\.conf\ thisfile\ >\ thisfile\.mm) :!'.s:path2scripts.'/otl2tags.py -c '.s:path2scripts.'/otl2tags_freemind.conf % > %.mm<CR>'
|
||||
" otl2tags => Graphviz
|
||||
exec 'amenu &VO.&Tools.otl2tags\.py\ =>\ &Graphviz\ (otl2tags\.py\ \-c\ otl2tags_graphviz\.conf\ thisfile\ >\ thisfile\.gv) :!'.s:path2scripts.'/otl2tags.py -c '.s:path2scripts.'/otl2tags_graphviz.conf % > %.gv<CR>'
|
||||
amenu &VO.&Tools.&myotl2thml\.sh\ (myotl2html\.sh\ thisfile) :!myotl2html.sh %<CR>
|
||||
amenu &VO.-Sep2- :
|
||||
amenu &VO.&Color\ Scheme :popup Edit.Color\ Scheme<cr>
|
||||
amenu &VO.-Sep3- :
|
||||
amenu &VO.&Help.&Index :he vo<cr>
|
||||
amenu &VO.&Help.&,,\ Commands :he votl-command<cr>
|
||||
amenu &VO.&Help.&Checkboxes :he votl-checkbox<cr>
|
||||
amenu &VO.&Help.&Hoisting :he votl-hoisting<cr>
|
||||
amenu &Help.-Sep1- :
|
||||
" Help menu additions
|
||||
amenu &Help.&Vim\ Outliner.&Index :he votl<cr>
|
||||
amenu &Help.&Vim\ Outliner.&,,\ Commands :he votl-command<cr>
|
||||
amenu &Help.&Vim\ Outliner.&Checkboxes :he votl-checkbox<cr>
|
||||
amenu &Help.&Vim\ Outliner.&Hoisting :he votl-hoisting<cr>
|
||||
"}}}1
|
||||
" Auto-commands {{{1
|
||||
if !exists("autocommand_vo_loaded")
|
||||
let autocommand_vo_loaded = 1
|
||||
au BufNewFile,BufRead *.otl setf votl
|
||||
" au CursorHold *.otl syn sync fromstart
|
||||
"set updatetime=500
|
||||
endif
|
||||
"}}}1
|
||||
|
||||
" this command needs to be run every time so Vim doesn't forget where to look
|
||||
setlocal tags^=$HOME/.vim/vimoutliner/vo_tags.tag
|
||||
|
||||
" Added an indication of current syntax as per Dillon Jones' request
|
||||
let b:current_syntax = "outliner"
|
||||
|
||||
" Directory where VO is located now
|
||||
let vo_dir = expand("<sfile>:p:h:h")
|
||||
|
||||
" Load rc file, only the first found.
|
||||
let rcs = split(globpath('$HOME,$HOME/.vimoutliner','.vimoutlinerrc'), "\n") +
|
||||
\ split(globpath('$HOME,$HOME/.vimoutliner,$HOME/.vim', 'vimoutlinerrc'), "\n") +
|
||||
\ split(globpath(vo_dir, 'vimoutlinerrc'), "\n")
|
||||
|
||||
if len(rcs) > 0
|
||||
exec 'source '.rcs[0]
|
||||
else
|
||||
runtime vimoutliner/vimoutlinerrc
|
||||
endif
|
||||
" Load modules
|
||||
if exists('g:vo_modules_load')
|
||||
for vo_module in split(g:vo_modules_load, '\s*:\s*')
|
||||
exec "runtime! vimoutliner/plugin/votl_" . vo_module . ".vim"
|
||||
endfor
|
||||
unlet! vo_module
|
||||
endif
|
||||
|
||||
" Vim Outliner Key Mappings {{{1
|
||||
" insert the date
|
||||
nmap <silent><buffer> <localleader>d $:call InsertSpaceDate()<cr>
|
||||
imap <silent><buffer> <localleader>d ~<esc>x:call InsertDate(0)<cr>a
|
||||
nmap <silent><buffer> <localleader>D ^:call InsertDate(1)<cr>a <esc>
|
||||
|
||||
" insert the time
|
||||
nmap <silent><buffer> <localleader>t $:call InsertSpaceTime()<cr>
|
||||
imap <silent><buffer> <localleader>t ~<esc>x:call InsertTime(0)<cr>a
|
||||
nmap <silent><buffer> <localleader>T ^:call InsertTime(1)<cr>a <esc>
|
||||
|
||||
" sort a list naturally
|
||||
map <silent> <buffer> <localleader>s :silent call SortChildren(0)<cr>
|
||||
" sort a list, but you supply the options
|
||||
map <silent> <buffer> <localleader>S :silent call SortChildren(1)<cr>
|
||||
|
||||
" invoke the file explorer
|
||||
map <silent><buffer> <localleader>f :e .<cr>
|
||||
imap <silent><buffer> <localleader>f :e .<cr>
|
||||
|
||||
" Insert a fence for segmented lists.
|
||||
" this divider is used by otl2html.py to create '<hr>'
|
||||
map <silent><buffer> <localleader>- o----------------------------------------0
|
||||
imap <silent><buffer> <localleader>- ----------------------------------------<cr>
|
||||
|
||||
" switch document between the two types of bodytext styles
|
||||
if use_space_colon == 1
|
||||
" First, convert document to the marker style
|
||||
map <silent><buffer><localleader>b :%s/\(^\t*\) :/\1/e<cr>:%s/\(^\t*\) /\1 : /e<cr>:let @/=""<cr>
|
||||
" Now, convert document to the space style
|
||||
map <silent><buffer><localleader>B :%s/\(^\t*\) :/\1/e<cr>:let @/=""<cr>
|
||||
else
|
||||
" First, convert document to the marker style
|
||||
map <silent><buffer><localleader>b :%s/\(^\t*\):/\1/e<cr>:%s/\(^\t*\) /\1: /e<cr>:let @/=""<cr>
|
||||
" Now, convert document to the space style
|
||||
map <silent><buffer><localleader>B :%s/\(^\t*\):/\1/e<cr>:let @/=""<cr>
|
||||
endif
|
||||
|
||||
" Steve's additional mappings start here
|
||||
map <silent><buffer> <C-K> <C-]>
|
||||
map <silent><buffer> <C-N> <C-T>
|
||||
map <silent><buffer> <localleader>0 :set foldlevel=99999<CR>
|
||||
map <silent><buffer> <localleader>9 :set foldlevel=8<CR>
|
||||
map <silent><buffer> <localleader>8 :set foldlevel=7<CR>
|
||||
map <silent><buffer> <localleader>7 :set foldlevel=6<CR>
|
||||
map <silent><buffer> <localleader>6 :set foldlevel=5<CR>
|
||||
map <silent><buffer> <localleader>5 :set foldlevel=4<CR>
|
||||
map <silent><buffer> <localleader>4 :set foldlevel=3<CR>
|
||||
map <silent><buffer> <localleader>3 :set foldlevel=2<CR>
|
||||
map <silent><buffer> <localleader>2 :set foldlevel=1<CR>
|
||||
map <silent><buffer> <localleader>1 :set foldlevel=0<CR>
|
||||
"next line commented out due to hard-coded nature and ancient, nonexistent file
|
||||
"map <silent><buffer> <localleader>,, :runtime vimoutliner/vimoutlinerrc<CR>
|
||||
map! <silent><buffer> <localleader>w <Esc>:w<CR>a
|
||||
nmap <silent><buffer> <localleader>e :call Spawn()<cr>
|
||||
" Steve's additional mappings end here
|
||||
|
||||
" End of Vim Outliner Key Mappings }}}1
|
||||
|
||||
" The End
|
||||
" vim600: set foldmethod=marker foldlevel=0:
|
173
pack/acp/start/vimoutliner/install.sh
Executable file
173
pack/acp/start/vimoutliner/install.sh
Executable file
|
@ -0,0 +1,173 @@
|
|||
#!/bin/bash
|
||||
|
||||
homedir=$HOME
|
||||
vimdir=$homedir/.vim
|
||||
vodir=$vimdir/vimoutliner
|
||||
OS=`uname`
|
||||
|
||||
backupargs=""
|
||||
|
||||
|
||||
#SOME FUNCTIONS
|
||||
sure () {
|
||||
read REPLY
|
||||
echo test $REPLY = "y" || test $REPLY = "Y"
|
||||
}
|
||||
|
||||
make_dir () {
|
||||
test -d $1 || {
|
||||
echo " creating: $1"
|
||||
mkdir $1
|
||||
created=1
|
||||
}
|
||||
}
|
||||
|
||||
copyfile () {
|
||||
echo " installing: $2/$1"
|
||||
install $backupargs $1 $2/$1
|
||||
}
|
||||
|
||||
copydir () {
|
||||
files=`ls $1`
|
||||
for i in $files; do
|
||||
echo " installing: $2/$i"
|
||||
if [ -d $1/$i ]; then
|
||||
mkdir -p $2/$i
|
||||
copydir $1/$i $2/$i
|
||||
else
|
||||
install $backupargs $1/$i $2
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
#START THE INSTALLATION
|
||||
cat <<EOT
|
||||
Vim Outliner Installation
|
||||
This script is safe for installing Vim Outliner and for upgrading an
|
||||
existing Vim Outliner installation.
|
||||
EOT
|
||||
echo -n "Would you like to continue (y/N) ? "
|
||||
sure || exit
|
||||
|
||||
|
||||
#CREATE NECESSARY DIRECTORIES
|
||||
created=0
|
||||
echo checking/creating needed directories
|
||||
make_dir $vimdir
|
||||
make_dir $vimdir/syntax
|
||||
make_dir $vimdir/ftplugin
|
||||
make_dir $vimdir/ftdetect
|
||||
make_dir $vimdir/doc
|
||||
make_dir $vimdir/colors
|
||||
make_dir $vodir
|
||||
make_dir $vodir/plugin
|
||||
make_dir $vodir/scripts
|
||||
if [ $created -eq 0 ]; then echo " none created"; fi
|
||||
|
||||
#TWEAK $HOME/.vimrc
|
||||
modified=0
|
||||
echo checking/creating/modifying $homedir/.vimrc
|
||||
test -f $homedir/.vimrc || { echo " creating $homedir/.vimrc"
|
||||
touch $homedir/.vimrc
|
||||
}
|
||||
egrep -lq "filetype[[:space:]]+plugin[[:space:]]+indent[[:space:]]+on" $homedir/.vimrc || \
|
||||
{ modified=1
|
||||
echo "filetype plugin indent on" >> $homedir/.vimrc
|
||||
}
|
||||
egrep -lq "syntax[[:space:]]+on" $homedir/.vimrc || \
|
||||
{ modified=1
|
||||
echo "syntax on" >> $homedir/.vimrc
|
||||
}
|
||||
if [ $modified -eq 0 ] ; then
|
||||
echo " not modified";
|
||||
else
|
||||
echo " modifying $homedir/.vimrc"
|
||||
fi
|
||||
|
||||
#TWEAK $HOME/.vim/filetype.vim
|
||||
modified=0
|
||||
echo checking/creating/modifying $homedir/.vim/filetype.vim
|
||||
test -f $homedir/.vim/filetype.vim || \
|
||||
{ echo " creating $homedir/.vim/filetype.vim"
|
||||
touch $homedir/.vim/filetype.vim
|
||||
}
|
||||
egrep -lq "runtime\! ftdetect/\*.vim" $homedir/.vim/filetype.vim || \
|
||||
{ echo " modifying $homedir/.vim/filetype.vim"
|
||||
modified=1
|
||||
echo "runtime! ftdetect/*.vim" >> $homedir/.vim/filetype.vim
|
||||
}
|
||||
if [ $modified -eq 0 ] ; then echo " not modified"; fi
|
||||
|
||||
#CLEANUP OLD INSTALLATIONS
|
||||
echo "cleaning up old (<0.3.5) installations"
|
||||
files=`find $vimdir -iname "vo_*"`
|
||||
for file in $files; do
|
||||
echo "removing $file"
|
||||
rm -v $file
|
||||
done
|
||||
|
||||
#CLEANUP OLD BACKUPS
|
||||
if [ -z $backupargs ]; then
|
||||
echo "cleaning up old backups"
|
||||
files=`find $vimdir -iname "vo*.old"`
|
||||
for file in $files; do
|
||||
echo "removing $file"
|
||||
rm -v $file
|
||||
done
|
||||
files2=`find $vodir -iname "*.old"`
|
||||
for file in $files; do
|
||||
echo "removing $file"
|
||||
rm -v $file
|
||||
done
|
||||
fi
|
||||
|
||||
#COPY FILES
|
||||
echo "installing files"
|
||||
copyfile syntax/votl.vim $vimdir
|
||||
copyfile ftplugin/votl.vim $vimdir
|
||||
copyfile ftdetect/votl.vim $vimdir
|
||||
copyfile colors/vo_light.vim $vimdir
|
||||
copyfile colors/vo_dark.vim $vimdir
|
||||
copyfile doc/votl.txt $vimdir
|
||||
copyfile doc/votl_cheatsheet.txt $vimdir
|
||||
copyfile vimoutlinerrc $vodir
|
||||
copyfile vimoutliner/scripts/votl_maketags.pl $vimdir
|
||||
|
||||
#INCORPORATE HELP DOCUMENTATION
|
||||
echo "Installing vimoutliner documentation"
|
||||
vim -c "helptags $HOME/.vim/doc" -c q
|
||||
|
||||
#INSTALL THE ADD-ONS
|
||||
cat <<EOT
|
||||
Add-ons
|
||||
There are optional Vim Outliner plugins to handle checkboxes, hoisting and
|
||||
smartpaste. There is also a script to convert a Vim Outliner .otl file
|
||||
to a html file, as well as many other external scripts included.
|
||||
The plugins will be stored in $vodir/plugin and the scripts will be installed in
|
||||
$vodir/scripts.
|
||||
|
||||
EOT
|
||||
|
||||
echo -n "Would you like to install these (y/N) "
|
||||
if sure; then
|
||||
echo installing add-ons
|
||||
copydir vimoutliner/plugin $vodir/plugin
|
||||
copydir vimoutliner/scripts $vodir/scripts
|
||||
fi
|
||||
|
||||
#ALL DONE
|
||||
echo ""
|
||||
echo "Installation of Vimoutliner is now complete"
|
||||
|
||||
cat <<EOT
|
||||
|
||||
**********************************************************************
|
||||
* For help with using VimOutliner simply execute ":help vo" within *
|
||||
* vim. For a quick overview of all commands execute: *
|
||||
* ":help votl_cheatsheet" *
|
||||
* *
|
||||
* Additional useful scripts are available in the scripts folder, *
|
||||
* see $HOME/.vim/vimoutliner/scripts *
|
||||
**********************************************************************
|
||||
|
||||
EOT
|
248
pack/acp/start/vimoutliner/syntax/votl.vim
Normal file
248
pack/acp/start/vimoutliner/syntax/votl.vim
Normal file
|
@ -0,0 +1,248 @@
|
|||
"#########################################################################
|
||||
"# syntax/votl.vim: VimOutliner syntax highlighting
|
||||
"# version 0.4.0
|
||||
"# Copyright (C) 2001,2003 by Steve Litt (slitt@troubleshooters.com)
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"#
|
||||
"# You should have received a copy of the GNU General Public License
|
||||
"# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
"#
|
||||
"# Steve Litt, slitt@troubleshooters.com, http://www.troubleshooters.com
|
||||
"#########################################################################
|
||||
|
||||
" HISTORY {{{1
|
||||
"#########################################################################
|
||||
"# V0.1.0 Pre-alpha
|
||||
"# Set of outliner friendly settings
|
||||
"# Steve Litt, 5/28/2001
|
||||
"# End of version 0.1.0
|
||||
"#
|
||||
"# V0.1.1 Pre-alpha
|
||||
"# No change
|
||||
"#
|
||||
"# Steve Litt, 5/28/2001
|
||||
"# End of version 0.1.1
|
||||
"#
|
||||
"# V0.1.2 Pre-alpha
|
||||
"# No Change
|
||||
"# Steve Litt, 5/30/2001
|
||||
"# End of version 0.1.2
|
||||
"# V0.1.3 Pre-alpha
|
||||
"# No Change
|
||||
"# Steve Litt, 5/30/2001
|
||||
"# End of version 0.1.3
|
||||
"# V0.2.0
|
||||
"# Noel Henson adds code for outliner-friendly expand and
|
||||
"# collapse, comma comma commands, color coding, hooks for a
|
||||
"# spellchecker, sorting, and date insertion.
|
||||
"# Noel Henson, 11/24/2002
|
||||
"# End of version 0.2.0
|
||||
"# END OF HISTORY
|
||||
"#
|
||||
"#########################################################################
|
||||
|
||||
" Colors linked {{{1
|
||||
" Bill Powell, http://www.billpowellisalive.com
|
||||
" Linked colors to normal groups. Different schemes will need tweaking.
|
||||
" Occasionally certain groups will be rendered invisible. ;)
|
||||
"
|
||||
" Changelog {{{2
|
||||
"2007 Jan 23, 21:23 Tue - 0.3.0, Modified version 0.1
|
||||
" Linked syntax groups to standard Vim color groups, intsead of to
|
||||
" particular colors. Now each colorscheme can work its own magic on
|
||||
" a VO file.
|
||||
"2007 Apr 30, 9:36 Mon - 0.3.0, Modified version 0.2
|
||||
" Changed a few linked groups to reduce chances of groups being invisible.
|
||||
" No longer use Ignore group for anything.
|
||||
" Still a little redundancy; different groups might linked to same color group.
|
||||
" E.g., PT1 and UT1. But some color schemes (e.g. astronout) will differentiate between
|
||||
" Special and Debug. Others will use the same colors for, say, Identifier and Debug.
|
||||
" It just depends.
|
||||
" To tweak these groups, try :h syntax and go to group-name.
|
||||
" This shows the color groups, highlighted in your current colorscheme.
|
||||
" }}}
|
||||
hi link OL1 Statement
|
||||
hi link OL2 Identifier
|
||||
hi link OL3 Constant
|
||||
hi link OL4 PreProc
|
||||
hi link OL5 Statement
|
||||
hi link OL6 Identifier
|
||||
hi link OL7 Constant
|
||||
hi link OL8 PreProc
|
||||
hi link OL9 Statement
|
||||
|
||||
"colors for tags
|
||||
"hi link outlTags Tag
|
||||
hi link outlTags Todo
|
||||
|
||||
"color for body text
|
||||
hi link BT1 Comment
|
||||
hi link BT2 Comment
|
||||
hi link BT3 Comment
|
||||
hi link BT4 Comment
|
||||
hi link BT5 Comment
|
||||
hi link BT6 Comment
|
||||
hi link BT7 Comment
|
||||
hi link BT8 Comment
|
||||
hi link BT9 Comment
|
||||
|
||||
"color for pre-formatted text
|
||||
hi link PT1 Special
|
||||
hi link PT2 Special
|
||||
hi link PT3 Special
|
||||
hi link PT4 Special
|
||||
hi link PT5 Special
|
||||
hi link PT6 Special
|
||||
hi link PT7 Special
|
||||
hi link PT8 Special
|
||||
hi link PT9 Special
|
||||
|
||||
"color for tables
|
||||
hi link TA1 Type
|
||||
hi link TA2 Type
|
||||
hi link TA3 Type
|
||||
hi link TA4 Type
|
||||
hi link TA5 Type
|
||||
hi link TA6 Type
|
||||
hi link TA7 Type
|
||||
hi link TA8 Type
|
||||
hi link TA9 Type
|
||||
|
||||
"color for user text (wrapping)
|
||||
hi link UT1 Debug
|
||||
hi link UT2 Debug
|
||||
hi link UT3 Debug
|
||||
hi link UT4 Debug
|
||||
hi link UT5 Debug
|
||||
hi link UT6 Debug
|
||||
hi link UT7 Debug
|
||||
hi link UT8 Debug
|
||||
hi link UT9 Debug
|
||||
|
||||
"color for user text (non-wrapping)
|
||||
hi link UB1 Underlined
|
||||
hi link UB2 Underlined
|
||||
hi link UB3 Underlined
|
||||
hi link UB4 Underlined
|
||||
hi link UB5 Underlined
|
||||
hi link UB6 Underlined
|
||||
hi link UB7 Underlined
|
||||
hi link UB8 Underlined
|
||||
hi link UB9 Underlined
|
||||
|
||||
"colors for folded sections
|
||||
"hi link Folded Special
|
||||
"hi link FoldColumn Type
|
||||
|
||||
"colors for experimental spelling error highlighting
|
||||
"this only works for spellfix.vim with will be cease to exist soon
|
||||
hi link spellErr Error
|
||||
hi link BadWord Todo
|
||||
|
||||
" Syntax {{{1
|
||||
syn clear
|
||||
syn sync fromstart
|
||||
|
||||
syn match outlTags '_tag_\w*' contained
|
||||
|
||||
" Noel's style of body text {{{2
|
||||
syntax region BT1 start=+^ \S+ skip=+^ \S+ end=+^\S+me=e-1 end=+^\(\t\)\{1}\S+me=e-2 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT2 start=+^\(\t\)\{1} \S+ skip=+^\(\t\)\{1} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT3 start=+^\(\t\)\{2} \S+ skip=+^\(\t\)\{2} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT4 start=+^\(\t\)\{3} \S+ skip=+^\(\t\)\{3} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT5 start=+^\(\t\)\{4} \S+ skip=+^\(\t\)\{4} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT6 start=+^\(\t\)\{5} \S+ skip=+^\(\t\)\{5} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT7 start=+^\(\t\)\{6} \S+ skip=+^\(\t\)\{6} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT8 start=+^\(\t\)\{7} \S+ skip=+^\(\t\)\{7} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT9 start=+^\(\t\)\{8} \S+ skip=+^\(\t\)\{8} \S+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
|
||||
"comment-style bodytext as per Steve Litt {{{2
|
||||
syntax region BT1 start=+^:+ skip=+^:+ end=+^\S+me=e-1 end=+^\(\t\)\{1}\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT2 start=+^\(\t\)\{1}:+ skip=+^\(\t\)\{1}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT3 start=+^\(\t\)\{2}:+ skip=+^\(\t\)\{2}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT4 start=+^\(\t\)\{3}:+ skip=+^\(\t\)\{3}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT5 start=+^\(\t\)\{4}:+ skip=+^\(\t\)\{4}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT6 start=+^\(\t\)\{5}:+ skip=+^\(\t\)\{5}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT7 start=+^\(\t\)\{6}:+ skip=+^\(\t\)\{6}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT8 start=+^\(\t\)\{7}:+ skip=+^\(\t\)\{7}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region BT9 start=+^\(\t\)\{8}:+ skip=+^\(\t\)\{8}:+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
|
||||
"Preformatted body text {{{2
|
||||
syntax region PT1 start=+^;+ skip=+^;+ end=+^\S+me=e-1 end=+^\(\t\)\{1}\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT2 start=+^\(\t\)\{1};+ skip=+^\(\t\)\{1};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT3 start=+^\(\t\)\{2};+ skip=+^\(\t\)\{2};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT4 start=+^\(\t\)\{3};+ skip=+^\(\t\)\{3};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT5 start=+^\(\t\)\{4};+ skip=+^\(\t\)\{4};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT6 start=+^\(\t\)\{5};+ skip=+^\(\t\)\{5};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT7 start=+^\(\t\)\{6};+ skip=+^\(\t\)\{6};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT8 start=+^\(\t\)\{7};+ skip=+^\(\t\)\{7};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region PT9 start=+^\(\t\)\{8};+ skip=+^\(\t\)\{8};+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
|
||||
"Preformatted tables {{{2
|
||||
syntax region TA1 start=+^|+ skip=+^|+ end=+^\S+me=e-1 end=+^\(\t\)\{1}\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA2 start=+^\(\t\)\{1}|+ skip=+^\(\t\)\{1}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA3 start=+^\(\t\)\{2}|+ skip=+^\(\t\)\{2}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA4 start=+^\(\t\)\{3}|+ skip=+^\(\t\)\{3}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA5 start=+^\(\t\)\{4}|+ skip=+^\(\t\)\{4}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA6 start=+^\(\t\)\{5}|+ skip=+^\(\t\)\{5}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA7 start=+^\(\t\)\{6}|+ skip=+^\(\t\)\{6}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA8 start=+^\(\t\)\{7}|+ skip=+^\(\t\)\{7}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region TA9 start=+^\(\t\)\{8}|+ skip=+^\(\t\)\{8}|+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
|
||||
"wrapping user text {{{2
|
||||
syntax region UT1 start=+^>+ skip=+^>+ end=+^\S+me=e-1 end=+^\(\t\)\{1}\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT2 start=+^\(\t\)\{1}>+ skip=+^\(\t\)\{1}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT3 start=+^\(\t\)\{2}>+ skip=+^\(\t\)\{2}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT4 start=+^\(\t\)\{3}>+ skip=+^\(\t\)\{3}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT5 start=+^\(\t\)\{4}>+ skip=+^\(\t\)\{4}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT6 start=+^\(\t\)\{5}>+ skip=+^\(\t\)\{5}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT7 start=+^\(\t\)\{6}>+ skip=+^\(\t\)\{6}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT8 start=+^\(\t\)\{7}>+ skip=+^\(\t\)\{7}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UT9 start=+^\(\t\)\{8}>+ skip=+^\(\t\)\{8}>+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
|
||||
"non-wrapping user text {{{2
|
||||
syntax region UB1 start=+^<+ skip=+^<+ end=+^\S+me=e-1 end=+^\(\t\)\{1}\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB2 start=+^\(\t\)\{1}<+ skip=+^\(\t\)\{1}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB3 start=+^\(\t\)\{2}<+ skip=+^\(\t\)\{2}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB4 start=+^\(\t\)\{3}<+ skip=+^\(\t\)\{3}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB5 start=+^\(\t\)\{4}<+ skip=+^\(\t\)\{4}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB6 start=+^\(\t\)\{5}<+ skip=+^\(\t\)\{5}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB7 start=+^\(\t\)\{6}<+ skip=+^\(\t\)\{6}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB8 start=+^\(\t\)\{7}<+ skip=+^\(\t\)\{7}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
syntax region UB9 start=+^\(\t\)\{8}<+ skip=+^\(\t\)\{8}<+ end=+^\(\t\)*\S+me=s-1 contains=spellErr,SpellErrors,BadWord contained
|
||||
|
||||
"comment-style bodytext formatting as per Steve Litt
|
||||
syntax match Comment "^\s*:.*$"
|
||||
setlocal fo-=t fo+=crqno
|
||||
setlocal com=sO:\:\ -,mO:\:\ \ ,eO:\:\:,:\:,sO:\>\ -,mO:\>\ \ ,eO:\>\>,:\>
|
||||
|
||||
" Headings {{{2
|
||||
syntax region OL1 start=+^[^:\t]+ end=+^[^:\t]+me=e-1 contains=outlTags,BT1,BT2,PT1,PT2,TA1,TA2,UT1,UT2,UB1,UB2,spellErr,SpellErrors,BadWord,OL2 keepend
|
||||
syntax region OL2 start=+^\t[^:\t]+ end=+^\t[^:\t]+me=s-1 contains=outlTags,BT2,BT3,PT2,PT3,TA2,TA3,UT2,UT3,UB2,UB3,spellErr,SpellErrors,BadWord,OL3 keepend
|
||||
syntax region OL3 start=+^\(\t\)\{2}[^:\t]+ end=+^\(\t\)\{2}[^:\t]+me=e-3 contains=outlTags,BT3,BT4,PT3,PT4,TA3,TA4,UT3,UT4,UB3,UB4,spellErr,SpellErrors,BadWord,OL4 keepend
|
||||
syntax region OL4 start=+^\(\t\)\{3}[^:\t]+ end=+^\(\t\)\{3}[^:\t]+me=e-4 contains=outlTags,BT4,BT5,PT4,PT5,TA4,TA5,UT4,UT5,UB4,UB5,spellErr,SpellErrors,BadWord,OL5 keepend
|
||||
syntax region OL5 start=+^\(\t\)\{4}[^:\t]+ end=+^\(\t\)\{4}[^:\t]+me=e-5 contains=outlTags,BT5,BT6,PT5,PT6,TA5,TA6,UT5,UT6,UB5,UB6,spellErr,SpellErrors,BadWord,OL6 keepend
|
||||
syntax region OL6 start=+^\(\t\)\{5}[^:\t]+ end=+^\(\t\)\{5}[^:\t]+me=e-6 contains=outlTags,BT6,BT7,PT6,PT7,TA6,TA7,UT6,UT7,UB6,UB7,spellErr,SpellErrors,BadWord,OL7 keepend
|
||||
syntax region OL7 start=+^\(\t\)\{6}[^:\t]+ end=+^\(\t\)\{6}[^:\t]+me=e-7 contains=outlTags,BT7,BT8,PT7,PT8,TA7,TA8,UT7,UT8,UB7,UB8,spellErr,SpellErrors,BadWord,OL8 keepend
|
||||
syntax region OL8 start=+^\(\t\)\{7}[^:\t]+ end=+^\(\t\)\{7}[^:\t]+me=e-8 contains=outlTags,BT8,BT9,PT8,PT9,TA8,TA9,UT8,UT9,UB8,UB9,spellErr,SpellErrors,BadWord,OL9 keepend
|
||||
syntax region OL9 start=+^\(\t\)\{8}[^:\t]+ end=+^\(\t\)\{8}[^:\t]+me=e-9 contains=outlTags,BT9,PT9,TA9,UT9,UB9,spellErr,SpellErrors,BadWord keepend
|
||||
|
||||
" Auto-commands {{{1
|
||||
if !exists("autocommand_vo_loaded")
|
||||
let autocommand_vo_loaded = 1
|
||||
au BufNewFile,BufRead *.otl setf outliner
|
||||
" au CursorHold *.otl syn sync fromstart
|
||||
" set updatetime=500
|
||||
endif
|
||||
|
||||
" The End
|
||||
" vim600: set foldmethod=marker foldlevel=0:
|
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
BIN
pack/acp/start/vimoutliner/vimoutliner/images/favicon.ico
Normal file
BIN
pack/acp/start/vimoutliner/vimoutliner/images/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 B |
|
@ -0,0 +1,77 @@
|
|||
Hoisting
|
||||
What is it?
|
||||
: Hoisting is a way to focus on a particular area of an outline. Only the
|
||||
: offspring from a selected parent will be shown. The offspring are
|
||||
: left-justified just as if they were the top level headings and had no
|
||||
: parent.
|
||||
Installation
|
||||
The hoist plugin is included in the VimOutliner plugin directory
|
||||
This plugin is disabled by default
|
||||
See information in the ~/.vimoutlinerrc on how to enable it
|
||||
Optionally set the hoistParanoia variable
|
||||
: If you are really paranoid about loosing your data during shakedown
|
||||
: of vo_hoist.vim, you can add this to your ~/.vimoutlinerrc file. It
|
||||
: will prevent VO from automatically removing the temporary hoist
|
||||
: files. This will have a tendency to hugely increase the number of
|
||||
: files in your working directory (but if you're paranoid... ;) )
|
||||
let g:hoistParanoia = 1
|
||||
How do I use it?
|
||||
Hoisting
|
||||
: Whenever you open a VO document, hoisting will be available.
|
||||
Invocation
|
||||
Place the cursor on the parent to be hoisted
|
||||
,,h
|
||||
You will need to hit <ENTER> to accept some informational messages
|
||||
You should now see the children of the selected parent ready for editing
|
||||
Treat this document just like a normal .otl file
|
||||
De-hoisting
|
||||
: From within the hoisted document you simply need to quit. The
|
||||
: hoisted data will be saved in place of the old children. The cursor
|
||||
: will be returned to the hoisted parent.
|
||||
Invocation
|
||||
The :q, :wq, :x and ZZ perform a de-hoist operation
|
||||
A write will automatically be done to save any changes
|
||||
Manual De-hoisting
|
||||
: Should the de-hoisting ever fail or should an operator quit Vim (by
|
||||
: closing the window with the mouse, say), a manual de-hoisting will
|
||||
: need to be performed.
|
||||
You can find a currently hoisted parent by searching for __hoist
|
||||
Place the cursor on the parent with the __hoist tag
|
||||
,,H
|
||||
The edited, hoisted offspring will replace the current offspring
|
||||
The __hoist tag will be removed
|
||||
The Hoist Tag
|
||||
Example Tag
|
||||
: The hoist tag is added to a hoisted parent for error recovery. It
|
||||
: includes a filename, a line number and a timestamp.
|
||||
Example Tag
|
||||
__hoist:vo_hoist.46.20030816124249.otl
|
||||
Tag Components
|
||||
Tag Marker
|
||||
__hoist:
|
||||
Easy search and replace
|
||||
Filename Prefix
|
||||
vo_hoist.
|
||||
Needed to comply with VO standards for file naming
|
||||
Parent Line Number (at time of hoisting)
|
||||
46.
|
||||
Timestamp
|
||||
20030816124249
|
||||
YYYYMMDDhhmmss
|
||||
Filename Suffix
|
||||
.otl
|
||||
Duh
|
||||
The Log Files
|
||||
: Log files of the hoists are created to aid in error recovery should that
|
||||
: become necessary. They are created in the same directory as the working
|
||||
: .otl file.
|
||||
Log Filename
|
||||
.vo_hoist.<otlfilename>.log
|
||||
Example Log Filename
|
||||
.vo_hoist.test.otl.log
|
||||
Contents
|
||||
There is one line per hoist operation
|
||||
Each is comprised of a parent with a __hoist tag
|
||||
Limitations
|
||||
1 Level Deep
|
||||
: Until debug is complete, hoisting is limited to one level.
|
251
pack/acp/start/vimoutliner/vimoutliner/plugin/prev/votl_hoist.vim
Executable file
251
pack/acp/start/vimoutliner/vimoutliner/plugin/prev/votl_hoist.vim
Executable file
|
@ -0,0 +1,251 @@
|
|||
"######################################################################
|
||||
"# VimOutliner Hoisting
|
||||
"# Copyright (C) 2003 by Noel Henson noel@noels-lab.com
|
||||
"# The file is currently an experimental part of Vim Outliner.
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"######################################################################
|
||||
|
||||
" Load the plugin {{{1
|
||||
" mappings {{{1
|
||||
map <silent> <buffer> <localleader>h :call Hoist(line("."))<cr>
|
||||
map <silent> <buffer> <localleader>H :call DeHoistThis(line("."))<cr>
|
||||
"}}}1
|
||||
if exists("g:did_vo_hoist")
|
||||
finish
|
||||
endif
|
||||
if !exists("g:hoistParanoia")
|
||||
let g:hoistParanoia=0
|
||||
endif
|
||||
let g:did_vo_hoist = 1
|
||||
" Functions {{{1
|
||||
" RemoveTabsLine(line,tabs) {{{2
|
||||
" remove specified number of tabs from the beginning of line
|
||||
function! RemoveTabsLine(line,tabs)
|
||||
return substitute(getline(a:line),"^\\(\\t\\)\\{".a:tabs."}", "", "")
|
||||
endfunction
|
||||
"}}}2
|
||||
" MakeTempFilename(line) {{{2
|
||||
" return a string to use as the temporary filename for the hoisted area
|
||||
function! MakeTempFilename(line)
|
||||
return "vo_hoist.".a:line.strftime(".%Y%m%d%H%M%S").".otl"
|
||||
endfunction
|
||||
"}}}2
|
||||
" AddHoistFilename(line) {{{2
|
||||
" Add a temporary filename to a parent line to indicate hoisting
|
||||
function! AddHoistFilename(line)
|
||||
let l:newparent = getline(a:line)." __hoist:".MakeTempFilename(a:line)
|
||||
call setline(a:line,l:newparent)
|
||||
endfunction
|
||||
"}}}2
|
||||
"}}}2
|
||||
" DeleteHoistFilename(line) {{{2
|
||||
" Delete a temporary filename from a parent line
|
||||
function! DeleteHoistFilename(line)
|
||||
call setline(a:line,substitute(getline(a:line)," __hoist:.*","",""))
|
||||
endfunction
|
||||
"}}}2
|
||||
" ExtractHoistFilename(line) {{{2
|
||||
" Extract a filename from a hoisted parent
|
||||
function! ExtractHoistFilename(line)
|
||||
return substitute(getline(a:line),".* __hoist:","","")
|
||||
endfunction
|
||||
"}}}2
|
||||
" IsParent(line) {{{2
|
||||
" Return 1 if this line is a parent
|
||||
function! IsParent(line)
|
||||
return (Ind(a:line)+1) == Ind(a:line+1)
|
||||
endfunction
|
||||
"}}}2
|
||||
" IsHoistedParent(line) {{{2
|
||||
" Return 1 if this line is a parent with hoisted children
|
||||
function! IsHoistParent(line)
|
||||
return match(getline(a:line)," __hoist:","") != -1
|
||||
endfunction
|
||||
"}}}2
|
||||
" FindParent(line) {{{2
|
||||
" Return line if parent, parent line if not
|
||||
function! FindParent(line)
|
||||
if IsParent(a:line)
|
||||
return a:line
|
||||
else
|
||||
let l:parentindent = Ind(a:line)-1
|
||||
let l:searchline = a:line
|
||||
while (Ind(l:searchline) != l:parentindent) && (l:searchline > 0)
|
||||
let l:searchline = l:searchline-1
|
||||
endwhile
|
||||
return l:searchline
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" FindLastChild(line) {{{2
|
||||
" Return the line number of the last descendent of parent line
|
||||
function! FindLastChild(line)
|
||||
let l:parentindent = Ind(a:line)
|
||||
let l:searchline = a:line+1
|
||||
while Ind(l:searchline) > l:parentindent
|
||||
let l:searchline = l:searchline+1
|
||||
endwhile
|
||||
return l:searchline-1
|
||||
endfunction
|
||||
"}}}2
|
||||
"}}}2
|
||||
" Hoist(line) {{{2
|
||||
" Write the offspring of a parent to a new file, open it and remove the
|
||||
" leading tabs.
|
||||
function! Hoist(line)
|
||||
let l:parent = FindParent(a:line)
|
||||
if l:parent == 0
|
||||
return
|
||||
endif
|
||||
call cursor(l:parent,1)
|
||||
let l:firstline = l:parent+1
|
||||
let l:childindent = Ind(l:firstline)
|
||||
let l:lastline = FindLastChild(l:parent)
|
||||
let l:filename = MakeTempFilename(l:parent)
|
||||
echo l:firstline.",".l:lastline."w! ".l:filename
|
||||
let l:folded = foldclosed(l:parent)
|
||||
call cursor(l:parent,1)
|
||||
normal zo
|
||||
exe l:firstline.",".l:lastline."w! ".l:filename
|
||||
call AddHoistFilename(l:parent)
|
||||
silent write
|
||||
" log what we did in case we need to recover manually
|
||||
let l:doit = l:parent."write! >> .vo_hoist.".bufname(bufnr("%")).".log"
|
||||
exe l:doit
|
||||
let l:parentbuffer = bufnr("%")
|
||||
"WARNING: switching files
|
||||
let l:doit = "silent e +%s/^\\\\(\\\t\\\\)\\\\{"
|
||||
let l:doit = l:doit.l:childindent."}// ".l:filename." | "
|
||||
let l:doit = l:doit."let b:myParentBuffer = ".l:parentbuffer." | "
|
||||
let l:doit = l:doit."let b:myParentLine = ".l:parent." | "
|
||||
let l:doit = l:doit."call cursor(1,1)|"
|
||||
let l:doit = l:doit."let b:hoisted = 1"
|
||||
exe l:doit
|
||||
silent write
|
||||
endfunction
|
||||
"}}}2
|
||||
" DeleteChildren(line) {{{2
|
||||
" Delete the existing offspring of a parent
|
||||
function! DeleteChildren(line)
|
||||
let l:parent = FindParent(a:line)
|
||||
let l:firstline = l:parent+1
|
||||
let l:lastline = FindLastChild(l:parent)
|
||||
exe l:firstline.",".l:lastline."d"
|
||||
endfunction
|
||||
"}}}2
|
||||
" MakeTabString(n) {{{2
|
||||
" Return a string of n tabs
|
||||
function! MakeTabString(n)
|
||||
let l:string = ""
|
||||
let l:i = 0
|
||||
while l:i < a:n
|
||||
let l:string = l:string."\t"
|
||||
let l:i = l:i +1
|
||||
endwhile
|
||||
return l:string
|
||||
endfunction
|
||||
"}}}2
|
||||
" AddChildren(line) {{{2
|
||||
" Add left-justified children to parent. The filename is extracted from the
|
||||
" end of the parent line. The parent is assumed to have no children at this
|
||||
" point.
|
||||
function! AddChildren(line)
|
||||
let l:filename = ExtractHoistFilename(a:line)
|
||||
if filereadable(l:filename) == 1
|
||||
if a:line == line("$")
|
||||
exe "read ".l:filename
|
||||
if a:line != line("$")
|
||||
exe a:line+1.",$"." s/^/".MakeTabString(Ind(a:line)+1)."/"
|
||||
endif
|
||||
else
|
||||
exe a:line+1."ma v"
|
||||
call cursor(a:line,1)
|
||||
exe "read ".l:filename
|
||||
if a:line+1 != line("'v")
|
||||
exe a:line+1.",'v-1"." s/^/".MakeTabString(Ind(a:line)+1)."/"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" DeleteHoistFile(line) {{{2
|
||||
" Delete a temporary filename from a parent line
|
||||
function! DeleteHoistFile(line)
|
||||
if g:hoistParanoia
|
||||
return
|
||||
endif
|
||||
let l:filename = ExtractHoistFilename(a:line)
|
||||
call delete(l:filename)
|
||||
let l:filename = l:filename."~"
|
||||
call delete(l:filename)
|
||||
endfunction
|
||||
"}}}2
|
||||
" DeHoistThis(line) {{{2
|
||||
" Remove the old children, add the new children and remove the __hoist data
|
||||
" leading tabs from this file.
|
||||
function! DeHoistThis(line)
|
||||
let l:parent = FindParent(a:line)
|
||||
let l:folded = foldclosed(l:parent)
|
||||
call cursor(l:parent,1)
|
||||
if l:folded == l:parent
|
||||
normal zo
|
||||
endif
|
||||
call DeleteChildren(l:parent)
|
||||
call AddChildren(l:parent)
|
||||
call DeleteHoistFile(l:parent)
|
||||
call DeleteHoistFilename(l:parent)
|
||||
if l:folded == l:parent
|
||||
normal zc
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" DeHoist() {{{2
|
||||
" Remove the old children, add the new children and remove the __hoist data
|
||||
" leading tabs from the calling file.
|
||||
function! DeHoist()
|
||||
silent write
|
||||
if bufexists(b:myParentBuffer) == 0
|
||||
return
|
||||
endif
|
||||
let l:myParentBuffer = b:myParentBuffer
|
||||
let l:myParentLine = b:myParentLine
|
||||
bdelete
|
||||
" Warning switching files
|
||||
exe "buffer ".l:myParentBuffer
|
||||
call cursor(l:myParentLine,1)
|
||||
let l:parent = FindParent(l:myParentLine)
|
||||
let l:folded = foldclosed(l:parent)
|
||||
call cursor(l:parent,1)
|
||||
" if l:folded == l:parent
|
||||
" normal zo
|
||||
" endif
|
||||
normal zv
|
||||
silent call DeleteChildren(l:parent)
|
||||
silent call AddChildren(l:parent)
|
||||
silent call DeleteHoistFile(l:parent)
|
||||
silent call DeleteHoistFilename(l:parent)
|
||||
if l:folded == l:parent
|
||||
call cursor(l:parent,1)
|
||||
normal zc
|
||||
endif
|
||||
silent write
|
||||
endfunction
|
||||
"}}}2
|
||||
"}}}1
|
||||
" Autocommands {{{1
|
||||
au BufReadPost vo_hoist.*.otl cmap <buffer> wq call DeHoist()
|
||||
au BufReadPost vo_hoist.*.otl cmap <buffer> qa call DeHoist()
|
||||
au BufReadPost vo_hoist.*.otl cmap <buffer> q call DeHoist()
|
||||
au BufReadPost vo_hoist.*.otl cmap <buffer> x call DeHoist()
|
||||
au BufReadPost vo_hoist.*.otl nmap <buffer> ZZ :call DeHoist()<cr>
|
||||
"}}}1
|
||||
" vim600: set foldlevel=0 foldmethod=marker:
|
310
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_checkbox.otl
Normal file
310
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_checkbox.otl
Normal file
|
@ -0,0 +1,310 @@
|
|||
Checkboxes: votl_checkbox
|
||||
What is it?
|
||||
: Checkboxes is a plugin for project, task and list managment. It add an
|
||||
: understanding of check boxes and percentage of task completion to Vim
|
||||
: Outliner. It adds just three tags and six commands.
|
||||
Installation
|
||||
This should already be included in your Vim Outliner package
|
||||
The newest, stable version is included with this package in the plugin directory
|
||||
The pluging is already enabled in your ~/.vimoutlinerrc
|
||||
Tag Syntax
|
||||
[_] an unchecked item or incomplete task
|
||||
[X] a checked item or complete task
|
||||
[-] a canceled item - removes this item/branch from completion calculations
|
||||
% a placeholder for percentage of completion
|
||||
n% a percentage of completion, used in calculating parent completion
|
||||
n%w a percentage with a weighting factor - e.g.: 10%2
|
||||
[tag] a tag than can be replaced from a list of tags
|
||||
[tag] also the default tag name - will be replaced by tag[0] of tag list[0]
|
||||
[tag] [tag] tags must be separated by whitespace
|
||||
Example g:cbTags (put in .vimoutlinerrc)
|
||||
let g:cbTags = [
|
||||
\ ['TODO','FEEDBACK','VERIFY','DELEGATED','HOLDING']
|
||||
\,['Feature','Enhancement','Bug']
|
||||
\,['Low','Normal','High','URGENT']
|
||||
\,['Home','Lab','Work','Shopping']
|
||||
\]
|
||||
Checkbox Commands
|
||||
: The default <localleader> for VimOutliner is ,, so we will use this
|
||||
: leader in the command discussions.
|
||||
,,cb Create a check box
|
||||
: This works for the current heading or selected range of lines
|
||||
: including folds. Visual selection of the range of headings works
|
||||
: nicely. This command is currently not aware of body text. This
|
||||
: limited awareness needs to be fixed before this plugin can be
|
||||
: included in the standard Vim Outliner plugins.
|
||||
,,cB Create a check box (even if one exists)
|
||||
,,c% Create a checkbox and % symbol
|
||||
: This works just like ,,cb but add a % symbol for use in completion
|
||||
: calculations.
|
||||
,,cp Create a checkbox and % symbol
|
||||
: This works just like ,,cb but add a % symbol for use in completion
|
||||
: calculations; even on childless headings.
|
||||
,,cx Change check box state
|
||||
: If there is a checkbox on the line the cursor is on, change its
|
||||
: state. If it's checked, uncheck it and vice-versa. Then recompute
|
||||
: the completion of the entire branch starting from the root parent.
|
||||
,,cd Delete a checkbox
|
||||
: Delete the left-most check box on the selected heading(s).
|
||||
,,cz Compute completion
|
||||
: Starting at the heading the cursor is on, recursively compute the
|
||||
: completion level of all sub-headings.
|
||||
,,c1 Set completion to 10%
|
||||
: Set the completion to 10%, if a percentage already exists.
|
||||
,,c2 Set completion to 20%
|
||||
: Set the completion to 20%, if a percentage already exists.
|
||||
,,c3 Set completion to 30%
|
||||
: Set the completion to 30%, if a percentage already exists.
|
||||
,,c4 Set completion to 40%
|
||||
: Set the completion to 40%, if a percentage already exists.
|
||||
,,c5 Set completion to 50%
|
||||
: Set the completion to 50%, if a percentage already exists.
|
||||
,,c6 Set completion to 60%
|
||||
: Set the completion to 60%, if a percentage already exists.
|
||||
,,c7 Set completion to 70%
|
||||
: Set the completion to 70%, if a percentage already exists.
|
||||
,,c8 Set completion to 80%
|
||||
: Set the completion to 80%, if a percentage already exists.
|
||||
,,c9 Set completion to 90%
|
||||
: Set the completion to 90%, if a percentage already exists.
|
||||
,,c+ Increment the completion by 10%
|
||||
: Increment the completion by 10%, if a percentage already exists.
|
||||
,,c- Decrement the completion by 10%
|
||||
: Decrement the completion by 10%, if a percentage already exists.
|
||||
,,ct Set tag to next tag in current tag list
|
||||
: Set the tag under the cursor to the next tag in the list that
|
||||
: contains the current tag. This command is not mapped if g:cbTags
|
||||
: does not exist.
|
||||
,,cT Set tag to next tag list
|
||||
: Set the tag under the cursor to the first tag in the next tag list.
|
||||
: This command is not mapped if g:cbTags does not exist.
|
||||
How do I use it?
|
||||
Start with a simple example
|
||||
: Let's start with planning a small party; say a barbeque.
|
||||
Make the initial outline
|
||||
Barbeque
|
||||
Guests
|
||||
Bill and Barb
|
||||
Larry and Louise
|
||||
Marty and Mary
|
||||
Food
|
||||
Chicken
|
||||
Ribs
|
||||
Corn on the cob
|
||||
Beverages
|
||||
Soda
|
||||
Iced Tea
|
||||
Beer
|
||||
Party Favors
|
||||
Squirt guns
|
||||
Hats
|
||||
Name tags
|
||||
Materials
|
||||
Paper Plates
|
||||
Napkins
|
||||
Trash Containers
|
||||
Add the check boxes
|
||||
: This can be done by visually selecting them and typing ,,cb.
|
||||
: When done, you should see this:
|
||||
[_] Barbeque
|
||||
[_] Guests
|
||||
[_] Bill and Barb
|
||||
[_] Larry and Louise
|
||||
[_] Marty and Mary
|
||||
[_] Food
|
||||
[_] Chicken
|
||||
[_] Ribs
|
||||
[_] Corn on the cob
|
||||
[_] Beverages
|
||||
[_] Soda
|
||||
[_] Iced Tea
|
||||
[_] Beer
|
||||
[_] Party Favors
|
||||
[_] Squirt guns
|
||||
[_] Hats
|
||||
[_] Name tags
|
||||
[_] Materials
|
||||
[_] Paper Plates
|
||||
[_] Napkins
|
||||
[_] Trash Containers
|
||||
Now check off what's done
|
||||
: Checking off what is complete is easy with the ,,cx command.
|
||||
: Just place the cursor on a heading and ,,cx it. Now you can see
|
||||
: what's done as long as the outline is fully expanded.
|
||||
[_] Barbeque
|
||||
[X] Guests
|
||||
[X] Bill and Barb
|
||||
[X] Larry and Louise
|
||||
[X] Marty and Mary
|
||||
[_] Food
|
||||
[X] Chicken
|
||||
[X] Ribs
|
||||
[_] Corn on the cob
|
||||
[_] Beverages
|
||||
[_] Soda
|
||||
[X] Iced Tea
|
||||
[X] Beer
|
||||
[_] Party Favors
|
||||
[_] Squirt guns
|
||||
[_] Hats
|
||||
[_] Name tags
|
||||
[_] Materials
|
||||
[X] Paper Plates
|
||||
[_] Napkins
|
||||
[X] Trash Containers
|
||||
Getting more advanced
|
||||
Now summarize what's done
|
||||
: You can summarize what is done with the ,,cz command. Place the
|
||||
: cursor on the 'Barbeque' heading and ,,cz it. The command will
|
||||
: recursively process the outline and update the check boxes of
|
||||
: the parent headlines. You should see:
|
||||
: (Note: the only change is on the 'Guests' heading. It changed
|
||||
: because all of its children are complete.)
|
||||
[_] Barbeque
|
||||
[X] Guests
|
||||
[X] Bill and Barb
|
||||
[X] Larry and Louise
|
||||
[X] Marty and Mary
|
||||
[_] Food
|
||||
[X] Chicken
|
||||
[X] Ribs
|
||||
[_] Corn on the cob
|
||||
[_] Beverages
|
||||
[_] Soda
|
||||
[X] Iced Tea
|
||||
[X] Beer
|
||||
[_] Party Favors
|
||||
[_] Squirt guns
|
||||
[_] Hats
|
||||
[_] Name tags
|
||||
[_] Materials
|
||||
[X] Paper Plates
|
||||
[_] Napkins
|
||||
[X] Trash Containers
|
||||
Add percentages for a better view
|
||||
: You can get a much better view of what's going on, especially
|
||||
: with collapsed headings, if you add percentages. Place a 0% on
|
||||
: each heading that has children like this:
|
||||
[_] 59% Barbeque
|
||||
[X] 100% Guests
|
||||
[X] Bill and Barb
|
||||
[X] Larry and Louise
|
||||
[X] Marty and Mary
|
||||
[_] 66% Food
|
||||
[X] Chicken
|
||||
[X] Ribs
|
||||
[_] Corn on the cob
|
||||
[_] 66% Beverages
|
||||
[_] Soda
|
||||
[X] Iced Tea
|
||||
[X] Beer
|
||||
[_] 0% Party Favors
|
||||
[_] Squirt guns
|
||||
[_] Hats
|
||||
[_] Name tags
|
||||
[_] 66% Materials
|
||||
[X] Paper Plates
|
||||
[_] Napkins
|
||||
[X] Trash Containers
|
||||
Now compute the percentage of completion
|
||||
: After adding the 0% symbols, place the cursor on the 'Barbeque'
|
||||
: heading and execute ,,cz as before. Keep in mind that the
|
||||
: recursive percentages are weighted. You should see:
|
||||
[_] 59% Barbeque
|
||||
[X] 100% Guests
|
||||
[X] Bill and Barb
|
||||
[X] Larry and Louise
|
||||
[X] Marty and Mary
|
||||
[_] 66% Food
|
||||
[X] Chicken
|
||||
[X] Ribs
|
||||
[_] Corn on the cob
|
||||
[_] 66% Beverages
|
||||
[_] Soda
|
||||
[X] Iced Tea
|
||||
[X] Beer
|
||||
[_] 0% Party Favors
|
||||
[_] Squirt guns
|
||||
[_] Hats
|
||||
[_] Name tags
|
||||
[_] 66% Materials
|
||||
[X] Paper Plates
|
||||
[_] Napkins
|
||||
[X] Trash Containers
|
||||
Complete a few more just for fun
|
||||
: Mark Salad and Soda and recompute with ,,cz and you should
|
||||
: see the ouline below.
|
||||
:
|
||||
: Try playng around with zc and zo to see the effects of opening
|
||||
: and closing folds. Even if you place the cursor on 'Barbeque'
|
||||
: and zo it, you still have a good understanding of how complete
|
||||
: the project is.
|
||||
[_] 66% Barbeque
|
||||
[X] 100% Guests
|
||||
[X] Bill and Barb
|
||||
[X] Larry and Louise
|
||||
[X] Marty and Mary
|
||||
[_] 66% Food
|
||||
[X] Chicken
|
||||
[X] Ribs
|
||||
[_] Corn on the cob
|
||||
[X] 100% Beverages
|
||||
[X] Soda
|
||||
[X] Iced Tea
|
||||
[X] Beer
|
||||
[_] 0% Party Favors
|
||||
[_] Squirt guns
|
||||
[_] Hats
|
||||
[_] Name tags
|
||||
[_] 66% Materials
|
||||
[X] Paper Plates
|
||||
[_] Napkins
|
||||
[X] Trash Containers
|
||||
Getting way more advanced
|
||||
Weighted Tasks
|
||||
Here is a simple outline to track a project
|
||||
[_] 22% Garage Upgrade
|
||||
[_] 66% Clean out old junk
|
||||
[X] 100% empty garage
|
||||
[X] 100% sort junk
|
||||
[_] 0% dispose of junk
|
||||
[_] 0% Build Shelves
|
||||
[_] 0% Oranize Junk
|
||||
[_] 0% oranize saved junk
|
||||
[_] 0% put junk on shelves
|
||||
What if some tasks take more effort?
|
||||
: Assume that you know that it will take twice as long to sort
|
||||
: junk as it does to remove it from the garage or to dispose
|
||||
: of it. This can be represented with weights. Notice the
|
||||
: completion percentage of 'Clean out old junk' once a weight
|
||||
: has been added. Each percentage can be weighted.
|
||||
[_] 25% Garage Upgrade
|
||||
[_] 75% Clean out old junk
|
||||
[X] 100% empty garage
|
||||
[X] 100%2 sort junk
|
||||
[_] 0% dispose of junk
|
||||
[_] 0% Build Shelves
|
||||
[_] 0% Oranize Junk
|
||||
[_] 0% oranize saved junk
|
||||
[_] 0% put junk on shelves
|
||||
Complex weighting
|
||||
[_] 83% Garage Upgrade
|
||||
[_] 75%2 Clean out old junk
|
||||
[X] 100% empty garage
|
||||
[X] 100%2 sort junk
|
||||
[_] 0% dispose of junk
|
||||
[X] 100%2 Build Shelves
|
||||
[_] 66% Oranize Junk
|
||||
[X] 100%2 oranize saved junk
|
||||
[_] 0% put junk on shelves
|
||||
Tags: Add more information to a heading
|
||||
: Additional information and workflow information can easily
|
||||
: be added to headings with tags. The command ,,ct can be used
|
||||
: to cycle a tag among it sibling tags in g:cbTags. ,,cT can
|
||||
: be be used to cycle a tag to a different list of sibling
|
||||
: tags.
|
||||
My Software Project
|
||||
[_] 33% To Do
|
||||
[X] Misspellings in documention [Bug] [High]
|
||||
[_] Installation infects all networked systems with app [Feature] [Normal]
|
||||
[_] Clean garage [Low] [@Home]
|
475
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_checkbox.vim
Executable file
475
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_checkbox.vim
Executable file
|
@ -0,0 +1,475 @@
|
|||
"######################################################################
|
||||
"# VimOutliner Checkboxes
|
||||
"# Copyright (C) 2003 by Noel Henson noel@noels-lab.com
|
||||
"# The file is currently an experimental part of Vim Outliner.
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"######################################################################
|
||||
|
||||
" mappings {{{1
|
||||
" insert a chechbox
|
||||
noremap <silent><buffer> <localleader>cb :call SafelyInsertCheckBox()<cr>
|
||||
noremap <silent><buffer> <localleader>c% :call SafelyInsertCheckBoxPercent()<cr>
|
||||
noremap <silent><buffer> <localleader>cp :call SafelyInsertCheckBoxPercentAlways()<cr>
|
||||
noremap <silent><buffer> <localleader>cB :call InsertCheckBox()<cr>
|
||||
|
||||
" delete a chechbox
|
||||
noremap <silent><buffer> <localleader>cd :call DeleteCheckbox()<cr>
|
||||
|
||||
" switch the status of the box and adjust percentages
|
||||
if !exists('g:vo_checkbox_fast_calc') || g:vo_checkbox_fast_calc == 1
|
||||
" Use new and faster method
|
||||
noremap <silent><buffer> <localleader>cx :call SwitchBox() <bar>call CalculateMyBranch(line("."))<cr>
|
||||
noremap <silent><buffer> <localleader>c+ :call IncPercent(".") <bar>call CalculateMyBranch(line("."))<cr>
|
||||
noremap <silent><buffer> <localleader>c- :call DecPercent(".") <bar>call CalculateMyBranch(line("."))<cr>
|
||||
noremap <silent><buffer> <localleader>c1 :call SetPercent(".",10)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c2 :call SetPercent(".",20)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c3 :call SetPercent(".",30)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c4 :call SetPercent(".",40)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c5 :call SetPercent(".",50)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c6 :call SetPercent(".",60)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c7 :call SetPercent(".",70)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c8 :call SetPercent(".",80)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
noremap <silent><buffer> <localleader>c9 :call SetPercent(".",90)<bar>call CalculateMyBranch(line('.'))<cr>
|
||||
else
|
||||
" Use the old method
|
||||
noremap <silent><buffer> <localleader>cx :call SwitchBox() <bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c+ :call IncPercent(".") <bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c- :call DecPercent(".") <bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c1 :call SetPercent(".",10)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c2 :call SetPercent(".",20)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c3 :call SetPercent(".",30)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c4 :call SetPercent(".",40)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c5 :call SetPercent(".",50)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c6 :call SetPercent(".",60)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c7 :call SetPercent(".",70)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c8 :call SetPercent(".",80)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
noremap <silent><buffer> <localleader>c9 :call SetPercent(".",90)<bar>call NewHMD(FindRootParent(line(".")))<cr>
|
||||
endif
|
||||
|
||||
" calculate the proportion of work done on the subtree
|
||||
noremap <silent><buffer> <localleader>cz :call NewHMD(FindRootParent(line(".")))<cr>
|
||||
|
||||
" tag list key mappings
|
||||
if exists("g:cbTags")
|
||||
noremap <silent><buffer> <localleader>ct :call SetNextTag()<cr>
|
||||
noremap <silent><buffer> <localleader>cT :call SetNextList()<cr>
|
||||
endif
|
||||
|
||||
"}}}1
|
||||
" Load guard for functions {{{1
|
||||
if exists('s:loaded')
|
||||
finish
|
||||
endif
|
||||
let s:loaded = 1
|
||||
|
||||
" InsertCheckBox() {{{1
|
||||
" Insert a checkbox at the beginning of a header without disturbing the
|
||||
" current folding.
|
||||
function! InsertCheckBox()
|
||||
let @x = "[_] "
|
||||
normal! ^"xP
|
||||
endfunction
|
||||
"}}}1
|
||||
" Safely InsertCheckBox() {{{1
|
||||
" Insert a checkbox at the beginning of a header without disturbing the
|
||||
" current folding only if there is no checkbox already.
|
||||
function! SafelyInsertCheckBox()
|
||||
if match(getline("."),"^\t\t*\[<>:;|\]") != -1
|
||||
return
|
||||
endif
|
||||
if match(getline("."),"[\[X_\]]") == -1
|
||||
let @x = "[_] "
|
||||
normal! ^"xP
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
" Safely InsertCheckBoxPercent() {{{1
|
||||
" Insert a checkbox and % sign at the beginning of a header without disturbing
|
||||
" the current folding only if there is no checkbox already.
|
||||
function! SafelyInsertCheckBoxPercent()
|
||||
if match(getline("."),"^\t\t*\[<>:;|\]") != -1
|
||||
return
|
||||
endif
|
||||
if match(getline("."), "[\[X_\]]") == -1
|
||||
if Ind(line(".")+1) > Ind(line("."))
|
||||
let @x = "[_] % "
|
||||
else
|
||||
let @x = "[_] "
|
||||
endif
|
||||
normal! ^"xP
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
" Safely InsertCheckBoxPercentAlways() {{{1
|
||||
" Insert a checkbox and % sign at the beginning of a header without disturbing
|
||||
" the current folding only if there is no checkbox already. Include the
|
||||
" checkbox even on childless headings.
|
||||
function! SafelyInsertCheckBoxPercentAlways()
|
||||
if match(getline("."),"^\t\t*\[<>:;|\]") != -1
|
||||
return
|
||||
endif
|
||||
if match(getline("."), "[\[X_\]]") == -1
|
||||
let @x = "[_] % "
|
||||
normal! ^"xP
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
" SetBox(char) {{{1
|
||||
" Switch the state of the checkbox on the current line.
|
||||
function! SetBox(char)
|
||||
substitute/\[.\]/\="[".expand(a:char)."]"/
|
||||
if a:char == 'X'
|
||||
call SetPercent(".",100)
|
||||
elseif a:char == '_'
|
||||
call SetPercent(".",0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"}}}1
|
||||
" SwitchBox() {{{1
|
||||
" Switch the state of the checkbox on the current line.
|
||||
function! SwitchBox()
|
||||
let l:line = getline(".")
|
||||
let questa = strridx(l:line,"[_]")
|
||||
let questb = strridx(l:line,"[X]")
|
||||
if (questa != -1) || (questb != -1)
|
||||
if (questa != -1)
|
||||
call SetBox('X')
|
||||
else
|
||||
call SetBox('_')
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
" DeleteCheckbox() {{{1
|
||||
" Delete a checkbox if one exists
|
||||
function! DeleteCheckbox()
|
||||
let questa = strridx(getline("."),"[_]")
|
||||
let questb = strridx(getline("."),"[X]")
|
||||
if (questa != -1) || (questb != -1)
|
||||
if (questa != -1)
|
||||
substitute/\(^\s*\)\[_\] \(.*\)/\1\2/
|
||||
else
|
||||
substitute/\(^\s*\)\[X\] \(.*\)/\1\2/
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
" Ind(line) {{{1
|
||||
" Return the index of the line.
|
||||
" Remove it when using the new version of VO
|
||||
function! Ind(line)
|
||||
return indent(a:line) / &tabstop
|
||||
endf
|
||||
" FindMyParent(line) {{{1
|
||||
" returns the line number of the parent of the current node
|
||||
function! FindMyParent(line)
|
||||
let l:mylevel = Ind(a:line)
|
||||
if l:mylevel == 0
|
||||
return (a:line)
|
||||
endif
|
||||
let l:i = a:line
|
||||
while Ind(l:i) >= l:mylevel
|
||||
let l:i -= 1
|
||||
endwhile
|
||||
return l:i
|
||||
endf
|
||||
|
||||
" FindRootParent(line) {{{1
|
||||
" returns the line number of the root parent for any child
|
||||
function! FindRootParent(line)
|
||||
if Ind(a:line) == 0
|
||||
return (a:line)
|
||||
endif
|
||||
let l:i = a:line
|
||||
while l:i > 1 && Ind(l:i) > 0
|
||||
let l:i = l:i - 1
|
||||
endwhile
|
||||
return l:i
|
||||
endf
|
||||
|
||||
" LimitPercent(percent) {{{1
|
||||
" Limits percentage values to between 0 and 100
|
||||
function! LimitPercent(val)
|
||||
if a:val > 100
|
||||
return 100
|
||||
elseif a:val < 0
|
||||
return 0
|
||||
else
|
||||
return a:val
|
||||
endif
|
||||
endf
|
||||
|
||||
" GetPercent(line) {{{1
|
||||
" Get the percent complete from a line
|
||||
function! GetPercent(line)
|
||||
let l:proportion = 0
|
||||
let mbegin=match(getline(a:line), " [0-9]*%")
|
||||
if mbegin
|
||||
let mend=matchend(getline(a:line), " [0-9]*%")
|
||||
let l:proportion=getline(a:line)[mbegin+1 : mend-1]
|
||||
let l:proportion=str2nr(l:proportion)
|
||||
endif
|
||||
return l:proportion
|
||||
endf
|
||||
|
||||
" SetPercent(line,proportion) {{{1
|
||||
" Set the percent complete for a line
|
||||
function! SetPercent(line,proportion)
|
||||
let mbegin=match(getline(a:line), " [0-9]*%")
|
||||
if mbegin
|
||||
call setline(a:line,substitute(getline(a:line)," [0-9]*%"," ".a:proportion."%",""))
|
||||
endif
|
||||
endf
|
||||
|
||||
" IncPercent(line) {{{1
|
||||
" Increments the percent doneness by 10%
|
||||
function! IncPercent(line)
|
||||
if match(getline(a:line), " [0-9]*%")
|
||||
call SetPercent(a:line,LimitPercent(GetPercent(a:line)+10))
|
||||
endif
|
||||
endf
|
||||
|
||||
" DecPercent(line) {{{1
|
||||
" Decrements the percent doneness by 10%
|
||||
function! DecPercent(line)
|
||||
if match(getline(a:line), " [0-9]*%")
|
||||
let l:percent = GetPercent(a:line)
|
||||
call setline(a:line,substitute(getline(a:line),"\\[X\\]","[_]",""))
|
||||
call SetPercent(a:line,LimitPercent(l:percent-10))
|
||||
endif
|
||||
endf
|
||||
|
||||
" ComputePW(line,count,done) {{{1
|
||||
" Computes proportion and weight of a node
|
||||
" Returns (proportion,weight) proportion could be a flag of -1
|
||||
function! ComputePW(line,count,done)
|
||||
let l:proportion=0
|
||||
let l:haspercent = 0
|
||||
" get the percent
|
||||
let mbegin=match(getline(a:line), " [0-9]*%")
|
||||
if mbegin != -1
|
||||
let l:haspercent = 1
|
||||
let mend=matchend(getline(a:line), " [0-9]*%")
|
||||
let l:proportion=str2nr(getline(a:line)[mbegin+1 : mend-1])
|
||||
endif
|
||||
" get the weight
|
||||
let l:weight=1
|
||||
let mbegin=match(getline(a:line), "%[0-9]\\+")
|
||||
if mbegin != -1
|
||||
let mend=matchend(getline(a:line), "%[0-9]\\+\s")
|
||||
let l:weight=str2nr(getline(a:line)[mbegin+1 : mend-1])
|
||||
endif
|
||||
" compute the proportion
|
||||
if a:count>0
|
||||
let l:proportion = ((a:done*100)/a:count)/100
|
||||
elseif match(getline(a:line),"\\[X\\]") != -1
|
||||
let l:proportion = 100
|
||||
elseif match(getline(a:line),"\\[-\\]") != -1
|
||||
let l:weight = 0
|
||||
endif
|
||||
" update non-ignored items
|
||||
let l:questa = strridx(getline(a:line),"[-]")
|
||||
if l:questa == -1
|
||||
call setline(a:line,substitute(getline(a:line)," [0-9]*%"," ".l:proportion."%",""))
|
||||
endif
|
||||
" Limit proportion to 0 or 100 if there is not a percentage sign
|
||||
if !haspercent && (!exists('g:vo_checkbox_fast_calc') || g:vo_checkbox_fast_calc == 1)
|
||||
let l:proportion = l:proportion == 100 ? l:proportion : 0
|
||||
endif
|
||||
" update the completion
|
||||
if l:questa != -1
|
||||
return [100,l:weight]
|
||||
elseif l:proportion == 100
|
||||
call setline(a:line,substitute(getline(a:line),"\\[_\\]","[X]",""))
|
||||
return [100,l:weight]
|
||||
elseif l:proportion == 0 && a:count == 0
|
||||
if match(getline(a:line),"\\[X\\]") != -1
|
||||
return [100,l:weight]
|
||||
elseif match(getline(a:line),"\\[_\\]") != -1
|
||||
return [0,l:weight]
|
||||
else
|
||||
return [-1,l:weight]
|
||||
endif
|
||||
else
|
||||
call setline(a:line,substitute(getline(a:line),"\\[X\\]","[_]",""))
|
||||
return [l:proportion,l:weight]
|
||||
endif
|
||||
endf
|
||||
|
||||
" CalculateMyChildren(line) {{{1
|
||||
" Calculates percent completion only on the immediate children of the
|
||||
" parent specified by line.
|
||||
function! CalculateMyChildren(line)
|
||||
let l:done = 0
|
||||
let l:count = 0
|
||||
let l:line = a:line + 1
|
||||
let l:mylevel = Ind(a:line)
|
||||
let l:childlevel = l:mylevel+1
|
||||
while l:mylevel < Ind(l:line) " I have children
|
||||
if l:childlevel == Ind(l:line)
|
||||
let l:childstat = ComputePW(l:line,0,0)
|
||||
let l:childdoneness = l:childstat[0] * l:childstat[1]
|
||||
if l:childdoneness >= 0
|
||||
let l:done += l:childdoneness
|
||||
let l:count += l:childstat[1]
|
||||
endif
|
||||
endif
|
||||
let l:line += 1
|
||||
endwhile
|
||||
return ComputePW(a:line,l:count,l:done) " returns with (proportion,weight)
|
||||
endf
|
||||
|
||||
" CalculateMyBranch(line) {{{1
|
||||
" Calculate from the leaf, up unlke NewHMD
|
||||
function! CalculateMyBranch(line)
|
||||
call NewHMD(a:line) " compute and adjust my children, if I have any
|
||||
let l:line = a:line
|
||||
while Ind(l:line) > 0
|
||||
let l:line = FindMyParent(l:line)
|
||||
call CalculateMyChildren(l:line)
|
||||
endwhile
|
||||
endf
|
||||
|
||||
" NewHMD(line) {{{1
|
||||
" (New How Many Done)
|
||||
" Calculates proportion of already done work in the subtree
|
||||
" Recursive, but slow because it computes an entire branch of an outline
|
||||
" from level 1.
|
||||
" Returns (proportion,weight) proportion could be a flag of -1
|
||||
function! NewHMD(line)
|
||||
let l:done = 0
|
||||
let l:count = 0
|
||||
let l:line = a:line+1
|
||||
let l:mylevel = Ind(a:line)
|
||||
let l:childlevel = l:mylevel+1
|
||||
while l:mylevel < Ind(l:line) " I have children
|
||||
if l:childlevel == Ind(l:line)
|
||||
let l:childstat = NewHMD(l:line)
|
||||
let l:childdoneness = l:childstat[0] * l:childstat[1]
|
||||
if l:childdoneness >= 0
|
||||
let l:done += l:childdoneness
|
||||
let l:count += l:childstat[1]
|
||||
endif
|
||||
endif
|
||||
let l:line += 1
|
||||
endwhile
|
||||
return ComputePW(a:line,l:count,l:done) " returns with (proportion,weight)
|
||||
endf
|
||||
|
||||
" Experimental Heading Tags {{{1
|
||||
|
||||
if !exists('g:cbTags')
|
||||
finish
|
||||
endif
|
||||
|
||||
" GetTag() {{{2
|
||||
" return the tag word under the cursor
|
||||
function! GetTag()
|
||||
let word = expand("<cWORD>")
|
||||
if word[0] == '[' && word[-1:] == ']'
|
||||
return word[1:-2]
|
||||
endif
|
||||
return ""
|
||||
endfunction
|
||||
|
||||
" WhereInLists(word) {{{2
|
||||
" return a single-entry list with a pair of values [listIndex,tagIndex]
|
||||
" return -1,-1 if tag word not found
|
||||
function! WhereInLists(word)
|
||||
let lidx = 0
|
||||
for list in g:cbTags
|
||||
let tidx = index(list,a:word)
|
||||
if tidx >= 0
|
||||
return [lidx,tidx]
|
||||
endif
|
||||
let lidx += 1
|
||||
endfor
|
||||
return [-1,-1]
|
||||
endfunction
|
||||
|
||||
" NextTagIdx(lidx,tidx) {{{2
|
||||
" return the index of the next tag in the current list
|
||||
function! NextTagIdx(lidx,tidx)
|
||||
if a:tidx >= 0
|
||||
let llen = len(g:cbTags[a:lidx])
|
||||
let tidx = (a:tidx + 1)%llen
|
||||
endif
|
||||
return tidx
|
||||
endfunction
|
||||
|
||||
" GetNextTag(word) {{{2
|
||||
" return the next tag word (from a:word) in the list
|
||||
function! GetNextTag(word)
|
||||
if a:word == 'tag'
|
||||
return g:cbTags[0][0]
|
||||
endif
|
||||
let liti = WhereInLists(a:word)
|
||||
if liti[1] == -1
|
||||
return ""
|
||||
endif
|
||||
let liti[1] = NextTagIdx(liti[0],liti[1])
|
||||
let nextword = g:cbTags[liti[0]][liti[1]]
|
||||
return nextword
|
||||
endfunction
|
||||
|
||||
" SetNextTag() {{{2
|
||||
" set the current tag to the next tag in the same list
|
||||
" this is circular, the last tag will roll to the first tag
|
||||
function! SetNextTag()
|
||||
let oldtag = GetTag()
|
||||
let newtag = GetNextTag(oldtag)
|
||||
if newtag == ""
|
||||
return
|
||||
endif
|
||||
let sub = "normal!ci[".newtag
|
||||
exec sub
|
||||
endfunction
|
||||
|
||||
" NextListIdx(lidx) {{{2
|
||||
" return the index of the next list
|
||||
function! NextListIdx(lidx)
|
||||
if a:lidx >= 0
|
||||
let llen = len(g:cbTags)
|
||||
let lidx = (a:lidx + 1)%llen
|
||||
endif
|
||||
return lidx
|
||||
endfunction
|
||||
|
||||
" GetNextList(word) {{{2
|
||||
" return the next tag word (from a:word) in the list
|
||||
function! GetNextList(word)
|
||||
if a:word == 'tag'
|
||||
return g:cbTags[0][0]
|
||||
endif
|
||||
let liti = WhereInLists(a:word)
|
||||
if liti[1] == -1
|
||||
return ""
|
||||
endif
|
||||
let liti[0] = NextListIdx(liti[0])
|
||||
let nextword = g:cbTags[liti[0]][0]
|
||||
return nextword
|
||||
endfunction
|
||||
|
||||
" SetNextList() {{{2
|
||||
" set the current tag to the first tag in the next list
|
||||
" this is circular, the last list will roll to the first list
|
||||
function! SetNextList()
|
||||
let oldtag = GetTag()
|
||||
let newtag = GetNextList(oldtag)
|
||||
if newtag == ""
|
||||
return
|
||||
endif
|
||||
let sub = "normal!ci[".newtag
|
||||
exec sub
|
||||
endfunction
|
||||
" vim600: set foldlevel=0 foldmethod=marker:
|
139
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_clock.vim
Normal file
139
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_clock.vim
Normal file
|
@ -0,0 +1,139 @@
|
|||
"######################################################################
|
||||
"# VimOutliner Clock
|
||||
"# Copyright (C) 2011 by Daniel Carl
|
||||
"# The file is currently an experimental part of Vim Outliner.
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"######################################################################
|
||||
" Shortlog{{{1
|
||||
"
|
||||
" This plugin of vimoutliner allow the simple tracking of times and the
|
||||
" calculation of them in seconds, minutes, hours or days
|
||||
" Exmaple :
|
||||
" May -> 64.75 h
|
||||
" Working time week 51 -> 46.00 h
|
||||
" Working time week 52 -> 18.75 h
|
||||
" 2010-05-03 [08:00:00 -- 17:45:00] -> 9.75 h
|
||||
" 2010-05-04 [09:00:00 -- 18:00:00] -> 9.00 h
|
||||
"
|
||||
" TODO: Use better date calculation to track also time around 00:00
|
||||
" [23:00:00 -- 03:00:00] that will at the time lead to negative
|
||||
" hours.
|
||||
" TODO: change the clocking format so that times over several days could
|
||||
" be calculated - [2010-05-03 08:00:00 -- 2010-05-23 26:30:45] or
|
||||
" a shorter dateformat - this seems to need a more complex
|
||||
" datehandling
|
||||
" TODO: write a helppage for the vimoutliner that describes the votd_clock
|
||||
" TODO: allow the user to select his own dateformat
|
||||
"}}}1
|
||||
" ClockStart(space) {{{1
|
||||
" Insert a space, then the datetime.
|
||||
function! ClockStart(space)
|
||||
let @x = ""
|
||||
if a:space == 1
|
||||
let @x = " "
|
||||
endif
|
||||
let @x = @x . strftime("%Y-%m-%d [%T -- %T] ->")
|
||||
normal! "xp
|
||||
endfunction
|
||||
"}}}1
|
||||
" ClockStop() {{{1
|
||||
" Insert a space, then the datetime.
|
||||
function! ClockStop()
|
||||
if match(getline("."), "\\[.* -- .*\\]\\s*-\>") != -1
|
||||
call setline(".",substitute(getline(".")," -- .*]\\s*-\>"," -- ".strftime("%T] ->"),""))
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
" CalculateSeconds(str) {{{1
|
||||
" Calculates the seconds between the start and the end time.
|
||||
function! CalculateSeconds(str)
|
||||
let l:parts = split(a:str,"\ --\ ")
|
||||
let l:startparts = split(l:parts[0],":")
|
||||
let l:endparts = split(l:parts[1],":")
|
||||
|
||||
let l:seconds = (str2nr(l:endparts[2]) - str2nr(l:startparts[2]))
|
||||
let l:seconds = (str2nr(l:endparts[1]) - str2nr(l:startparts[1])) * 60 + l:seconds
|
||||
let l:seconds = (str2nr(l:endparts[0]) - str2nr(l:startparts[0])) * 3600 + l:seconds
|
||||
return l:seconds
|
||||
endfunction
|
||||
" }}}1
|
||||
" CalculateDuration() {{{1
|
||||
" insert date time
|
||||
function! CalculateDuration(line)
|
||||
let l:seconds=0
|
||||
let l:count=0
|
||||
let l:i = 1
|
||||
while Ind(a:line) < Ind(a:line+l:i)
|
||||
if (Ind(a:line)+1) == (Ind(a:line+l:i))
|
||||
let l:childseconds = CalculateDuration(a:line+l:i)
|
||||
if l:childseconds >= 0
|
||||
let l:seconds = l:seconds + l:childseconds
|
||||
let l:count = l:count+1
|
||||
endif
|
||||
endif
|
||||
let l:i = l:i+1
|
||||
endwhile
|
||||
|
||||
" if no childs found calculate the seconds for the line
|
||||
let l:lineString = getline(a:line)
|
||||
if match(l:lineString,"\\s*-\>") != -1
|
||||
let l:times = matchstr(l:lineString,"\\[.* -- .*\\]\\s*-\>")
|
||||
if l:times != ""
|
||||
" calculate the real time difference
|
||||
let l:seconds = CalculateSeconds(substitute(l:times,"\\[\\(.*\\)\\]","\\1",""))
|
||||
endif
|
||||
" don't add summarized time to text lines
|
||||
if match(l:lineString,"^\t*[;:<>]") == -1
|
||||
if match(l:lineString," -\> [0-9 .]*s") != -1
|
||||
call setline(a:line,substitute(l:lineString," -\>.*s"," -> ".l:seconds." s",""))
|
||||
elseif match(getline(a:line)," -\> [0-9 .]*m") != -1
|
||||
call setline(a:line,substitute(l:lineString," -\>.*m"," -> ".printf("%.2f",l:seconds/60.0)." m",""))
|
||||
elseif match(getline(a:line)," -\> [0-9 .]*d") != -1
|
||||
call setline(a:line,substitute(l:lineString," -\>.*"," -> ".printf("%.2f",(l:seconds/86400.0))." d",""))
|
||||
else
|
||||
call setline(a:line,substitute(l:lineString," -\>.*"," -> ".printf("%.2f",(l:seconds/3600.0))." h",""))
|
||||
endif
|
||||
endif
|
||||
" else
|
||||
" return -1
|
||||
endif
|
||||
return l:seconds
|
||||
endf
|
||||
"}}}1
|
||||
" FindRootParent(line) {{{1
|
||||
" returns the line number of the root parent for any child
|
||||
function! FindRootParent(line)
|
||||
if Ind(a:line) == 0
|
||||
return (a:line)
|
||||
endif
|
||||
let l:i = a:line
|
||||
while l:i > 1 && Ind(l:i) > 0
|
||||
let l:i = l:i - 1
|
||||
endwhile
|
||||
return l:i
|
||||
endf
|
||||
"}}}1
|
||||
" UpdateTimes() {{{1
|
||||
" initiates the update of all times in the tree where the cursur is located
|
||||
function! UpdateTimes()
|
||||
call CalculateDuration(FindRootParent(line(".")))
|
||||
endf
|
||||
"}}}1
|
||||
" Mappings {{{1
|
||||
nmap <silent> <buffer> <localleader>cs $:call ClockStart(1)<cr>
|
||||
imap <silent> <buffer> <localleader>cs ~<esc>x:call ClockStart(0)<cr>a
|
||||
nmap <silent> <buffer> <localleader>cS $:call ClockStop()<cr>:call UpdateTimes()<cr>
|
||||
imap <silent> <buffer> <localleader>cS ~<esc>x:call ClockStop()<cr>:call UpdateTimes()<cr>i
|
||||
nmap <silent> <buffer> <localleader>cu $:call UpdateTimes()<cr>
|
||||
"}}}1
|
||||
" The End
|
||||
" vim600: set foldmethod=marker foldlevel=0:
|
157
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_format.vim
Executable file
157
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_format.vim
Executable file
|
@ -0,0 +1,157 @@
|
|||
"######################################################################
|
||||
"# VimOutliner Format plugin
|
||||
"# Copyright (C) 2011 by Jostein Berntsen
|
||||
"# The file is currently an experimental part of Vim Outliner.
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"######################################################################
|
||||
" Documentation{{{1
|
||||
"
|
||||
" This script inserts bullets, dashes, and arrows in front of lines, including
|
||||
" VO body text. To insert markers for several lines, select the lines with V
|
||||
" and execute the mapping. Indents will be kept as they are.
|
||||
" You can also use the MakeText function to make body text from headers or
|
||||
" lists.
|
||||
"
|
||||
" There are also functions for
|
||||
" 1) Aligning text in a paragraph to a level 1 header
|
||||
" 2) Insert checkboxes for all headings in a paragraph
|
||||
" 3) Indent text in a paragraph/branch to the right
|
||||
" 4) Indent text in a paragraph/branch to the left
|
||||
"
|
||||
"}}}1
|
||||
" Load guard for functions {{{1
|
||||
if exists("g:loaded_votl_format") || &cp
|
||||
finish
|
||||
endif
|
||||
let g:loaded_votl_format= 1
|
||||
let s:keepcpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
" Mappings {{{1
|
||||
|
||||
""" Command mappings
|
||||
"
|
||||
" Insert bullets on selected text
|
||||
map <buffer><localleader><F1> :call InsertBullet()<cr>
|
||||
" Insert dashes on selected text
|
||||
map <buffer><localleader><F2> :call InsertDash()<cr>
|
||||
" Insert arrows on selected text
|
||||
map <buffer><localleader><F3> :call InsertArrow()<cr>
|
||||
" Insert colons before selected text
|
||||
map <buffer><localleader><F4> :call MakeText()<cr>
|
||||
" Align text in a paragraph and indent 1 level
|
||||
map <buffer><localleader><F5> V}k:le<cr>V}>
|
||||
" Insert checkboxes for text lines in a paragraph
|
||||
map <buffer><localleader><F6> V}k,,cb
|
||||
" Indent text in a paragraph 1 level to the right and keep indentation
|
||||
map <buffer><localleader><F7> :call VOindentright()<cr>
|
||||
" Indent text in a paragraph 1 level to the level and keep indentation
|
||||
map <buffer><localleader><F8> :call VOindentleft()<cr>
|
||||
|
||||
"}}}1
|
||||
" InsertBullet() {{{1
|
||||
" Insert bullets on selected text.
|
||||
|
||||
function! InsertBullet()
|
||||
if match(getline("."),"^[\t]*:") != -1
|
||||
let @x = ": * "
|
||||
normal! ^"xPex
|
||||
else
|
||||
let @x = "* "
|
||||
normal! ^"xP
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"}}}1
|
||||
" InsertDash() {{{1
|
||||
" Insert dashes on selected text.
|
||||
|
||||
function! InsertDash()
|
||||
if match(getline("."),"^[\t]*:") != -1
|
||||
let @x = ": - "
|
||||
normal! ^"xPex
|
||||
else
|
||||
let @x = "- "
|
||||
normal! ^"xP
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"}}}1
|
||||
" InsertArrow() {{{1
|
||||
" Insert arrows on selected text.
|
||||
|
||||
function! InsertArrow()
|
||||
if match(getline("."),"^[\t]*:") != -1
|
||||
let @x = ": --> "
|
||||
normal! ^"xPex
|
||||
else
|
||||
let @x = "--> "
|
||||
normal! ^"xP
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"}}}1
|
||||
" MakeText() {{{1
|
||||
" Make selected lines body text.
|
||||
|
||||
function! MakeText()
|
||||
let @x = ":"
|
||||
normal! ^"xP
|
||||
endfunction
|
||||
|
||||
"}}}1
|
||||
" VOindentright() {{{1
|
||||
" Indent branch 1 level to the right.
|
||||
|
||||
function! VOindentright()
|
||||
let thisLine = line(".")
|
||||
if (foldclosed(thisLine) == -1) && IsParent(thisLine)
|
||||
normal! zc
|
||||
let fold_cursor = getpos(".")
|
||||
normal! >>
|
||||
let get_cursor = getpos(".")
|
||||
call setpos('.',fold_cursor)
|
||||
normal! zo
|
||||
call setpos('.',get_cursor)
|
||||
set foldlevel=3
|
||||
else
|
||||
normal! >>
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
"}}}1
|
||||
" VOindentleft() {{{1
|
||||
" Indent branch 1 level to the left.
|
||||
|
||||
function! VOindentleft()
|
||||
let thisLine = line(".")
|
||||
if (foldclosed(thisLine) == -1) && IsParent(thisLine)
|
||||
normal! zc
|
||||
let fold_cursor = getpos(".")
|
||||
normal! <<
|
||||
let get_cursor = getpos(".")
|
||||
call setpos('.',fold_cursor)
|
||||
normal! zo
|
||||
call setpos('.',get_cursor)
|
||||
set foldlevel=3
|
||||
else
|
||||
normal! <<
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"}}}1
|
||||
" The End
|
||||
" vim600: set foldmethod=marker foldlevel=0:
|
||||
|
||||
|
||||
|
219
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_gtd.vim
Normal file
219
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_gtd.vim
Normal file
|
@ -0,0 +1,219 @@
|
|||
"######################################################################
|
||||
"# VimOutliner GTD
|
||||
"# Copyright (C) 2003 by Noel Henson noel@noels-lab.com
|
||||
"# The file is currently an experimental part of Vim Outliner.
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"######################################################################
|
||||
|
||||
" InsertElem() {{{1
|
||||
" Insert a elem without disturbing the current folding.
|
||||
function! InsertElem(elem)
|
||||
let @x = a:elem
|
||||
normal! ^"xP
|
||||
endfunction
|
||||
"}}}1
|
||||
|
||||
" DeleteCheckbox() {{{1
|
||||
" Delete a checkbox with all its marks (team/completion)
|
||||
" if one exists
|
||||
function! DeleteCheckbox()
|
||||
:-1/\[[X_?-]\%(,[<>=] [^]]*\)\?\] \%(\d*%\)\?/s///
|
||||
endfunction
|
||||
"}}}1
|
||||
|
||||
let g:reOutline = "^\t\+\[<>:;|\]"
|
||||
let g:reBox = "[\[X_?-\]"
|
||||
let g:reTeam = ",\[<>=\] \[^]\]*"
|
||||
let g:rePercent = "\\d*% "
|
||||
|
||||
" Safe Insert *Box() {{{1
|
||||
" Insert a element at the beginning of a header without disturbing the
|
||||
" current folding only if there is no element already.
|
||||
function! InsertSwitch(elem)
|
||||
if match(getline("."),g:reOutline) != -1
|
||||
return
|
||||
endif
|
||||
" if match(getline("."),"[".a:elem."\\%(".g:reTeam."\\)\\?"."] ") != -1
|
||||
" return
|
||||
" endif
|
||||
if match(getline("."),g:reBox."\\%(".g:reTeam."\\)\\?"."] ") != -1
|
||||
substitute/\[./\="[".a:elem/
|
||||
else
|
||||
call InsertElem("[".a:elem."] ")
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
|
||||
" Safe Add Team Indicator() {{{1
|
||||
" Insert a work with("="), for (">"), waiting for ("<")
|
||||
" in a checkbox (created if needed) at the beginning of a header
|
||||
" without disturbing the current folding.
|
||||
function! SafeAddTeam(elem)
|
||||
if match(getline("."),g:reOutline) != -1
|
||||
return
|
||||
endif
|
||||
if match(getline("."),g:reBox.g:reTeam."] ") != -1
|
||||
return
|
||||
endif
|
||||
if match(getline("."),g:reBox."] ") != -1
|
||||
substitute/\[[X_?-]/\=submatch(0).",".a:elem." "/
|
||||
else
|
||||
call InsertElem("[_".",".a:elem." "."] ")
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
|
||||
" Safe InsertCheckBoxPercent() {{{1
|
||||
" Insert a checkbox and % sign at the beginning of a header without disturbing
|
||||
" the current folding
|
||||
function! SafeAddPercent()
|
||||
" if Ind(line(".")+1) <= Ind(line("."))
|
||||
" return
|
||||
" endif
|
||||
if match(getline("."),g:reOutline) != -1
|
||||
return
|
||||
endif
|
||||
if match(getline("."),g:reBox."\\%(".g:reTeam."\\)\\?"."] ".g:rePercent) != -1
|
||||
return
|
||||
endif
|
||||
if match(getline("."),g:reBox."\\%(".g:reTeam."\\)\\?"."] ") != -1
|
||||
substitute/\[[^]]\+\] /&% /
|
||||
else
|
||||
call InsertElem("[_] % ")
|
||||
endif
|
||||
endfunction
|
||||
"}}}1
|
||||
|
||||
" Ind(line) {{{1
|
||||
" Return the index of the line.
|
||||
" Remove it when using the new version of VO
|
||||
function! Ind(line)
|
||||
return indent(a:line) / &tabstop
|
||||
endf
|
||||
"}}}1
|
||||
|
||||
" FindRootParent(line) {{{1
|
||||
" returns the line number of the root parent for any child
|
||||
function! FindRootParent(line)
|
||||
let l:i = a:line
|
||||
while l:i > 1 && Ind(l:i) > 0
|
||||
let l:i -= 1
|
||||
endwhile
|
||||
return l:i
|
||||
endf
|
||||
"}}}1
|
||||
|
||||
" NewHMD(line) {{{1
|
||||
" (How Many Done)
|
||||
" Calculates proportion of already done work in the subtree
|
||||
function! NewHMD(line)
|
||||
let l:done = 0 " checkboxes
|
||||
let l:count = 0 " number of elems : for %
|
||||
let l:i = 1 " line counting
|
||||
let l:proportion = 0 " % : for checkboxes (<100 or 100 ?) and %
|
||||
let l:lineindent = Ind(a:line)
|
||||
|
||||
" look recursively
|
||||
|
||||
while Ind(a:line+l:i) > l:lineindent
|
||||
if Ind(a:line+l:i) == l:lineindent + 1
|
||||
let l:childdoneness = NewHMD(a:line+l:i)
|
||||
if l:childdoneness >= 0
|
||||
let l:done += l:childdoneness
|
||||
let l:count += 1
|
||||
endif
|
||||
" echomsg "->".a:line."/".(a:line+l:i)."/ [".l:childdoneness."]-[".l:count."]"
|
||||
else
|
||||
" echomsg "(skip) ->".a:line."/".(a:line+l:i)
|
||||
endif
|
||||
let l:i += 1
|
||||
endwhile
|
||||
|
||||
" update %
|
||||
|
||||
if l:count > 0
|
||||
" echomsg "->".a:line." proportion ".l:proportion
|
||||
let l:proportion = ((l:done * 100)/l:count)/100
|
||||
endif
|
||||
call setline(a:line,substitute(getline(a:line)," [0-9]*%"," ".l:proportion."%",""))
|
||||
|
||||
"
|
||||
" update checkboxes
|
||||
"
|
||||
|
||||
" everything under is done, toggle
|
||||
if l:proportion == 100
|
||||
" echomsg "->".a:line." proportion 100."
|
||||
call setline(a:line,substitute(getline(a:line),"[.","[X",""))
|
||||
return 100
|
||||
endif
|
||||
|
||||
if l:proportion == 0 && l:count == 0
|
||||
" done or skipped
|
||||
if match(getline(a:line),"\[[X-][\],]") != -1
|
||||
" echomsg "->".a:line." proportion is X or -."
|
||||
return 100
|
||||
endif
|
||||
|
||||
" not done or questionnable
|
||||
if match(getline(a:line),"\[[_\?][\],]") != -1
|
||||
" echomsg "->".a:line." proportion is _ or ?."
|
||||
return 0
|
||||
endif
|
||||
|
||||
" unknown status for line
|
||||
" echomsg "->".a:line." proportion is unknown."
|
||||
return -1
|
||||
endif
|
||||
|
||||
" we have not done tasks, undo 'mark as done'
|
||||
if match(getline(a:line),"\[[X][\],]") != -1
|
||||
call setline(a:line,substitute(getline(a:line),"[.","[_",""))
|
||||
endif
|
||||
" echomsg "->".a:line." proportion is revert?. [".l:proportion."] / [".l:count."]"
|
||||
return l:proportion
|
||||
endf
|
||||
"}}}1
|
||||
|
||||
" mappings {{{1
|
||||
" gtd addings
|
||||
" work alone
|
||||
noremap <buffer> <localleader>cb :call InsertSwitch("_")<cr>
|
||||
noremap <buffer> <localleader>cq :call InsertSwitch("?")<cr>
|
||||
noremap <buffer> <localleader>cD :call InsertSwitch("-")<cr>
|
||||
noremap <buffer> <localleader>cx :call InsertSwitch("X")<cr>:call NewHMD(FindRootParent(line(".")))<cr>
|
||||
" noremap <buffer> <localleader>cx :call InsertSwitch("X")<cr>
|
||||
" team work
|
||||
noremap <buffer> <localleader>cw :call SafeAddTeam("<")<cr>
|
||||
noremap <buffer> <localleader>cf :call SafeAddTeam(">")<cr>
|
||||
noremap <buffer> <localleader>c= :call SafeAddTeam("=")<cr>
|
||||
" completion
|
||||
noremap <buffer> <localleader>c% :call SafeAddPercent()<cr>
|
||||
|
||||
" forced mapping
|
||||
noremap <buffer> <localleader>gb :call InsertElem("[_] ")<cr>
|
||||
noremap <buffer> <localleader>gq :call InsertElem("[?] ")<cr>
|
||||
noremap <buffer> <localleader>gD :call InsertElem("[-] ")<cr>
|
||||
noremap <buffer> <localleader>gx :call InsertElem("[X] ")<cr>
|
||||
noremap <buffer> <localleader>gw :call InsertElem("[_,< ] ")<cr>
|
||||
noremap <buffer> <localleader>gf :call InsertElem("[_,> ] ")<cr>
|
||||
noremap <buffer> <localleader>g= :call InsertElem("[_,= ] ")<cr>
|
||||
noremap <buffer> <localleader>g% :call InsertElem("[_] % ")<cr>
|
||||
|
||||
" delete a chechbox
|
||||
noremap <buffer> <localleader>cd :call DeleteCheckbox()<cr>
|
||||
|
||||
" calculate the proportion of work done on the subtree
|
||||
noremap <buffer> <localleader>cz :call NewHMD(FindRootParent(line(".")))<cr>
|
||||
"}}}1
|
||||
|
||||
" vim600: set foldlevel=0 foldmethod=marker:
|
56
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_math.otl
Normal file
56
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_math.otl
Normal file
|
@ -0,0 +1,56 @@
|
|||
VO Math
|
||||
Syntax
|
||||
{} contains formalae to compute
|
||||
{f0;f1} semicolon separates formulae
|
||||
There is a respective order between the formulae and variables in a heading
|
||||
{math0;math1;math2} var0=result0 var1=result1 var2=result2
|
||||
ordering
|
||||
Math can come before or after variables
|
||||
{3+5;3*5} sum=8 product=15
|
||||
sum=8 product=15 {3+5;3*5}
|
||||
name=n name become a named result for passing to a parent
|
||||
A=n B=n space separates variables
|
||||
A=n test B=n space separates variables, interspersed words are allowed
|
||||
Math Examples
|
||||
Example 1: one-line math {3*5} result=15
|
||||
Example 2: one-line floating-point math {3*5.0} result=15.0
|
||||
Example 3: Simple math with child variables {A*B+C} result=5.0
|
||||
Item 1 A=2
|
||||
Item 2 B=2
|
||||
Item 3 C=3.0
|
||||
Example 4: Automatic summing {bonk} total=6.0
|
||||
Item 1 bonk=1
|
||||
Item 2 bonk=2
|
||||
Item 3 bonk=3.0
|
||||
Example 5: Multiple equations {A*B;B*C;C*A;A+B+C} AB=2.0 BC=6.0 CA=3.0 sumABC=6.0
|
||||
Item 1 A=1
|
||||
Item 2 B=2
|
||||
Item 3 C=3.0
|
||||
Example 6: Multiple trees {Labor;Materials;Total} Labor=1222.5 Materials=225.0 Total=1447.5
|
||||
Project 1 {Labor;Materials;Labor+Materials} Labor=747.5 Materials=110.0 Total=857.5
|
||||
Task 1 {Hours*Rate;Materials} Labor=500.0 Materials=100.0
|
||||
Hours=10
|
||||
Rate=50
|
||||
Materials=100
|
||||
Task 2 {Hours*Rate;Materials} Labor=247.5 Materials=10.0
|
||||
Hours=4.5
|
||||
Rate=55
|
||||
Materials=10
|
||||
Project 2 {Labor;Materials;Labor+Materials} Labor=475.0 Materials=115.0 Total=590.0
|
||||
Task 1 {Hours*Rate;Materials} Labor=300.0 Materials=70.0
|
||||
Hours=6
|
||||
Rate=50
|
||||
Materials=70
|
||||
Task 2 {Hours*Rate;Materials} Labor=175.0 Materials=45.0
|
||||
Hours=3.5
|
||||
Rate=50
|
||||
Materials=45
|
||||
Example 7: Reversal of results and maths AB=2.0 BC=6.0 CA=3.0 sumABC=6.0 {A*B;B*C;C*A;A+B+C}
|
||||
Item 1 A=1
|
||||
Item 2 B=2
|
||||
Item 3 C=3.0
|
||||
Example 8: Scientific notation: {10000.0*100000} result=1.0e9
|
||||
Example 9: Trigonometry: {sin(pi/4)} theta=0.707107
|
||||
pi=3.1415926
|
||||
Example 10: Base conversion: {printf("0x%x",65)} hex='0x41'
|
||||
Example 11: Vim internal state: {&ts;&foldlevel} tabstop=4 foldlevel=99999
|
286
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_math.vim
Normal file
286
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_math.vim
Normal file
|
@ -0,0 +1,286 @@
|
|||
"######################################################################
|
||||
"# VimOutliner Outline Math
|
||||
"# Copyright (C) 2014 by Noel Henson noelwhenson@gmail.com
|
||||
"# The file is currently an experimental part of Vim Outliner.
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"######################################################################
|
||||
|
||||
" Naming Conventions ################################################## {{{1
|
||||
" lnum: line number
|
||||
" line: string from a line
|
||||
" vars: dictionary of variables, key:value pairs
|
||||
"
|
||||
" Common Functions #################################################### {{{1
|
||||
" These functions have broader application scope than those specific to
|
||||
" performing math on outline trees. Perhaps even adding math to VO tables.
|
||||
"
|
||||
|
||||
" MyLineage(lnum) {{{2
|
||||
" return a list of ancestors in order of youngest-first
|
||||
" eg:
|
||||
" 9 A
|
||||
" 10 B
|
||||
" 11 C
|
||||
" 12 D
|
||||
" MyLineage(12)
|
||||
" [11,10,9]
|
||||
function! MyLineage(lnum)
|
||||
let lineage = []
|
||||
let lnum = a:lnum
|
||||
let indent = Ind(lnum)
|
||||
if indent == 0
|
||||
return lineage
|
||||
endif
|
||||
let parentIndent = indent - 1
|
||||
while (parentIndent >= 0) && (lnum >= 0)
|
||||
while (indent > parentIndent) && (lnum >= 0)
|
||||
let lnum -= 1
|
||||
let indent = Ind(lnum)
|
||||
endwhile
|
||||
let lineage += [lnum]
|
||||
let parentIndent -= 1
|
||||
endwhile
|
||||
return lineage
|
||||
endfunction
|
||||
|
||||
" MyChildren(lnum) {{{2
|
||||
" return a list of immediate children from the specificed line
|
||||
function! MyChildren(lnum)
|
||||
let children = []
|
||||
let parentInd = Ind(a:lnum)
|
||||
let childInd = parentInd + 1
|
||||
let last = line("$")
|
||||
let lnum = a:lnum + 1
|
||||
let lnumInd = Ind(lnum)
|
||||
while (lnum <= last) && (parentInd < lnumInd)
|
||||
if lnumInd == childInd
|
||||
let children += [lnum]
|
||||
endif
|
||||
let lnum += 1
|
||||
let lnumInd = Ind(lnum)
|
||||
endwhile
|
||||
return children
|
||||
endfunction
|
||||
|
||||
" RootParents() {{{2
|
||||
" return a list of all root nodes (indent level 0)
|
||||
function! RootParents()
|
||||
let parents = []
|
||||
let lnum = 1
|
||||
let lines = line("$")
|
||||
while lnum <= lines
|
||||
let ind = Ind(lnum)
|
||||
if ind == 0
|
||||
let parents += [lnum]
|
||||
endif
|
||||
let lnum += 1
|
||||
endwhile
|
||||
return parents
|
||||
endfunction
|
||||
|
||||
" FindMath(string) {{{2
|
||||
" location of first character of match, -1 if not
|
||||
" notation: ...{...}...=number...
|
||||
" function! FindMath(string)
|
||||
" return match(a:string,'{.*}.*=-\?[0-9]\+\(.[0-9]\+\)\+\([eE][-+]\?[0-9]\+\)\?')
|
||||
" endfunction
|
||||
" the below is faster!
|
||||
" function! FindMath(string)
|
||||
" return match(a:string,'{.*}.*=-\?[0-9]')
|
||||
" endfunction
|
||||
" the below is even faster
|
||||
" and allows for formulae to be placed at the end of a heading
|
||||
function! FindMath(string)
|
||||
if match(a:string,'=') != -1
|
||||
return match(a:string,'{.*}')
|
||||
else
|
||||
return -1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" GetMathFromString(string) {{{2
|
||||
" returns a list of formulae in a string, in the order they were listed
|
||||
" returns an empty list if none
|
||||
" notation: {formula} or {formula1;formula2;...;formulan}
|
||||
function! GetMathFromString(string)
|
||||
let mstart = FindMath(a:string)
|
||||
if mstart == -1
|
||||
return []
|
||||
endif
|
||||
let mstart += 1
|
||||
let mend = match(a:string,'}',mstart)
|
||||
if mend == -1
|
||||
return []
|
||||
endif
|
||||
let mend -= 1
|
||||
return split(a:string[mstart : mend],';')
|
||||
endfunction
|
||||
|
||||
" MarkValues(string) {{{2
|
||||
" mark Values in a string for replacement by formula results
|
||||
" turns each number into '= voMathResult'
|
||||
function! MarkValues(string)
|
||||
return substitute(a:string,'=-\?[0-9]\+\(.[0-9]\+\)\?\([eE][-+]\?[0-9]\+\)\?','=voMathResult','g')
|
||||
endfunction
|
||||
|
||||
" GetVarsFromString(string,vars) {{{2
|
||||
" add key:value pairs from a string to the passed dictionary
|
||||
" create new entries if key does not exist
|
||||
" add values to existing entries
|
||||
" vars is a dictionary of key:value pairs
|
||||
" notation: name=number
|
||||
function! GetVarsFromString(string,vars)
|
||||
" quick return if no potential variables
|
||||
if match(a:string,'=') == -1
|
||||
return
|
||||
endif
|
||||
let tokens = split(a:string)
|
||||
for token in tokens
|
||||
if match(token,'=') == -1
|
||||
continue
|
||||
endif
|
||||
let [key,value] = split(token,"=")
|
||||
" read values are cast to floats to prevent
|
||||
" auto-casting to integers in the first case
|
||||
" and strings in the second
|
||||
if has_key(a:vars,key)
|
||||
let a:vars[key] += str2float(value)
|
||||
else
|
||||
let a:vars[key] = str2float(value)
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" ReplaceVars(formula,vars) {{{2
|
||||
" replace variables with their values from the supplied dictionary
|
||||
" vars is a dictionary of key:value pairs
|
||||
" key:value pairs are first sorted by key length, longest-first
|
||||
" this prevents name collisions when similar key names are used like:
|
||||
" Total and Totals -or- X1 and X12
|
||||
function! ReplaceVars(formula,vars)
|
||||
let formula = a:formula
|
||||
let vars = []
|
||||
for [key,val] in items(a:vars)
|
||||
let vars += [[len(key),key,val]]
|
||||
endfor
|
||||
let vars = reverse(sort(vars))
|
||||
for [len,key,val] in vars
|
||||
let formula = substitute(formula,key,string(val),"g")
|
||||
endfor
|
||||
return formula
|
||||
endfunction
|
||||
|
||||
" ComputeString(string,vars) {{{2
|
||||
" compute a string using its math and a dictionary of variables
|
||||
" return the computed, modified string
|
||||
" string is a string containing math and result variable names
|
||||
" vars is a dictionary of key:value pairs used in the computation
|
||||
function! ComputeString(string,vars)
|
||||
let string = a:string
|
||||
let maths = GetMathFromString(string)
|
||||
if len(maths)
|
||||
let string = MarkValues(string)
|
||||
for math in maths
|
||||
let math = ReplaceVars(math,a:vars)
|
||||
let result = string(eval(math))
|
||||
let string = substitute(string,'voMathResult',result,"")
|
||||
endfor
|
||||
endif
|
||||
return string
|
||||
endfunction
|
||||
|
||||
" Math Functions on Outlines ########################################## {{{1
|
||||
|
||||
" MyChildrensVars(lnum) {{{2
|
||||
" return a dictionary of variable from immediate children
|
||||
function! MyChildrensVars(lnum)
|
||||
let children = MyChildren(a:lnum)
|
||||
let vars = {}
|
||||
for child in children
|
||||
call GetVarsFromString(getline(child),vars)
|
||||
endfor
|
||||
return vars
|
||||
endfunction
|
||||
|
||||
" ComputeLine(lnum) {{{2
|
||||
" compute a line's maths using variables from it's children
|
||||
" replace the line with the newly computed line
|
||||
function! ComputeLine(lnum)
|
||||
let vars = MyChildrensVars(a:lnum)
|
||||
let line = ComputeString(getline(a:lnum),vars)
|
||||
call setline(a:lnum,line)
|
||||
endfunction
|
||||
|
||||
" ComputeUp(lnum) {{{2
|
||||
" compute 'up' a tree towards level 1
|
||||
" the line (lnum) itself is computed first
|
||||
" this is intended to be a fast compute method to update a branch of nodes
|
||||
" it assumes that all other calculations in a tree are correct
|
||||
function! ComputeUp(lnum)
|
||||
call ComputeLine(a:lnum)
|
||||
let lineage = MyLineage(a:lnum)
|
||||
if len(lineage)
|
||||
for lnum in lineage
|
||||
call ComputeLine(lnum)
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" ComputeDown(lnum) {{{2
|
||||
" compute 'down' a tree from the current node
|
||||
" the line (lnum) itself is computed last
|
||||
function! ComputeDown(lnum)
|
||||
let children = MyChildren(a:lnum)
|
||||
if len(children)
|
||||
for lnum in children
|
||||
call ComputeDown(lnum)
|
||||
endfor
|
||||
endif
|
||||
call ComputeLine(a:lnum)
|
||||
endfunction
|
||||
|
||||
" ComputeTree(lnum) {{{2
|
||||
" compute down an entire tree
|
||||
function! ComputeTree(lnum)
|
||||
let parents = MyLineage(a:lnum)
|
||||
if len(parents)
|
||||
let topparent = parents[-1]
|
||||
else
|
||||
let topparent = a:lnum
|
||||
endif
|
||||
call ComputeDown(topparent)
|
||||
endfunction
|
||||
|
||||
" ComputeDocument() {{{2
|
||||
" compute down all trees
|
||||
|
||||
function! ComputeDocument(lnum)
|
||||
let parents = RootParents()
|
||||
for parent in parents
|
||||
call ComputeDown(parent)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Concealings {{{1
|
||||
" BadWord is a very old VO region that is no longer used.
|
||||
" It can be used now for plugins :)
|
||||
" This should probably be fixed at some point in the future
|
||||
syntax match BadWord "{.\+}" conceal transparent cchar=µ
|
||||
set conceallevel=1
|
||||
|
||||
" mappings {{{1
|
||||
|
||||
map <silent><buffer> <localleader>== :call ComputeUp(line("."))<cr>
|
||||
map <silent><buffer> <localleader>=t :call ComputeTree(line("."))<cr>
|
||||
map <silent><buffer> <localleader>=d :call ComputeDocument()<cr>
|
||||
map <silent><buffer> <localleader>=h :set conceallevel=1<cr>
|
||||
map <silent><buffer> <localleader>=H :set conceallevel=0<cr>
|
456
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_newhoist.vim
Normal file
456
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_newhoist.vim
Normal file
|
@ -0,0 +1,456 @@
|
|||
"######################################################################
|
||||
"# VimOutliner Hoisting
|
||||
"# Copyright (C) 2003 by Noel Henson noel@noels-lab.com
|
||||
"# The file is currently an experimental part of Vim Outliner.
|
||||
"#
|
||||
"# This program is free software; you can redistribute it and/or modify
|
||||
"# it under the terms of the GNU General Public License as published by
|
||||
"# the Free Software Foundation; either version 2 of the License, or
|
||||
"# (at your option) any later version.
|
||||
"#
|
||||
"# This program is distributed in the hope that it will be useful,
|
||||
"# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
"# GNU General Public License for more details.
|
||||
"######################################################################
|
||||
|
||||
" Load the plugin {{{1
|
||||
if exists("g:did_vo_hoist")
|
||||
"finish
|
||||
endif
|
||||
if !exists("g:hoistParanoia")
|
||||
let g:hoistParanoia=0
|
||||
endif
|
||||
if !exists('hlevel')
|
||||
let hlevel = 20
|
||||
endif
|
||||
let g:did_vo_hoist = 1
|
||||
" mappings {{{1
|
||||
map <silent> <buffer> <localleader>hh :call Hoist(line("."))<cr>
|
||||
map <silent> <buffer> <localleader>hd :call DeHoist()<cr>
|
||||
map <silent> <buffer> <localleader>hD :call DeHoistAll()<cr>
|
||||
"}}}1
|
||||
" syntax {{{1
|
||||
" Hoisted {{{2
|
||||
"syntax match Invis +^\~\zs.*$+ containedin=ALL conceal cchar=~
|
||||
""hi Invis guifg=bg ctermfg=bg
|
||||
""hi Invis guifg=bg
|
||||
"hi link Invis Conceal
|
||||
"}}}2
|
||||
"}}}1
|
||||
" MyFoldText() {{{1
|
||||
" Create string used for folded text blocks
|
||||
function! MyFoldText()
|
||||
let l:MySpaces = MakeSpaces(&sw)
|
||||
let l:line = getline(v:foldstart)
|
||||
let l:bodyTextFlag=0
|
||||
if l:line =~'^\~'
|
||||
let l:line = '~'.repeat(' ', winwidth(0)-1)
|
||||
elseif l:line =~ "^\t* \\S" || l:line =~ "^\t*\:"
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[TEXT]"
|
||||
elseif l:line =~ "^\t*\;"
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[TEXT BLOCK]"
|
||||
elseif l:line =~ "^\t*\> "
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER]"
|
||||
elseif l:line =~ "^\t*\>"
|
||||
let l:ls = stridx(l:line,">")
|
||||
let l:le = stridx(l:line," ")
|
||||
if l:le == -1
|
||||
let l:l = strpart(l:line, l:ls+1)
|
||||
else
|
||||
let l:l = strpart(l:line, l:ls+1, l:le-l:ls-1)
|
||||
endif
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER ".l:l."]"
|
||||
elseif l:line =~ "^\t*\< "
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER BLOCK]"
|
||||
elseif l:line =~ "^\t*\<"
|
||||
let l:ls = stridx(l:line,"<")
|
||||
let l:le = stridx(l:line," ")
|
||||
if l:le == -1
|
||||
let l:l = strpart(l:line, l:ls+1)
|
||||
else
|
||||
let l:l = strpart(l:line, l:ls+1, l:le-l:ls-1)
|
||||
endif
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[USER BLOCK ".l:l."]"
|
||||
elseif l:line =~ "^\t*\|"
|
||||
let l:bodyTextFlag=1
|
||||
let l:MySpaces = MakeSpaces(&sw * (v:foldlevel-1))
|
||||
let l:line = l:MySpaces."[TABLE]"
|
||||
endif
|
||||
let l:sub = substitute(l:line,'\t',l:MySpaces,'g')
|
||||
let l:len = strlen(l:sub)
|
||||
let l:sub = l:sub . " " . MakeDashes(58 - l:len)
|
||||
let frange = (v:foldend + l:bodyTextFlag)- v:foldstart
|
||||
let l:sub = l:sub . " (" . frange
|
||||
if frange == 1
|
||||
let l:sub = l:sub . " line)"
|
||||
else
|
||||
let l:sub = l:sub . " lines)"
|
||||
endif
|
||||
return l:sub.repeat(' ', winwidth(0)-len(l:sub))
|
||||
endfunction
|
||||
"}}}1
|
||||
" New Fold Function (will be put into vo_base later {{{1
|
||||
function! MyHoistableFoldLevel(line)
|
||||
let l:myindent = Ind(a:line)
|
||||
let l:nextindent = Ind(a:line+1)
|
||||
|
||||
if HoistFold(a:line)
|
||||
" if (a:line == 1)
|
||||
" return g:hlevel
|
||||
" elseif (HoistFold(a:line-1) == 0)
|
||||
" return ">".0
|
||||
" else
|
||||
" return g:hlevel
|
||||
" endif
|
||||
return g:hlevel
|
||||
|
||||
elseif BodyText(a:line)
|
||||
if (BodyText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (BodyText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedBodyText(a:line)
|
||||
if (PreformattedBodyText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedBodyText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedTable(a:line)
|
||||
if (PreformattedTable(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedTable(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedUserText(a:line)
|
||||
if (PreformattedUserText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedUserTextSpace(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif PreformattedUserTextLabeled(a:line)
|
||||
if (PreformattedUserTextLabeled(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (PreformattedUserText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif UserText(a:line)
|
||||
if (UserText(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (UserTextSpace(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
elseif UserTextLabeled(a:line)
|
||||
if (UserTextLabeled(a:line-1) == 0)
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if (UserText(a:line+1) == 0)
|
||||
return '<'.(l:myindent+1)
|
||||
endif
|
||||
return (l:myindent+1)
|
||||
else
|
||||
if l:myindent < l:nextindent
|
||||
return '>'.(l:myindent+1)
|
||||
endif
|
||||
if l:myindent > l:nextindent
|
||||
return (l:myindent)
|
||||
endif
|
||||
return l:myindent
|
||||
endif
|
||||
endfunction
|
||||
set foldexpr=MyHoistableFoldLevel(v:lnum)
|
||||
"}}}2
|
||||
"}}}1
|
||||
" Functions {{{1
|
||||
" RemoveTabs(line,tabs) {{{2
|
||||
" remove specified number of tabs from the begining of line
|
||||
function! RemoveTabs(start,end,tabs)
|
||||
if a:tabs > 0
|
||||
let l:doit = "silent ".a:start.",".a:end."s/^\\(\\t\\)\\{".a:tabs."}/"
|
||||
exe l:doit
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" IsParent(line) {{{2
|
||||
" Return 1 if this line is a parent
|
||||
function! IsParent(line)
|
||||
return (Ind(a:line)+1) == Ind(a:line+1)
|
||||
endfunction
|
||||
"}}}2
|
||||
" FindParent(line) {{{2
|
||||
" Return line if parent, parent line if not
|
||||
function! FindParent(line)
|
||||
if IsParent(a:line)
|
||||
return a:line
|
||||
else
|
||||
let l:parentindent = Ind(a:line)-1
|
||||
let l:searchline = a:line
|
||||
while (Ind(l:searchline) != l:parentindent) && (l:searchline > 0)
|
||||
let l:searchline = l:searchline-1
|
||||
endwhile
|
||||
return l:searchline
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" HoistFold() {{{2
|
||||
" Return a flag indicating that there is a valid hoist
|
||||
function! HoistFold(line)
|
||||
if getline(a:line) =~ '^\~'
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" Hoisted() {{{2
|
||||
" Return a flag indicating that there is a valid hoist
|
||||
function! Hoisted()
|
||||
if getline(1) =~ '^\~'
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
"}}}2
|
||||
" FindTopHoist(line) {{{2
|
||||
" Return line number of the nearest (last line) top hoist tag
|
||||
function! FindTopHoist(line)
|
||||
let l:line = a:line
|
||||
while (match(getline(l:line),"^\\~") == -1) && (l:line > 0)
|
||||
let l:line -= 1
|
||||
endwhile
|
||||
return l:line
|
||||
endfunction
|
||||
"}}}2
|
||||
" FindBottomHoist(line) {{{2
|
||||
" Return line number of the nearest (last line) top hoist tag
|
||||
function! FindBottomHoist(line)
|
||||
let l:line = a:line
|
||||
let l:lastline = line('$')
|
||||
while getline(l:line) !~ "^\\~" && (l:line > 0) && l:line <= l:lastline
|
||||
let l:line += 1
|
||||
endwhile
|
||||
return l:line
|
||||
endfunction
|
||||
"}}}2
|
||||
" FindLastChild(line) {{{2
|
||||
" Return the line number of the last decendent of parent line
|
||||
function! FindLastChild(line)
|
||||
let l:parentindent = Ind(a:line)
|
||||
let l:searchline = a:line+1
|
||||
while Ind(l:searchline) > l:parentindent
|
||||
let l:searchline = l:searchline+1
|
||||
endwhile
|
||||
return l:searchline-1
|
||||
endfunction
|
||||
"}}}2
|
||||
" GetHoistedIndent(line) {{{2
|
||||
" line is the line number containing the indent
|
||||
" Returns the original indent of the hoisted region
|
||||
function! GetHoistedIndent(line)
|
||||
return str2nr(strpart(getline(a:line),1,2))
|
||||
endfunction
|
||||
"}}}2
|
||||
" HoistTagBefore(line,indent) {{{2
|
||||
function! HoistTagBefore(line,indent)
|
||||
let l:doit = "silent 1,".(a:line-1)."s/^/\\~".a:indent." /"
|
||||
exe l:doit
|
||||
"call setline(1, map(getline(1,a:line-1), '"~".a:indent.v:val'))
|
||||
endfunction
|
||||
"}}}2
|
||||
" HoistDeTagBefore(line) {{{2
|
||||
function! HoistDeTagBefore(line)
|
||||
let l:doit = "silent 1,".a:line."s/^\\~\\d* //"
|
||||
exe l:doit
|
||||
endfunction
|
||||
"}}}2
|
||||
" HoistTagAfter(line) {{{2
|
||||
function! HoistTagAfter(line)
|
||||
if a:line > line('$')
|
||||
return
|
||||
endif
|
||||
let l:doit = "silent ".a:line.",$s/^/\\~/"
|
||||
exe l:doit
|
||||
endfunction
|
||||
"}}}2
|
||||
" HoistDeTagAfter(line) {{{2
|
||||
function! HoistDeTagAfter(line)
|
||||
if a:line > line('$')
|
||||
return
|
||||
endif
|
||||
let l:doit = "silent ".a:line.",$s/^\\~//"
|
||||
exe l:doit
|
||||
endfunction
|
||||
"}}}2
|
||||
" HoistWrite(file) {{{2
|
||||
" Write the clean file if hoisted
|
||||
function! HoistWrite(file,...) range
|
||||
"let lines = getline(1,line('$'))
|
||||
let saved = 0
|
||||
mkview
|
||||
call DeHoistAll()
|
||||
if v:cmdbang
|
||||
let bang = '!'
|
||||
else
|
||||
let bang = ''
|
||||
endif
|
||||
try
|
||||
if a:0
|
||||
echom a:firstline.','.a:lastline."w".bang.fnameescape(v:cmdarg).' '.a:file
|
||||
exe a:firstline.','.a:lastline."w".bang.fnameescape(v:cmdarg).' '.a:file
|
||||
else
|
||||
exe "w".bang.fnameescape(v:cmdarg).' '.a:file
|
||||
endif
|
||||
let saved = 1
|
||||
catch
|
||||
echohl ErrorMsg
|
||||
echom substitute(v:exception,'^Vim(.\{-}):','','')
|
||||
echohl None
|
||||
endtry
|
||||
"call setline(1,lines)
|
||||
silent earlier
|
||||
silent loadview
|
||||
if saved
|
||||
silent setlocal nomodified
|
||||
endif
|
||||
endfunction "HoistWrite
|
||||
" Hoist(line) {{{2
|
||||
" Write the offspring of a parent to a new file, open it and remove the
|
||||
" leading tabs.
|
||||
function! Hoist(line)
|
||||
let l:parent = FindParent(a:line)
|
||||
if l:parent == 0
|
||||
return
|
||||
endif
|
||||
"call cursor(l:parent,1)
|
||||
"let l:firstline = l:parent+1
|
||||
let l:firstline = l:parent
|
||||
let l:childindent = Ind(l:firstline)
|
||||
let l:lastline = FindLastChild(l:parent)
|
||||
setlocal foldlevel=20
|
||||
call HoistTagBefore(l:firstline,l:childindent)
|
||||
call HoistTagAfter(l:lastline+1)
|
||||
" call RemoveTabs(l:firstline,l:lastline,l:childindent)
|
||||
call cursor(l:firstline,1)
|
||||
setlocal foldlevel=19
|
||||
augroup VO_HOIST
|
||||
au!
|
||||
au CursorMoved,CursorMovedI <buffer>
|
||||
\ if getline('.') =~ '^\~\d* ' |
|
||||
\ call HoistKeepCursor(1) |
|
||||
\ elseif getline('.') =~ '^\~' |
|
||||
\ call HoistKeepCursor(0) |
|
||||
\ endif
|
||||
"au BufWriteCmd <buffer> call HoistWrite(fnameescape(expand("<amatch>")))
|
||||
"au FileWriteCmd <buffer> '[,']call HoistWrite(fnameescape(expand("<amatch>")), 1)
|
||||
augroup END
|
||||
if exists('+conceallevel')
|
||||
syntax match Invis +^\~.*$+ conceal cchar=~
|
||||
hi link Invis Conceal
|
||||
setlocal conceallevel=2
|
||||
else
|
||||
syntax match Invis +^\~.*$+ containedin=ALL
|
||||
let i = 1
|
||||
while synIDtrans(i) != 0
|
||||
if synIDattr(i, 'name') == 'Normal'
|
||||
if synIDattr(i, 'bg') >= 0
|
||||
" bg is set
|
||||
hi Invis guifg=bg ctermfg=bg
|
||||
else
|
||||
hi Invis guifg=NONE ctermfg=NONE
|
||||
endif
|
||||
break
|
||||
endif
|
||||
let i += 1
|
||||
endwhile
|
||||
endif
|
||||
endfunction
|
||||
" }}}2
|
||||
" HoistKeepCursor(top) {{{2
|
||||
" Keep cursor out of non-hoisted area.
|
||||
function! HoistKeepCursor( top )
|
||||
if a:top
|
||||
while getline('.') =~ '^\~\d* '
|
||||
normal! j
|
||||
endwhile
|
||||
else
|
||||
while getline('.') =~ '^\~'
|
||||
normal! k
|
||||
endwhile
|
||||
endif
|
||||
endfunction "HoistKeepCursor }}}2
|
||||
" MakeTabs(n) {{{2
|
||||
" return a string of n tabs
|
||||
function! MakeTabs(n)
|
||||
let l:tabs = ""
|
||||
let l:n = a:n
|
||||
while l:n > 0
|
||||
let l:tabs = l:tabs."\t"
|
||||
let l:n -= 1
|
||||
endwhile
|
||||
return l:tabs
|
||||
endfunction
|
||||
"}}}2
|
||||
"}}}2
|
||||
" DeHoist() {{{2
|
||||
" Write the offspring of a parent to a new file, open it and remove the
|
||||
" leading tabs.
|
||||
function! DeHoist()
|
||||
if !Hoisted()
|
||||
return
|
||||
endif
|
||||
let l:line = line(".")
|
||||
let l:top = FindTopHoist(l:line)
|
||||
let l:bottom = FindBottomHoist(l:line)
|
||||
echom 1
|
||||
let l:indent = GetHoistedIndent(l:top)
|
||||
" let l:tabs = MakeTabs(l:indent)
|
||||
" let l:doit = "silent ".(l:top+1).",".(l:bottom-1)."s/^/".l:tabs."/"
|
||||
" exe l:doit
|
||||
call HoistDeTagBefore(l:top)
|
||||
call HoistDeTagAfter(l:bottom)
|
||||
if !Hoisted()
|
||||
augroup VO_HOIST
|
||||
au!
|
||||
augroup! VO_HOIST
|
||||
augroup END
|
||||
endif
|
||||
call cursor(l:line,l:indent)
|
||||
endfunction
|
||||
"}}}2
|
||||
" DeHoistAll() {{{2
|
||||
" Write the offspring of a parent to a new file, open it and remove the
|
||||
" leading tabs.
|
||||
function! DeHoistAll()
|
||||
while Hoisted()
|
||||
call DeHoist()
|
||||
endwhile
|
||||
endfunction
|
||||
"}}}2
|
||||
"}}}1
|
||||
" vim600: set foldlevel=0 foldmethod=marker:
|
|
@ -0,0 +1,117 @@
|
|||
" Here is a small script that remaps the p and P normal commands such that VO
|
||||
" will do what one would expect when pasting cut/copied nodes into another
|
||||
" section of an outline. It will adjust the indents and not paste into the
|
||||
" middle of a branch.
|
||||
" Added 2011-03-01(JB): This script will now also copy an outline correctly by
|
||||
" using \\y, copy to the register with \\r, cut an outline by using \\d, and
|
||||
" paste from the register using \\b.
|
||||
" http://www.lists.vimoutliner.org/pipermail/vimoutliner/2008-October/002366.html
|
||||
|
||||
map <buffer>p :call VOput()<cr>
|
||||
map <buffer>\\b :call VOputreg()<cr>
|
||||
map <buffer>\\y :call VOcop()<cr>
|
||||
map <buffer>\\r :call VOreg()<cr>
|
||||
map <buffer>\\d :call VOcut()<cr>
|
||||
map <buffer>P ]P
|
||||
|
||||
if exists('s:loaded')
|
||||
finish
|
||||
endif
|
||||
let s:loaded = 1
|
||||
|
||||
function! IsParent(line)
|
||||
if a:line == line("$")
|
||||
return 0
|
||||
elseif Ind(a:line) < Ind(a:line+1)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! VOcop()
|
||||
let thisLine = line(".")
|
||||
if (foldclosed(thisLine) == -1) && IsParent(thisLine)
|
||||
normal! zc
|
||||
let fold_cursor = getpos(".")
|
||||
normal! yy
|
||||
let get_cursor = getpos(".")
|
||||
call setpos('.',fold_cursor)
|
||||
normal! zo
|
||||
call setpos('.',get_cursor)
|
||||
else
|
||||
normal! yy
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! VOreg()
|
||||
let thisLine = line(".")
|
||||
if (foldclosed(thisLine) == -1) && IsParent(thisLine)
|
||||
normal! zc
|
||||
let fold_cursor = getpos(".")
|
||||
normal! V"+y
|
||||
let get_cursor = getpos(".")
|
||||
call setpos('.',fold_cursor)
|
||||
normal! zo
|
||||
call setpos('.',get_cursor)
|
||||
else
|
||||
normal! V"+y
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! VOcut()
|
||||
let thisLine = line(".")
|
||||
if (foldclosed(thisLine) == -1) && IsParent(thisLine)
|
||||
normal! zc
|
||||
let fold_cursor = getpos(".")
|
||||
normal! dd
|
||||
let get_cursor = getpos(".")
|
||||
call setpos('.',fold_cursor)
|
||||
normal! zo
|
||||
call setpos('.',get_cursor)
|
||||
else
|
||||
normal! dd
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! VOput()
|
||||
let thisLine = line(".")
|
||||
if (foldclosed(thisLine) == -1) && IsParent(thisLine)
|
||||
normal! zc
|
||||
let fold_cursor = getpos(".")
|
||||
normal! ]p
|
||||
let put_cursor = getpos(".")
|
||||
call setpos('.',fold_cursor)
|
||||
normal! zo
|
||||
call setpos('.',put_cursor)
|
||||
else
|
||||
normal! ]p
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! VOputreg()
|
||||
let thisLine = line(".")
|
||||
if (foldclosed(thisLine) == -1) && IsParent(thisLine)
|
||||
normal! zc
|
||||
let fold_cursor = getpos(".")
|
||||
normal! "+]p
|
||||
let put_cursor = getpos(".")
|
||||
call setpos('.',fold_cursor)
|
||||
normal! zo
|
||||
call setpos('.',put_cursor)
|
||||
else
|
||||
normal! "+]p
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
246
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_tags.vim
Normal file
246
pack/acp/start/vimoutliner/vimoutliner/plugin/votl_tags.vim
Normal file
|
@ -0,0 +1,246 @@
|
|||
" File: plugin/votl_tags.vim
|
||||
" Version: 1.0
|
||||
" Modified: 2011-02-28
|
||||
" Description: This plugin provides inter-outline links for vimoutliner.
|
||||
" Maintainer: Israel Chauca F. <israelchauca@gmail.com>
|
||||
" Manual: The following mappings are added:
|
||||
" - <C-K> : Follow a link.
|
||||
" - <C-N> : Jump back in the link-history.
|
||||
" - <localleader>l : Create a link.
|
||||
" ============================================================================
|
||||
|
||||
if v:version < 700
|
||||
echom 'VimOutliner: votl_tags.vim requires Vim 7.0 or later.'
|
||||
finish
|
||||
endif
|
||||
|
||||
" Create outlines' jump-list.
|
||||
if !exists('w:vo_jump_list')
|
||||
let w:vo_jump_list = []
|
||||
endif
|
||||
|
||||
" Mappings {{{1
|
||||
|
||||
" Follow inter-outline link.
|
||||
noremap <buffer> <Plug>VO_FollowLink :call <SID>follow_link()<CR>
|
||||
if !hasmapto('<Plug>VO_FollowLink')
|
||||
"map <unique> <buffer> <C-K> <Plug>VO_FollowLink
|
||||
map <silent> <buffer> <C-K> <Plug>VO_FollowLink
|
||||
endif
|
||||
|
||||
" Go back to previous outline.
|
||||
noremap <buffer> <Plug>VO_JumpBack :call <SID>jump_back()<CR>
|
||||
if !hasmapto('<Plug>VO_JumpBack')
|
||||
"map <unique> <buffer> <C-N> <Plug>VO_JumpBack
|
||||
map <silent> <buffer> <C-N> <Plug>VO_JumpBack
|
||||
endif
|
||||
|
||||
" Create a link from a word in normal mode.
|
||||
noremap <buffer> <Plug>VO_CreateLink :call <SID>create_link()<CR>
|
||||
if !hasmapto('<Plug>VO_CreateLink')
|
||||
silent! map <silent> <unique> <buffer> <localleader>l <Plug>VO_CreateLink
|
||||
endif
|
||||
|
||||
" Create a link from a word in insert mode.
|
||||
inoremap <buffer> <Plug>VO_CreateLinkI <C-O>:call <SID>create_link()<CR>
|
||||
if !hasmapto('<Plug>VO_CreateLinkI')
|
||||
silent! imap <silent> <unique> <buffer> <localleader>l <Plug>VO_CreateLinkI
|
||||
endif
|
||||
|
||||
" Functions {{{1
|
||||
|
||||
let s:checkboxpat = '\%(\[[^[\]]\+\]\s\+\%(\d*%\d*\s\+\)\?\)\?'
|
||||
|
||||
" Don't re-load functions.
|
||||
if exists('s:loaded')
|
||||
finish
|
||||
endif
|
||||
let s:loaded = 1
|
||||
|
||||
" s:get_link() {{{2
|
||||
" Get link data.
|
||||
function! s:get_link(linenr)
|
||||
" Check if it's a valid link.
|
||||
let line = getline(a:linenr)
|
||||
if line =~? '\m^\t*'.s:checkboxpat.'_tag_\w\+\s*$'
|
||||
" Don't remember where this bit came from, please let me know if you do.
|
||||
let [_,file,row,col;m0] = matchlist(getline(a:linenr + 1), '\m^\t*'.s:checkboxpat.'\([^:]\+\)\%(:\(\d\+\)\)\?\%(:\(\d\+\)\)\?$')
|
||||
elseif line =~? '\m^\t*'.s:checkboxpat.'_ilink_\(.\{-}:\s\)\?\s*\S.*$'
|
||||
let pat = '\m^\t*'.s:checkboxpat.'_ilink_\%([^:\\/]\{-}:\s\)\?\s*\(.\+\)\%(:\(\d\+\)\)\?\%(:\(\d\+\)\)\?$'
|
||||
let [_,file,row,col;m0] = matchlist(line, pat)
|
||||
else
|
||||
return ['',0,0,0]
|
||||
endif
|
||||
let is_inner_link = 0
|
||||
if file == '%'
|
||||
let file = expand('%:p')
|
||||
let is_inner_link = 1
|
||||
endif
|
||||
let row = (row == '' ? 0 : row * 1)
|
||||
let col = (col == '' ? 0 : col * 1)
|
||||
|
||||
return [file, row, col, is_inner_link]
|
||||
endfunction
|
||||
|
||||
" s:follow_link() {{{2
|
||||
" Follow an interoutline link.
|
||||
function! s:follow_link()
|
||||
" Get link data.
|
||||
let [file, row, col, is_inner_link] = s:get_link(line('.'))
|
||||
if file == ''
|
||||
echom 'Vimoutliner: "'.substitute(getline('.'), '\m^\t*'.s:checkboxpat, '', '').'" doesn''t not look like an inter-outline link.'
|
||||
return
|
||||
endif
|
||||
|
||||
" Check if file path exists.
|
||||
let file = s:get_absolute_path(expand('%:h'), file)
|
||||
let file = fnamemodify(file,':p')
|
||||
let baseDir = fnamemodify(file,':h')
|
||||
let dirconfirm = 0
|
||||
" Check if directories exists. {{{3
|
||||
if glob(baseDir) == ''
|
||||
if exists('*confirm')
|
||||
let dirconfirm = confirm('The linked file "'.file.'" and one or more directories do not exist, do you want to create them now?', "&Yes\n&No", '2', 'Question')
|
||||
else
|
||||
" Can't ask, asume a yes for answer.
|
||||
let dirconfirm = 1
|
||||
endif
|
||||
if dirconfirm == 1
|
||||
" Create dir(s):
|
||||
if exists('*mkdir')
|
||||
call mkdir(baseDir,'p')
|
||||
elseif executable('mkdir')
|
||||
call system('`which mkdir` -p '.shellescape(baseDir))
|
||||
else
|
||||
echom 'Vimoutliner: Vim can not create the required directories, please create them yourself.'
|
||||
return
|
||||
endif
|
||||
else
|
||||
return
|
||||
endif
|
||||
endif
|
||||
" Check if file exists. {{{3
|
||||
if glob(file) == ''
|
||||
if exists('*confirm') && dirconfirm == 0
|
||||
let confirm = confirm('The linked file "'.file.'" does not exist, do you want to create it now?', "&Yes\n&No", '2', 'Question')
|
||||
else
|
||||
" Can't ask, asume a yes for answer.
|
||||
let confirm = 1
|
||||
endif
|
||||
if confirm == 1
|
||||
call writefile([], file)
|
||||
else
|
||||
return
|
||||
endif
|
||||
endif
|
||||
" }}}3
|
||||
" Now let's jump to that outline.
|
||||
try
|
||||
call s:update_jump_list()
|
||||
if !is_inner_link
|
||||
exec "buffer ".bufnr(substitute(file, '\m^'.getcwd().'/','',''), 1)
|
||||
endif
|
||||
if row > 0
|
||||
call setpos('.',[0,row,col,0])
|
||||
endif
|
||||
setlocal buflisted
|
||||
catch
|
||||
" Prevent reporting that the error ocurred inside this function.
|
||||
echoh ErrorMsg
|
||||
echom substitute(v:exception,'\m^Vim(.\{-}):','','')
|
||||
echoh None
|
||||
endtry
|
||||
return ''
|
||||
endfunction
|
||||
" s:get_absolute_path(baseDir, fileName) {{{2
|
||||
" Guess an absolute path
|
||||
function! s:get_absolute_path(baseDir, fileName)
|
||||
let baseDir = a:baseDir
|
||||
if baseDir !~ '/$'
|
||||
let baseDir = baseDir . '/'
|
||||
endif
|
||||
if a:fileName =~ '^/'
|
||||
let absFileName = a:fileName
|
||||
else
|
||||
let absFileName = baseDir . a:fileName
|
||||
endif
|
||||
|
||||
let absFileName = substitute(absFileName, '\m/\./', '/', 'g')
|
||||
while absFileName =~ '/\.\./'
|
||||
absFileName = substitute(absFileName, '\m/[^/]*\.\./', '', '')
|
||||
endwhile
|
||||
return absFileName
|
||||
endfunction
|
||||
" s:update_jump_list() {{{2
|
||||
" Add current outline to list.
|
||||
function! s:update_jump_list()
|
||||
call add(w:vo_jump_list, [bufnr('%')] + getpos('.'))
|
||||
endfunction
|
||||
" s:remove_buf(buf) {{{2
|
||||
" Remove outline from list.
|
||||
function! s:remove_buf()
|
||||
if !exists('w:vo_jump_list') || len(w:vo_jump_list) == 0
|
||||
return
|
||||
endif
|
||||
" Remove last outline.
|
||||
call remove(w:vo_jump_list, -1)
|
||||
endfunction
|
||||
" s:jump_back() {{{2
|
||||
" Jump back to the previous outline.
|
||||
function! s:jump_back()
|
||||
if len(w:vo_jump_list) == 0
|
||||
echom 'This is the first outline.'
|
||||
return
|
||||
endif
|
||||
exec "buffer ".w:vo_jump_list[-1][0]
|
||||
call setpos('.', w:vo_jump_list[-1][1 : ])
|
||||
call s:remove_buf()
|
||||
endfunction
|
||||
" s:create_link() {{{2
|
||||
" Create an interoutline link with the current keyword under the cursor.
|
||||
function! s:create_link()
|
||||
let line = getline('.')
|
||||
" Create link on a header only
|
||||
if line =~ '\m^\t\+[^ :;<>|]'
|
||||
echom 'Vimoutliner: Links have to be on a header.'
|
||||
return
|
||||
endif
|
||||
" Check if the there's is some content in the current line and a current
|
||||
" link doesn't exists.
|
||||
if line =~# '\m^\t*'.s:checkboxpat.'_ilink_\%([^:]\{-}:\s\)\?\s*\S\+.*$'
|
||||
echom 'Vimoutliner: Looks like "'.substitute(line,'^\t*'.s:checkboxpat.'\(\S.*$\)','\1','').'" is already a link.'
|
||||
return
|
||||
endif
|
||||
call inputsave()
|
||||
let path = input('Linked outline''s path: ', '', 'file')
|
||||
call inputrestore()
|
||||
if path == ''
|
||||
" User canceled.
|
||||
return ''
|
||||
endif
|
||||
let path = matchstr(path, '\m^\t*'.s:checkboxpat.'\zs\S.\{-}\ze\s*$')
|
||||
"if path !~ '\.otl$'
|
||||
"" Add extension.
|
||||
"let path = path.'.otl'
|
||||
"endif
|
||||
let tag = '_ilink_'
|
||||
let [_,indent,checkbox,label;m0] = matchlist(line, '\m^\(\t*\)\('.s:checkboxpat.'\)\%(_ilink_\)\?\s*\(\S\%(.\{-1,}\S\)\?\)\?\s*\%(:\s\)\?\s*$')
|
||||
"echom indent.'-'.checkbox.'-'.label
|
||||
if indent == ''
|
||||
let indent = matchstr(getline(line('.')-1), '\m^\(\t*\)')
|
||||
endif
|
||||
if label !~ ':\s*$'
|
||||
let label = substitute(label, '\m\s*$', ': ', '')
|
||||
else
|
||||
let label = substitute(label, '\m:\s*$', ': ', '')
|
||||
endif
|
||||
|
||||
call setline(line('.'), indent.checkbox.tag.' '.label.path)
|
||||
echo ''
|
||||
endfunction
|
||||
" Autocommands {{{1
|
||||
augroup vo_links
|
||||
au!
|
||||
au BufWinEnter * if !exists('w:vo_jump_list') | let w:vo_jump_list = [] | endif
|
||||
augroup END
|
||||
"{{{1 vim:foldmethod=marker
|
17
pack/acp/start/vimoutliner/vimoutliner/scripts/MediaWiki2otl
Normal file
17
pack/acp/start/vimoutliner/vimoutliner/scripts/MediaWiki2otl
Normal file
|
@ -0,0 +1,17 @@
|
|||
"delete trailing white space
|
||||
:%s/^[ \t][ \t]*\(.*\)$/\1/
|
||||
"delete one line from each block of empty lines
|
||||
:g/^\_$\n\_^..*$/d
|
||||
"add leading : to body text
|
||||
:%s/^[^=]..*[^=]$/:&/
|
||||
"add leading : to dividers made entirely of equal signs
|
||||
:%s/^==*$/:&/
|
||||
"delete one leading = and space from heading
|
||||
"delete trailing space and = from heading
|
||||
"\1 is leading equal signs. \2 is heading.
|
||||
:%s/^=\(=*\) \(.*\) =\+$/\1\2/
|
||||
"indent body text lines (lines starting with ":")
|
||||
"how to indent body text lines?
|
||||
"indent headings
|
||||
"substitute each = with tab
|
||||
:g/^=/s/=/\t/g
|
|
@ -0,0 +1,37 @@
|
|||
This email has the attachment.
|
||||
|
||||
Hello Vim Outliners,
|
||||
|
||||
I want to migrate some word processor documents to otl. If you know of a formatter to convert "MediaWiki to otl" or "odt to otl" or "doc to otl" please let me know. I did not find one.
|
||||
|
||||
I am attempting to write ex script to convert MediaWiki to otl. This would be useful because LibreOffice Writer can export to MediaWiki format, and then the script would convert it to otl.
|
||||
|
||||
The heading format in MediaWiki is simple; one equal sign for each level in the heading hierarchy e.g.:
|
||||
|
||||
= head1 =
|
||||
body text
|
||||
== head2 ==
|
||||
body text
|
||||
=== head3 ===
|
||||
body text
|
||||
|
||||
The above MediaWiki text should convert to otl like this:
|
||||
|
||||
head1
|
||||
:body text
|
||||
head2
|
||||
:body text
|
||||
head3
|
||||
:body text
|
||||
|
||||
The attached MediaWiki2otl script converts MediaWiki to otl except for one thing. I can not figure out how to indent the body text lines (indent lines that start with “:”). Here is the pseudo code:
|
||||
|
||||
if current line has “=”
|
||||
set count to number of “=”
|
||||
else
|
||||
insert count “\t”
|
||||
|
||||
Can this be done in ex script? i.e. Is there an ex command that can set a variable (or register) and an ex command to read that variable in the following lines?
|
||||
|
||||
Thank you,
|
||||
wolfv
|
118
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/COPYING
Normal file
118
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/COPYING
Normal file
|
@ -0,0 +1,118 @@
|
|||
The Litt Perl Development Tools License
|
||||
Version 1.0, 3/14/2003
|
||||
---------------------------------------
|
||||
|
||||
The Litt Perl Development Tools License (LPDTL)
|
||||
consists of the GNU GPL plus an exception, plus an
|
||||
exception to that exception.
|
||||
|
||||
This program is free software; you can
|
||||
redistribute it and/or modify it under the terms
|
||||
of version 2 of the GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it
|
||||
will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General
|
||||
Public License along with this software; see the
|
||||
file COPYING.GPL. If not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite
|
||||
330, Boston, MA 02111-1307 USA. Other locations
|
||||
for the GNU General Public License include:
|
||||
|
||||
http://www.troubleshooters.com/licenses/LPDTL/COPYING.GPL
|
||||
|
||||
and
|
||||
|
||||
http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
|
||||
THE EXCEPTION
|
||||
|
||||
As a special exception, the author of this Perl
|
||||
Development Tool gives permission for additional
|
||||
uses of the text contained in this Perl
|
||||
Development Tool.
|
||||
|
||||
The exception is that, if you reference the LPDTL
|
||||
licensed software, by use of a Perl "use" or
|
||||
"require" statement, from other files, this does
|
||||
not by itself cause the files referencing this
|
||||
Perl Development Tool to be covered by the GNU
|
||||
General Public License. Your use of the
|
||||
referencing files is in no way restricted on
|
||||
account of their referencing the code in this Perl
|
||||
Development Tool.
|
||||
|
||||
Likewise, if you link the LPDTL licensed software
|
||||
with other files to produce an executable, this
|
||||
does not by itself cause the resulting executable
|
||||
to be covered by the GNU General Public License.
|
||||
Your use of that executable is in no way
|
||||
restricted on account of linking the LPDTL
|
||||
licensed software's code into it.
|
||||
|
||||
|
||||
EXCEPTION LIMITATIONS
|
||||
|
||||
This exception does not however invalidate any
|
||||
other reasons why the referencing files, or any
|
||||
produced executables, might be covered by the GNU
|
||||
General Public License.
|
||||
|
||||
This exception applies only to the code released
|
||||
by its author under the Litt Perl Development
|
||||
Tools License. Such code must clearly state that
|
||||
it's covered by the Litt Perl Development Tools
|
||||
License. If you copy code from other GNU-GPL
|
||||
compatible software, as the General Public License
|
||||
permits, the exception does not apply to the code
|
||||
that you add in this way. To avoid misleading
|
||||
anyone as to the status of such modified files,
|
||||
you must delete this exception notice from them.
|
||||
|
||||
If you write modifications of your own for
|
||||
software licensed under the Litt Perl Development
|
||||
Tools License, it is your choice whether to permit
|
||||
this exception to apply to your modifications. If
|
||||
you do not wish that, delete this exception
|
||||
notice.
|
||||
|
||||
This exception cannot be applied to software whose
|
||||
license, End User License Agreement, or Terms Of
|
||||
Use limit reverse engineering or discussion about
|
||||
the software. This exception cannot be applied to
|
||||
software incorporating any type of software
|
||||
patents.
|
||||
|
||||
|
||||
THE EXCEPTION TO THE EXCEPTION
|
||||
|
||||
The intent of the Litt Perl Development Tools
|
||||
License (LPDTL) is to produce a free software
|
||||
development environment enabling a software
|
||||
developer to create free software, nonfree
|
||||
software, or proprietary software. Therefore, all
|
||||
of the resulting program's software development
|
||||
features must be contained in the LPDTL licensed
|
||||
software, or in GPL licensed software. It is a
|
||||
violation of the LPDTL to place any software
|
||||
development features in any file not licensed
|
||||
under either the GPL or the LPDTL.
|
||||
|
||||
A "software development feature" is a feature
|
||||
enabling creation or modification of software.
|
||||
|
||||
|
||||
DISCUSSION OF INTENT OF THIS LICENSE
|
||||
|
||||
You can find a discussion of the intent of this
|
||||
license in the LPDTL_discuss.txt file. If you
|
||||
haven't been given a copy of this file, you can
|
||||
find it in the
|
||||
http://www.troubleshooters.com/licenses/LPDTL/
|
||||
directory.
|
340
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/COPYING.GPL
Normal file
340
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/COPYING.GPL
Normal file
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,118 @@
|
|||
The Litt Perl Development Tools License
|
||||
Version 1.0, 3/14/2003
|
||||
---------------------------------------
|
||||
|
||||
The Litt Perl Development Tools License (LPDTL)
|
||||
consists of the GNU GPL plus an exception, plus an
|
||||
exception to that exception.
|
||||
|
||||
This program is free software; you can
|
||||
redistribute it and/or modify it under the terms
|
||||
of version 2 of the GNU General Public License as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it
|
||||
will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General
|
||||
Public License along with this software; see the
|
||||
file COPYING.GPL. If not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite
|
||||
330, Boston, MA 02111-1307 USA. Other locations
|
||||
for the GNU General Public License include:
|
||||
|
||||
http://www.troubleshooters.com/licenses/LPDTL/COPYING.GPL
|
||||
|
||||
and
|
||||
|
||||
http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
|
||||
THE EXCEPTION
|
||||
|
||||
As a special exception, the author of this Perl
|
||||
Development Tool gives permission for additional
|
||||
uses of the text contained in this Perl
|
||||
Development Tool.
|
||||
|
||||
The exception is that, if you reference the LPDTL
|
||||
licensed software, by use of a Perl "use" or
|
||||
"require" statement, from other files, this does
|
||||
not by itself cause the files referencing this
|
||||
Perl Development Tool to be covered by the GNU
|
||||
General Public License. Your use of the
|
||||
referencing files is in no way restricted on
|
||||
account of their referencing the code in this Perl
|
||||
Development Tool.
|
||||
|
||||
Likewise, if you link the LPDTL licensed software
|
||||
with other files to produce an executable, this
|
||||
does not by itself cause the resulting executable
|
||||
to be covered by the GNU General Public License.
|
||||
Your use of that executable is in no way
|
||||
restricted on account of linking the LPDTL
|
||||
licensed software's code into it.
|
||||
|
||||
|
||||
EXCEPTION LIMITATIONS
|
||||
|
||||
This exception does not however invalidate any
|
||||
other reasons why the referencing files, or any
|
||||
produced executables, might be covered by the GNU
|
||||
General Public License.
|
||||
|
||||
This exception applies only to the code released
|
||||
by its author under the Litt Perl Development
|
||||
Tools License. Such code must clearly state that
|
||||
it's covered by the Litt Perl Development Tools
|
||||
License. If you copy code from other GNU-GPL
|
||||
compatible software, as the General Public License
|
||||
permits, the exception does not apply to the code
|
||||
that you add in this way. To avoid misleading
|
||||
anyone as to the status of such modified files,
|
||||
you must delete this exception notice from them.
|
||||
|
||||
If you write modifications of your own for
|
||||
software licensed under the Litt Perl Development
|
||||
Tools License, it is your choice whether to permit
|
||||
this exception to apply to your modifications. If
|
||||
you do not wish that, delete this exception
|
||||
notice.
|
||||
|
||||
This exception cannot be applied to software whose
|
||||
license, End User License Agreement, or Terms Of
|
||||
Use limit reverse engineering or discussion about
|
||||
the software. This exception cannot be applied to
|
||||
software incorporating any type of software
|
||||
patents.
|
||||
|
||||
|
||||
THE EXCEPTION TO THE EXCEPTION
|
||||
|
||||
The intent of the Litt Perl Development Tools
|
||||
License (LPDTL) is to produce a free software
|
||||
development environment enabling a software
|
||||
developer to create free software, nonfree
|
||||
software, or proprietary software. Therefore, all
|
||||
of the resulting program's software development
|
||||
features must be contained in the LPDTL licensed
|
||||
software, or in GPL licensed software. It is a
|
||||
violation of the LPDTL to place any software
|
||||
development features in any file not licensed
|
||||
under either the GPL or the LPDTL.
|
||||
|
||||
A "software development feature" is a feature
|
||||
enabling creation or modification of software.
|
||||
|
||||
|
||||
DISCUSSION OF INTENT OF THIS LICENSE
|
||||
|
||||
You can find a discussion of the intent of this
|
||||
license in the LPDTL_discuss.txt file. If you
|
||||
haven't been given a copy of this file, you can
|
||||
find it in the
|
||||
http://www.troubleshooters.com/licenses/LPDTL/
|
||||
directory.
|
23
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/INSTALL
Normal file
23
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/INSTALL
Normal file
|
@ -0,0 +1,23 @@
|
|||
INSTALLATION PROCEDURES FOR Node.pm
|
||||
Version 0.2.0 released 5/13/2004
|
||||
|
||||
Downloading
|
||||
Download from
|
||||
http://www.troubleshooters.com/projects/Node/Node.#.#.#.tgz
|
||||
Installing
|
||||
The tarball extracts into a directory called Node
|
||||
cd to the directory into which you want to place Node
|
||||
Move any existing Node directory out of the way
|
||||
tar xzvf Node.#.#.#.tgz
|
||||
Testing
|
||||
cd into the Node directory
|
||||
./hello.pl
|
||||
troubleshoot as necessary
|
||||
Using
|
||||
In any perl program using Node not in the Node directory...
|
||||
Use following code at beginning
|
||||
#!/usr/bin/perl -w -I/path/to/Node
|
||||
use strict;
|
||||
use Node;
|
||||
If destination machine has unknown Node.pm directory...
|
||||
See example_nodepath.pl
|
|
@ -0,0 +1,26 @@
|
|||
INTENT OF THE LITT PERL DEVELOPMENT TOOL LICENSE
|
||||
|
||||
The intent of the Litt Perl Development Tool License (LPDTL) is to provide
|
||||
programmers with a development tool that is copylefted free software without
|
||||
requiring applications built from this tool to be free software.
|
||||
|
||||
I (Steve Litt) have tried to craft the LPDTL to prevent "cute and
|
||||
innovative" ways of taking this tool private. For instance, a person might
|
||||
try to make the LPDTL licensed code dependent on subroutines in proprietary
|
||||
subroutines. This is why the LPDTL has a clause stating that all
|
||||
*development* features must reside in the LPDTL code, or in GPL code, but
|
||||
not non-GPL-compatible code.
|
||||
|
||||
Although the LPDTL allows its use with software of almost any license, it
|
||||
specifically forbids use with licenses doing any of the following:
|
||||
|
||||
1. Restricting reverse engineering
|
||||
|
||||
2. Restricting discussion about the software
|
||||
|
||||
3. Code that includes software patents
|
||||
|
||||
I feel that restrictions on reverse engineering and discussion, and software
|
||||
patents, are so destructive to society, that I have included language
|
||||
preventing use of LPDTL licensed code with any software incorporating any of
|
||||
these three atrocities.
|
475
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/Node.pm
Normal file
475
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/Node.pm
Normal file
|
@ -0,0 +1,475 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
#######################################################################
|
||||
# Copyright (C) 2003 by Steve Litt, all rights reserved.
|
||||
# Licensed under version 1 of the
|
||||
# Litt Perl Development Tools License
|
||||
# See COPYING file
|
||||
# Or COPYING.LPDTL.1.0
|
||||
# Or see http://www.troubleshooters.com/licenses/LPDTL/COPYING.LPDTL.1.0
|
||||
#
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK!
|
||||
#
|
||||
# Version 0.2.0 released 5/13/2004
|
||||
|
||||
use strict;
|
||||
|
||||
package Node;
|
||||
sub new($$$$)
|
||||
{
|
||||
my($typeOfClass) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $typeOfClass);
|
||||
|
||||
$self->{'name'}=$_[1];
|
||||
$self->{'type'}=$_[2];
|
||||
$self->{'value'}=$_[3];
|
||||
|
||||
|
||||
$self->{'nextsibling'}=undef;
|
||||
$self->{'prevsibling'}=undef;
|
||||
$self->{'parent'}=undef;
|
||||
$self->{'firstchild'}=undef;
|
||||
$self->{'lastchild'}=undef;
|
||||
|
||||
$self->{'attributes'}={};
|
||||
|
||||
return($self);
|
||||
}
|
||||
|
||||
|
||||
#### For single attribute
|
||||
sub setAttribute()
|
||||
{
|
||||
$_[0]->{'attributes'}->{$_[1]} = $_[2];
|
||||
}
|
||||
|
||||
sub removeAttribute()
|
||||
{
|
||||
delete $_[0]->{'attributes'}->{$_[1]};
|
||||
}
|
||||
|
||||
sub getAttribute()
|
||||
{
|
||||
if($_[0]->hasAttributes())
|
||||
{
|
||||
return $_[0]->{'attributes'}->{$_[1]};
|
||||
}
|
||||
else
|
||||
{
|
||||
return(undef);
|
||||
}
|
||||
}
|
||||
|
||||
sub hasAttribute()
|
||||
{
|
||||
if($_[0]->hasAttributes())
|
||||
{
|
||||
return defined($_[0]->getAttribute($_[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
return(undef);
|
||||
}
|
||||
}
|
||||
|
||||
#### For attribute array
|
||||
sub hasAttributes()
|
||||
{
|
||||
return defined($_[0]->getAttributes());
|
||||
}
|
||||
sub getAttributes()
|
||||
{
|
||||
return %{$_[0]->{'attributes'}};
|
||||
}
|
||||
|
||||
sub setAttributes()
|
||||
{
|
||||
$_[0]->{'attributes'} = $_[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#### For traversing
|
||||
sub getFirstChild() {return($_[0]->{'firstchild'});}
|
||||
sub getNextSibling() {return($_[0]->{'nextsibling'});}
|
||||
sub getParent() {return($_[0]->{'parent'});}
|
||||
|
||||
sub hasFirstChild() {return(defined($_[0]->{'firstchild'}));}
|
||||
sub hasNextSibling() {return(defined($_[0]->{'nextsibling'}));}
|
||||
sub hasParent() {return(defined($_[0]->{'parent'}));}
|
||||
|
||||
#### For reverse traversing
|
||||
sub getLastChild() {return($_[0]->{'lastchild'});}
|
||||
sub getPrevSibling() {return($_[0]->{'prevsibling'});}
|
||||
|
||||
sub hasLastChild() {return(defined($_[0]->{'lastchild'}));}
|
||||
sub hasPrevSibling() {return(defined($_[0]->{'prevsibling'}));}
|
||||
|
||||
#### For content
|
||||
sub getName() {return($_[0]->{'name'});}
|
||||
sub getType() {return($_[0]->{'type'});}
|
||||
sub getValue() {return($_[0]->{'value'});}
|
||||
sub setName() {$_[0]->{'name'} = $_[1];}
|
||||
sub setType() {$_[0]->{'type'} = $_[1];}
|
||||
sub setValue() {$_[0]->{'value'} = $_[1];}
|
||||
|
||||
sub hasName() {return(defined($_[0]->{'name'}));}
|
||||
sub hasType() {return(defined($_[0]->{'type'}));}
|
||||
sub hasValue() {return(defined($_[0]->{'value'}));}
|
||||
|
||||
#### For setting pointers, should probably be private or protected
|
||||
sub setFirstChild() {$_[0]->{'firstchild'} = $_[1];}
|
||||
sub setNextSibling() {$_[0]->{'nextsibling'} = $_[1];}
|
||||
sub setParent() {$_[0]->{'parent'} = $_[1];}
|
||||
sub setLastChild() {$_[0]->{'lastchild'} = $_[1];}
|
||||
sub setPrevSibling() {$_[0]->{'prevsibling'} = $_[1];}
|
||||
|
||||
#### For creation
|
||||
sub insertSiblingBeforeYou()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($oldPrevSibling) = $self->getPrevSibling();
|
||||
$self->setPrevSibling($_[1]);
|
||||
$self->getPrevSibling()->setParent($self->getParent());
|
||||
$self->getPrevSibling()->setNextSibling($self);
|
||||
if(!defined($oldPrevSibling))
|
||||
{
|
||||
$self->getParent()->setFirstChild($self->getPrevSibling());
|
||||
$self->getPrevSibling()->setPrevSibling(undef);
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->getPrevSibling()->setPrevSibling($oldPrevSibling);
|
||||
$oldPrevSibling->setNextSibling($self->getPrevSibling());
|
||||
}
|
||||
return($self->getPrevSibling());
|
||||
}
|
||||
|
||||
sub insertSiblingAfterYou()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($oldNextSibling) = $self->getNextSibling();
|
||||
$self->setNextSibling($_[1]);
|
||||
$self->getNextSibling()->setParent($self->getParent());
|
||||
$self->getNextSibling()->setPrevSibling($self);
|
||||
if(!defined($oldNextSibling))
|
||||
{
|
||||
if(defined($self->getParent()))
|
||||
{
|
||||
$self->getParent()->setLastChild($self->getNextSibling());
|
||||
}
|
||||
$self->getNextSibling()->setNextSibling(undef);
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->getNextSibling()->setNextSibling($oldNextSibling);
|
||||
$oldNextSibling->setPrevSibling($self->getNextSibling());
|
||||
}
|
||||
return($self->getNextSibling());
|
||||
}
|
||||
|
||||
sub insertFirstChild()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($oldFirstChild) = $self->getFirstChild();
|
||||
if(defined($oldFirstChild))
|
||||
{
|
||||
$oldFirstChild->insertSiblingBeforeYou($_[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->setFirstChild($_[1]);
|
||||
$self->setLastChild($_[1]);
|
||||
$self->getFirstChild()->setParent($self);
|
||||
}
|
||||
return($self->getFirstChild());
|
||||
}
|
||||
|
||||
sub insertLastChild()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($oldLastChild) = $self->getLastChild();
|
||||
if(defined($oldLastChild))
|
||||
{
|
||||
$oldLastChild->insertSiblingAfterYou($_[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->setFirstChild($_[1]);
|
||||
$self->setLastChild($_[1]);
|
||||
$self->getFirstChild()->setParent($self);
|
||||
}
|
||||
return($self->getLastChild());
|
||||
}
|
||||
|
||||
#### For cloning
|
||||
sub clone()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($clone) = Node->new();
|
||||
$clone->setName($self->getName());
|
||||
$clone->setType($self->getType());
|
||||
$clone->setValue($self->getValue());
|
||||
|
||||
$clone->setParent($self->getParent());
|
||||
$clone->setFirstChild($self->getFirstChild());
|
||||
$clone->setLastChild($self->getLastChild());
|
||||
$clone->setPrevSibling($self->getPrevSibling());
|
||||
$clone->setNextSibling($self->getNextSibling());
|
||||
return($clone);
|
||||
}
|
||||
|
||||
#### For deletion
|
||||
sub deleteSelf()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($prev) = $self->getPrevSibling();
|
||||
my($next) = $self->getNextSibling();
|
||||
my($parent) = $self->getParent();
|
||||
if((defined($self->getPrevSibling()))&&(defined($self->getNextSibling())))
|
||||
{
|
||||
$self->getNextSibling()->setPrevSibling($self->getPrevSibling());
|
||||
$self->getPrevSibling()->setNextSibling($self->getNextSibling());
|
||||
}
|
||||
elsif((!defined($self->getPrevSibling()))&&(!defined($self->getNextSibling())))
|
||||
{
|
||||
$self->getParent()->setFirstChild(undef);
|
||||
$self->getParent()->setLastChild(undef);
|
||||
}
|
||||
elsif(!defined($self->getPrevSibling()))
|
||||
{
|
||||
$self->getParent()->setFirstChild($self->getNextSibling());
|
||||
$self->getNextSibling()->setPrevSibling(undef);
|
||||
}
|
||||
elsif(!defined($self->getNextSibling()))
|
||||
{
|
||||
$self->getParent()->setLastChild($self->getPrevSibling());
|
||||
$self->getPrevSibling()->setNextSibling(undef);
|
||||
}
|
||||
$self->setFirstChild(undef);
|
||||
$self->setLastChild(undef);
|
||||
}
|
||||
|
||||
sub deleteTree()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
|
||||
# #### Code to delete children and decendents here
|
||||
$self->deleteSelf();
|
||||
}
|
||||
|
||||
package OutlineParser;
|
||||
sub new()
|
||||
{
|
||||
my($typeOfClass) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $typeOfClass);
|
||||
$self->{'head'} = Node->new("Header Node", "Head", "Inserted by OutlineParser");
|
||||
$self->{'fromstdin'} = 1;
|
||||
$self->{'zapblanks'} = 1;
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub setCommentChar($$)
|
||||
{
|
||||
$_[0]->{'commentchar'} = $_[1];
|
||||
}
|
||||
|
||||
sub getCommentChar($)
|
||||
{
|
||||
return($_[0]->{'commentchar'});
|
||||
}
|
||||
|
||||
sub hasCommentChar($)
|
||||
{
|
||||
return(defined($_[0]->{'commentchar'}));
|
||||
}
|
||||
|
||||
sub getFirstNonBlankChar($$)
|
||||
{
|
||||
my $self = shift;
|
||||
my $line = shift;
|
||||
chomp $line;
|
||||
my @parts = split(/\s+/,$line, 2);
|
||||
$line = join('', @parts);
|
||||
my $firstchar = substr($line, 0, 1);
|
||||
return $firstchar;
|
||||
}
|
||||
|
||||
|
||||
sub parse()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($fname) = $_[1];
|
||||
|
||||
my(@levelStack);
|
||||
push(@levelStack, ($self->{'head'}));
|
||||
my($checker) = $self->{'head'};
|
||||
my($lineno) = 0;
|
||||
my($prevLevel) = -1;
|
||||
|
||||
my($inf);
|
||||
if($self->{'fromstdin'} == 0)
|
||||
{
|
||||
defined($fname) or die "OutlineParser::parse() requires a filename argument, terminating.\n";
|
||||
open(INF, "<" . $fname) or die "OutlineParser::parse() could not open $fname for input, terminating.\n";
|
||||
$inf = q(INF);
|
||||
}
|
||||
else
|
||||
{
|
||||
$inf = qw(STDIN);
|
||||
}
|
||||
while(<$inf>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
$lineno++;
|
||||
my $zapFlag = 0;
|
||||
my $firstNonBlankChar = $self->getFirstNonBlankChar($line);
|
||||
if(($self->{'zapblanks'} != 0) && ($firstNonBlankChar eq ''))
|
||||
{
|
||||
$zapFlag = 1;
|
||||
}
|
||||
if($self->hasCommentChar() && ($self->getCommentChar() eq $firstNonBlankChar))
|
||||
{
|
||||
$zapFlag = 1;
|
||||
}
|
||||
|
||||
unless($zapFlag)
|
||||
{
|
||||
my($level) = 0;
|
||||
|
||||
$line =~ m/^( *)(.*)/;
|
||||
if(defined($1))
|
||||
{
|
||||
$level = length($1);
|
||||
$line = $2;
|
||||
}
|
||||
else
|
||||
{
|
||||
$line = $2;
|
||||
}
|
||||
|
||||
my $node = Node->new("", "Node", $line);
|
||||
$node->setAttribute('_lineno', $lineno);
|
||||
|
||||
if($level == $prevLevel)
|
||||
{
|
||||
$levelStack[$prevLevel]->insertSiblingAfterYou($node);
|
||||
$levelStack[$level] = $node;
|
||||
}
|
||||
elsif($level == $prevLevel + 1)
|
||||
{
|
||||
$levelStack[$prevLevel]->insertFirstChild($node);
|
||||
$levelStack[$level] = $node;
|
||||
}
|
||||
elsif($level > $prevLevel + 1)
|
||||
{
|
||||
die "Multiple indent at line $lineno, \"$line\", terminating.\n";
|
||||
}
|
||||
elsif($level < $prevLevel)
|
||||
{
|
||||
my($dedent) = $prevLevel - $level;
|
||||
while($level < $prevLevel)
|
||||
{
|
||||
pop(@levelStack);
|
||||
$prevLevel--;
|
||||
}
|
||||
$levelStack[$prevLevel]->insertSiblingAfterYou($node);
|
||||
$levelStack[$level] = $node;
|
||||
}
|
||||
$prevLevel = $level;
|
||||
}
|
||||
}
|
||||
if($self->{'fromstdin'} == 0) {close(INF);}
|
||||
return($self->getHead());
|
||||
}
|
||||
|
||||
sub fromStdin() {$_[0]->{'fromstdin'} = 1;}
|
||||
sub fromFile() {$_[0]->{'fromstdin'} = 0;}
|
||||
sub zapBlanks() {$_[0]->{'zapblanks'} = 1;}
|
||||
sub dontZapBlanks() {$_[0]->{'zapblanks'} = 0;}
|
||||
sub getHead() {return($_[0]->{'head'});}
|
||||
|
||||
|
||||
package Walker;
|
||||
sub new()
|
||||
{
|
||||
my $typeOfClass = $_[0];
|
||||
my $self = {};
|
||||
bless($self, $typeOfClass);
|
||||
$self->{'top'} = $_[1];
|
||||
$self->{'entrycallback'} = $_[2];
|
||||
$self->{'exitcallback'} = $_[3];
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub walk()
|
||||
{
|
||||
my($self) = $_[0];
|
||||
my($ascending) = 0;
|
||||
my($checker)=$self->{'top'}; # like a checker you move around a board
|
||||
my($level)=0;
|
||||
my($continue) = 1;
|
||||
my $counter = 0;
|
||||
while($continue)
|
||||
{
|
||||
if($ascending == 0)
|
||||
{
|
||||
if(defined($self->{'entrycallback'}))
|
||||
{
|
||||
my @args = @{$self->{'entrycallback'}};
|
||||
my $sub = shift(@args);
|
||||
push(@args, ($checker, $level));
|
||||
&{$sub}(@args);
|
||||
}
|
||||
if($level < 0) {$continue=0;} ## Callback sets negative to terminate
|
||||
}
|
||||
else
|
||||
{
|
||||
if(defined($self->{'exitcallback'}))
|
||||
{
|
||||
my @args = @{$self->{'exitcallback'}};
|
||||
my $sub = shift(@args);
|
||||
push(@args, ($checker, $level));
|
||||
&{$sub}(@args);
|
||||
}
|
||||
if($level < 0) {$continue=0;} ## Callback sets negative to terminate
|
||||
if($checker == $self->{'top'}) {$continue=0;}
|
||||
}
|
||||
|
||||
if($continue == 0)
|
||||
{
|
||||
#skip this if/elsif/else entirely
|
||||
}
|
||||
elsif(($ascending == 0) && (defined($checker->getFirstChild())))
|
||||
{
|
||||
$ascending = 0;
|
||||
$checker = $checker->getFirstChild();
|
||||
$level++;
|
||||
}
|
||||
elsif((defined($checker->getNextSibling())) && ($checker != $self->{'top'}))
|
||||
{
|
||||
$ascending = 0;
|
||||
$checker = $checker->getNextSibling();
|
||||
}
|
||||
elsif(defined($checker->getParent()))
|
||||
{
|
||||
$ascending = 1;
|
||||
$checker = $checker->getParent();
|
||||
$level--;
|
||||
# if($level < 1) {$continue = 0;}
|
||||
}
|
||||
else
|
||||
{
|
||||
$continue = 0;
|
||||
}
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
177
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/README.otl
Normal file
177
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/README.otl
Normal file
|
@ -0,0 +1,177 @@
|
|||
MANUAL FOR THE Node.pm Tool
|
||||
Version 0.2.0 released 5/13/2004
|
||||
License
|
||||
Litt Perl Development Tools License, version 1
|
||||
See COPYING file
|
||||
This license is the GNU GPL with an exception
|
||||
See COPYING.GPL
|
||||
NO WARRANTY!!!!! See COPYING.GPL
|
||||
Purpose
|
||||
Handling hierarchies in Perl
|
||||
Implements a tree of nodes
|
||||
Each node has a name, a type, a value, and optionally attributes
|
||||
Each node can have zero, one or many attributes
|
||||
Each attribute has a name and a value
|
||||
Especially made to handle tab indented outlines in memory
|
||||
Learning Node.pm
|
||||
Learn from the example programs: Study them in this order:
|
||||
example_hello.pl
|
||||
example_parse.pl
|
||||
example_otl2markup.pl
|
||||
example_attribs.pl
|
||||
example_bylevel.pl
|
||||
example_delete.pl
|
||||
example_insert.pl
|
||||
example_nodepath.pl
|
||||
That's the only way to learn this tool
|
||||
Do each example program in order
|
||||
Run
|
||||
Read
|
||||
Study
|
||||
Example programs
|
||||
example_hello.pl
|
||||
Proof of concept
|
||||
7 lines of perl
|
||||
Instantiate and read from a Node object
|
||||
example_parse.pl
|
||||
Parse a tab indented outline file into a Node tree
|
||||
Use a Walker object to walk the tree and print the Nodes
|
||||
Create a Callback object and callback routine
|
||||
example_otl2markup.pl
|
||||
Use return callback to create end tags
|
||||
example_attribs.pl
|
||||
Set and get Node attributes
|
||||
Observer "_lineno" attribute,
|
||||
which was set by the Parser object
|
||||
example_bylevel.pl
|
||||
Read the Node tree recursively and output by level
|
||||
Use the Callbacks object to store information
|
||||
Use multiple callbacks to simplify a complex algorithm
|
||||
Observe that the performance is still quite good
|
||||
example_delete.pl
|
||||
Delete nodes during a callback
|
||||
Observe that the Walker object takes the deletion in stride
|
||||
Observe that the Walker object does not "lose its place"
|
||||
example_insert.pl
|
||||
Insert nodes
|
||||
Build a Node tree without an outline or Parser object
|
||||
Create child nodes using an array
|
||||
Create child nodes from a callback routine
|
||||
Use a return callback to count occurrences within in its subtree
|
||||
Access and use a Node's name, type and value
|
||||
Move nodes within the tree
|
||||
example_nodepath.pl
|
||||
Load a Node.pm file in a different directory
|
||||
Load a Node.pm file at runtime from an entry in a config file
|
||||
Use an environment variable to change the name of the config file
|
||||
File manifest
|
||||
Documentation
|
||||
INSTALL
|
||||
README.otl
|
||||
Licensing
|
||||
COPYING
|
||||
COPYING.GPL
|
||||
COPYING.LPDTL.1.0
|
||||
LPDTL_discuss.txt
|
||||
Node.pm file
|
||||
|
||||
Node.pm
|
||||
Example Programs
|
||||
example_hello.pl
|
||||
example_parse.pl
|
||||
example_otl2markup.pl
|
||||
example_attribs.pl
|
||||
example_bylevel.pl
|
||||
example_delete.pl
|
||||
example_insert.pl
|
||||
example_nodepath.pl
|
||||
Sample node path config file (for example_nodepath.pl)
|
||||
myapp.cfg
|
||||
Sample outline (used for example_delete.pl)
|
||||
deletetest.otl
|
||||
Objects
|
||||
Node.pm implements three object types:
|
||||
Node
|
||||
OutlineParser
|
||||
Walker
|
||||
Node
|
||||
A single element in the hierarchy
|
||||
All nodes connected
|
||||
Parent pointer
|
||||
(the pointer is a Perl reference, of course)
|
||||
First child pointer
|
||||
Last child pointer
|
||||
Previous sibling pointer
|
||||
Last sibling pointer
|
||||
Each node has:
|
||||
A name
|
||||
hasName()
|
||||
getName()
|
||||
setName()
|
||||
A type
|
||||
hasType()
|
||||
getType()
|
||||
setType()
|
||||
A value
|
||||
hasValue()
|
||||
getValue()
|
||||
setValue()
|
||||
Zero, one or many attributes
|
||||
Each attribute has a name and a value
|
||||
Single attribute methods:
|
||||
hasAttribute()
|
||||
getAttribute()
|
||||
setAttribute()
|
||||
removeAttribute()
|
||||
Attribute array methods:
|
||||
hasAttributes()
|
||||
getAttributes()
|
||||
setAttributes()
|
||||
Node methods enable all hierarchy operations
|
||||
Node insertion
|
||||
insertFirstChild()
|
||||
insertLastChild()
|
||||
insertSiblingBeforeYou()
|
||||
insertSiblingAfterYou()
|
||||
Node deletion
|
||||
deleteSelf()
|
||||
Low level node traversal
|
||||
hasFirstChild()
|
||||
getFirstChild()
|
||||
hasLastChild()
|
||||
getLastChild()
|
||||
hasPrevSibling()
|
||||
getPrevSibling()
|
||||
hasNextSibling()
|
||||
getNextSibling()
|
||||
hasParent()
|
||||
getParent()
|
||||
OutlineParser
|
||||
Object to convert a tab indented outline to a tree of Node objects
|
||||
Outline must be well formed...
|
||||
Each line indented zero or one tab to the right of its parent
|
||||
You can set and access properties of the parse
|
||||
hasCommentChar()
|
||||
getCommentChar()
|
||||
setCommentChar()
|
||||
fromStdin()
|
||||
fromFile()
|
||||
zapBlanks()
|
||||
dontZapBlanks()
|
||||
After setting parse properties, you perform the parse
|
||||
my parser = OutlinerParser->new();
|
||||
parser->setCommentChar('#');
|
||||
parser->fromFile();
|
||||
my $topNode = parser->parse("myoutline.txt");
|
||||
Walker
|
||||
Object to traverse entire Node hierarchy
|
||||
Performs actions via callback routines
|
||||
my $walker = Walker->new($topNode, $entryCallbackRef, $returnCallbackRef);
|
||||
Entry callback occurs when node is first accessed
|
||||
Return callback occurs when node is re-accessed after going through children
|
||||
Callbacks should be object methods, not freestanding
|
||||
Callbacks must take 3 arguments:
|
||||
$self: The object containing the callback
|
||||
[\&Callbacks::cbPrintNodeInfo, $callbacks]);
|
||||
Installation
|
||||
See INSTALL file
|
|
@ -0,0 +1,18 @@
|
|||
Top
|
||||
Level2
|
||||
Level2b
|
||||
Level3
|
||||
deleteme
|
||||
gone
|
||||
gone
|
||||
deleteme
|
||||
gone
|
||||
gone
|
||||
this should stay
|
||||
deleteme
|
||||
deleteme
|
||||
gone
|
||||
gone
|
||||
Level3b
|
||||
2level2
|
||||
Top2
|
162
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_attribs.pl
Executable file
162
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_attribs.pl
Executable file
|
@ -0,0 +1,162 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
#####################################################################
|
||||
# This exercise demonstrates the use of attributes for each node.
|
||||
# Attributes are facts about an entity, rather than an entity itself.
|
||||
# In real practice, many times attributes can be substituted for nodes
|
||||
# and vice versa. However, an attribute CANNOT have children.
|
||||
#
|
||||
# This is the first exercise using multiple Walker objects. The first
|
||||
# Walker object counts each node's children, and if the node has
|
||||
# children, it creates an attribute named "children" for that node.
|
||||
# The value of the attribute is the number of direct children for
|
||||
# that node.
|
||||
#
|
||||
# Nodes are accessed two ways in the cbPrintNode() callback. The entire
|
||||
# attribute hash is accessed with hasAttributes and getAttributes(),
|
||||
# while single named attributes are accessed with hasAttributes and
|
||||
# getAttributes().
|
||||
#
|
||||
# One more action that's demonstrated is the use of secondary navigation
|
||||
# within a callback routine. For each node, the callback routine
|
||||
# navigates to the first child and then each successive sibling of that
|
||||
# child in order to count the direct children. This is a common
|
||||
# algorithm with Node.pm. It might look inefficient, and you might be
|
||||
# tempted to perform the count during the callback that prints the
|
||||
# information. Don't do it. Multiple walkers help keep Node.pm
|
||||
# enabled programs easy to understand and modify. Because the
|
||||
# entire node tree is in memory, the double navigation isn't
|
||||
# particularly slow.
|
||||
#
|
||||
# Real world programs make heavy use of multiple walkers. For instance,
|
||||
# the EMDL to UMENU program (not packaged here) has over 10 walkers.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
|
||||
use Node; # Use Note.pm tool
|
||||
|
||||
package Callbacks;
|
||||
sub new()
|
||||
{
|
||||
my($type) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $type);
|
||||
$self->{'errors'} = 0;
|
||||
$self->{'warnings'} = 0;
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub getErrors(){return $_[0]->{'errors'};}
|
||||
sub getWarnings(){return $_[0]->{'warnings'};}
|
||||
|
||||
sub cbCountChildren()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;}
|
||||
|
||||
my $childCount=0;
|
||||
if($checker->hasFirstChild())
|
||||
{
|
||||
$childCount++;
|
||||
my $checker2 = $checker->getFirstChild();
|
||||
while($checker2->hasNextSibling())
|
||||
{
|
||||
$childCount++;
|
||||
$checker2 = $checker2->getNextSibling();
|
||||
}
|
||||
$checker->setAttribute("children", $childCount);
|
||||
}
|
||||
}
|
||||
|
||||
sub cbPrintNode()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
for(my $n=0; $n < $level; $n++) {print "\t";}
|
||||
print "* ";
|
||||
print $checker->getValue(); # print the text of the node
|
||||
print "\n";
|
||||
|
||||
for(my $n=0; $n <= $level; $n++) {print "\t";}
|
||||
print "(";
|
||||
|
||||
my %attribs = {};
|
||||
%attribs = $checker->getAttributes() if $checker->hasAttributes();
|
||||
|
||||
my @keys = keys(%attribs);
|
||||
foreach my $key (sort @keys)
|
||||
{
|
||||
print $key, "=", $attribs{$key}, "; ";
|
||||
}
|
||||
|
||||
print ")\n";
|
||||
|
||||
if($checker->hasAttribute("children"))
|
||||
{
|
||||
for(my $n=0; $n <= $level; $n++) {print "\t";}
|
||||
print "This node has ";
|
||||
print $checker->getAttribute("children");
|
||||
print " children.\n";
|
||||
}
|
||||
}
|
||||
|
||||
package Main;
|
||||
|
||||
sub main()
|
||||
{
|
||||
#### PARSE FROM FILE README.otl
|
||||
my $parser = OutlineParser->new(); # instantiate parser
|
||||
$parser->setCommentChar("#"); # ignore lines starting with #
|
||||
$parser->fromFile(); # get input from file
|
||||
my $topNode=$parser->parse("README.otl");
|
||||
|
||||
#====================================================================
|
||||
# The preceding statement parses file README.otl into a node hierarchy
|
||||
# and assigns the top level node of that hierarchy to $topNode. When
|
||||
# you run the program you'll notice that the text in $topNode does
|
||||
# not appear in README.otl, but instead has value
|
||||
# "Inserted by OutlineParser".
|
||||
#
|
||||
# This is a feature, not a bug. In order to accommodate the typical
|
||||
# case of an outline having several top level items, and yet still
|
||||
# be able to represent the whole hierarchy as a single top node,
|
||||
# the OutlineParser object creates a new node with value
|
||||
# " Inserted by OutlineParser"
|
||||
# and places all the outline's top level items under that newly
|
||||
# created node.
|
||||
#
|
||||
# If the outline you're working on is guaranteed to have only
|
||||
# a single top level item, and if you want that to be the top
|
||||
# level node, you can simply do the following:
|
||||
#
|
||||
# $topNode=$topNode->getFirstChild();
|
||||
#====================================================================
|
||||
|
||||
#### INSTANTIATE THE Callbacks OBJECT
|
||||
my $callbacks = Callbacks->new();
|
||||
|
||||
#### WALK THE NODE TREE,
|
||||
#### OUTPUTTING LEVEL AND TEXT
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
[\&Callbacks::cbCountChildren, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
[\&Callbacks::cbPrintNode, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
}
|
||||
|
||||
main();
|
227
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_bylevel.pl
Executable file
227
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_bylevel.pl
Executable file
|
@ -0,0 +1,227 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
|
||||
use Node; # Use Node.pm tool
|
||||
|
||||
#####################################################################
|
||||
# The Walker object walks the node hierarchy recursively. That is,
|
||||
# it goes deep before going laterally. That's just what's needed for
|
||||
# many applications. However, sometimes it's necessary to look at
|
||||
# one level at a time.
|
||||
#
|
||||
# There are many ways to accomplish this. Some involve sorting and
|
||||
# merging. Many involve arrays of nodes on a given level, and
|
||||
# plunging one deep into each one.
|
||||
#
|
||||
# In this example we'll start with a walker that assigns the full
|
||||
# path to each node as an attribute of that node. We'll then loop
|
||||
# through all levels starting with 0, and for each one we'll print all
|
||||
# children of nodes at that level. Every time there's a parent change,
|
||||
# we'll print a header for that parent.
|
||||
#
|
||||
# This example also illustrates the use of variables within the
|
||||
# Callback object. You might have wondered why callbacks must be
|
||||
# part of an object rather than free floating functions. The answer
|
||||
# is that the use of callbacks as object methods means that we can
|
||||
# keep totals and break logic variables within the callback object,
|
||||
# thereby eliminating the (nasty) necessity of global variables.
|
||||
#
|
||||
# We cannot simply pass variables into and out of callback
|
||||
# routines because, by the very nature of a callback routine,
|
||||
# its arguments and return type are strictly predefined. In the
|
||||
# case of Node.pm the arguments are always $self, $checker and
|
||||
# $level. To get any other information into or out of the callback
|
||||
# routine, we must use a non-callback method of the same object.
|
||||
#
|
||||
# It should be noted that there's nothing wrong with having
|
||||
# multiple callback objects. If there are numerous callback
|
||||
# routines it might make sense to group them by functionality,
|
||||
# or by totals and persistent variables they must keep track of.
|
||||
#
|
||||
# As you run, study and understand this code, be aware that converting
|
||||
# a hierarchy to a list by levels is a very difficult and complex task.
|
||||
# Imagine keeping a list of children, and for each level using those
|
||||
# children to find the next generation, and rewriting the array. Or
|
||||
# prepending a level number followed by a child index on each line,
|
||||
# and then sorting the whole array by the level number and child
|
||||
# index, and finally running a routine to output the formatted
|
||||
# output, complete with break logic and headers.
|
||||
#
|
||||
# Now consider how easy Node.pm made this job. First, a trivial
|
||||
# Walker to calculate full paths, then a level loop calling a
|
||||
# Walker to print only children of nodes at the desired level. The
|
||||
# code is short, and it's very readable and understandable. The
|
||||
# callback routines are short enough that you can safely use non-
|
||||
# structured techniques such as returning from the middle instead
|
||||
# of using nested if statements. The result is even more readability.
|
||||
#
|
||||
# One could make the (very valid) point that nodes are visited many
|
||||
# times to process each once, and that this is not efficient in
|
||||
# terms of runtime performance. Absolutely true!
|
||||
#
|
||||
# However, the programming simplicity prevents truly collosal
|
||||
# efficency problems, such as cascading intermediate files, sorts,
|
||||
# and the various other CPU cycle grabbers that seem to crop up
|
||||
# in complex algorithms. And remember, the entire tree is in memory,
|
||||
# with navigation via simple pointers, so the environment of Node.pm
|
||||
# favors runtime speed.
|
||||
#
|
||||
# Case in point. My original EMDL to UMENU converter was such an
|
||||
# epic production that I needed to study it for 4 hours every time
|
||||
# I made a minor improvement. I had developed it using informal OOP
|
||||
# and structured techniques, and had paid close attention to
|
||||
# efficiency. The resulting program took 15 seconds to convert a
|
||||
# 2300 line EMDL file.
|
||||
#
|
||||
# I rewrote the converter using Node.pm. This was a complete
|
||||
# rewrite -- all new code -- no salvage. It was so much simpler
|
||||
# that I wrote it in 12 hours. But I was very concerned with
|
||||
# runtime. If the 15 seconds doubled, this would be a hassle,
|
||||
# and if it quadrupled it would be totally impractical. When
|
||||
# I ran it, the program did everything the original did, but
|
||||
# did it in 2 seconds. Node.pm had given me a 7 fold speed
|
||||
# increase.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
package Callbacks;
|
||||
sub new()
|
||||
{
|
||||
my($type) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $type);
|
||||
$self->{'errors'} = 0;
|
||||
$self->{'warnings'} = 0;
|
||||
$self->{'childrenatlevel'} = 0;
|
||||
$self->{'currentlevel'} = 0;
|
||||
$self->{'previousparentfullpath'} = "initialize";
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub getErrors(){return $_[0]->{'errors'};}
|
||||
sub getWarnings(){return $_[0]->{'warnings'};}
|
||||
|
||||
sub getChildrenAtLevel(){return $_[0]->{'childrenatlevel'};}
|
||||
sub setChildrenAtLevel(){$_[0]->{'childrenatlevel'} = $_[1];}
|
||||
sub incChildrenAtLevel(){$_[0]->{'childrenatlevel'}++;}
|
||||
|
||||
sub getCurrentLevel(){return $_[0]->{'currentlevel'};}
|
||||
sub setCurrentLevel(){$_[0]->{'currentlevel'} = $_[1];}
|
||||
|
||||
sub cbCalculateFullPath()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
if($checker->hasParent)
|
||||
{
|
||||
my $fullpath = $checker->getParent()->getAttribute("fullpath");
|
||||
$fullpath .= "/";
|
||||
$fullpath .= $checker->getValue();
|
||||
$checker->setAttribute("fullpath", $fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
$checker->setAttribute("fullpath", $checker->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
sub cbPrintNode()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
#### DO NOTHING UNLESS THIS NODE IS AT THE CURRENTLY SOUGHT LEVEL
|
||||
return unless $level == $self->getCurrentLevel();
|
||||
|
||||
#### DO NOTHING UNLESS THIS NODE HAS CHILDREN
|
||||
return unless $checker->hasFirstChild();
|
||||
|
||||
#### PRINT HEADER
|
||||
print "\n", $checker->getAttribute("fullpath"), "\n";
|
||||
|
||||
#### PRINT CHILDREN AND COUNT CHILDREN AT LEVEL
|
||||
my $checker2 = $checker->getFirstChild(); # We returned if there wasn't one
|
||||
print "\t", $checker2->getValue(), "\n";
|
||||
$self->incChildrenAtLevel();
|
||||
|
||||
while($checker2->hasNextSibling())
|
||||
{
|
||||
$checker2 = $checker2->getNextSibling();
|
||||
print "\t", $checker2->getValue(), "\n";
|
||||
$self->incChildrenAtLevel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
package Main;
|
||||
|
||||
sub main()
|
||||
{
|
||||
#### PARSE FROM FILE README.otl
|
||||
my $parser = OutlineParser->new(); # instantiate parser
|
||||
$parser->setCommentChar("#"); # ignore lines starting with #
|
||||
$parser->fromFile(); # get input from file
|
||||
my $topNode=$parser->parse("README.otl");
|
||||
|
||||
|
||||
#### INSTANTIATE THE Callbacks OBJECT
|
||||
my $callbacks = Callbacks->new();
|
||||
|
||||
#### WALK THE NODE TREE,
|
||||
#### CALCULATING FULL PATHS AND PUTTING THEM IN AN ATTRIBUTE
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode, # start with this node
|
||||
[\&Callbacks::cbCalculateFullPath, $callbacks] # do this on entry to each node
|
||||
);
|
||||
$walker->walk();
|
||||
|
||||
#### PRINT LEVEL 0
|
||||
print "\n\n********** BEGIN LEVEL ", "0", "\n";
|
||||
print "\t", $topNode->getValue(), "\n";
|
||||
|
||||
#### SET STARTING PARENT LEVEL,
|
||||
#### AND SET $childCount SO THE LOOP WILL FIRE THE FIRST TIME
|
||||
my $level=0;
|
||||
my $childCount=9999;
|
||||
|
||||
#==================================================================
|
||||
# The main loop follows, level by level. At each level, nodes are
|
||||
# queried for their children, which are then printed below the
|
||||
# node's full path. The result is a list of nodes sorted by
|
||||
# level.
|
||||
#
|
||||
# We add 1 to the level in the level header because we're referring
|
||||
# to the level of the children, not of the current node. We keep
|
||||
# looping to deeper levels until a level counts no children.
|
||||
#
|
||||
# This logic result in an empty level header at the bottom. If this
|
||||
# were a big concern, we could print the level headers in the
|
||||
# Callbacks::cbPrintNode() callback, with slightly altered logic.
|
||||
# However, it's a minor point, so for simplicity we print the
|
||||
# level header at the top of this loop in the main routine.
|
||||
#==================================================================
|
||||
while($childCount > 0)
|
||||
{
|
||||
print "\n\n********** BEGIN LEVEL ", $level + 1, "\n";
|
||||
$callbacks->setChildrenAtLevel(0);
|
||||
$callbacks->setCurrentLevel($level);
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
[\&Callbacks::cbPrintNode, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
$childCount = $callbacks->getChildrenAtLevel();
|
||||
$level++;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
107
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_delete.pl
Executable file
107
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_delete.pl
Executable file
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
|
||||
use Node; # Use Node.pm tool
|
||||
|
||||
#####################################################################
|
||||
# This exercise demonstrates the deletion of nodes.
|
||||
#
|
||||
# Because Perl is a garbage collection language, node deletion
|
||||
# DOES NOT deallocate memory and the like. However, in the absense
|
||||
# of a copy of the node, it will be garbage collected and unavailable.
|
||||
# Also, the deletion process specificly undef's the deleted node's
|
||||
# first and last children.
|
||||
#
|
||||
# You noticed I mentioned keeping a copy. The algorithm of a Walker
|
||||
# object moves a node around the tree like a checker. Calling
|
||||
# $checker->deleteSelf() does not render $checker undefined. In fact,
|
||||
# it still has its parent, nextSibling and previousSibling pointers
|
||||
# intact. What this means is that the Walker's next iteration goes
|
||||
# to exactly the same node as it would have if the deletion had not
|
||||
# taken place. In other words, you do not need to "move the checker
|
||||
# back one" after a deletion.
|
||||
#
|
||||
# This makes deletion algorithms very simple.
|
||||
#
|
||||
# There may come a time when you want to delete a node but keep its
|
||||
# children. In that case, you must first attach its children to nodes
|
||||
# that will not be deleted.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
package Callbacks;
|
||||
sub new()
|
||||
{
|
||||
my($type) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $type);
|
||||
$self->{'errors'} = 0;
|
||||
$self->{'warnings'} = 0;
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub getErrors(){return $_[0]->{'errors'};}
|
||||
sub getWarnings(){return $_[0]->{'warnings'};}
|
||||
|
||||
sub cbDelete()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
#### DELETE THIS NODE IF ITS VALUE CONTAINS deleteme
|
||||
my $text = "init";
|
||||
$text = $checker->getValue() if $checker->hasValue();
|
||||
if($text =~ m/deleteme/)
|
||||
{
|
||||
$checker->deleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
sub cbPrintNode()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;}
|
||||
|
||||
for(my $n=0; $n < $level; $n++) {print "\t";}
|
||||
print $checker->getValue(), "\n";
|
||||
}
|
||||
|
||||
package Main;
|
||||
|
||||
sub main()
|
||||
{
|
||||
#### PARSE FROM FILE README.otl
|
||||
my $parser = OutlineParser->new();
|
||||
$parser->setCommentChar("#");
|
||||
$parser->fromFile();
|
||||
my $topNode=$parser->parse("deletetest.otl");
|
||||
|
||||
#### INSTANTIATE THE Callbacks OBJECT
|
||||
my $callbacks = Callbacks->new();
|
||||
|
||||
#### WALK THE NODE TREE,
|
||||
#### DELETING NODES WITH "deleteme" IN THEM
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
[\&Callbacks::cbDelete, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
|
||||
#### WALK THE NODE TREE,
|
||||
#### OUTPUTTING LEVEL AND TEXT
|
||||
$walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
[\&Callbacks::cbPrintNode, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
}
|
||||
|
||||
main();
|
15
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_hello.pl
Executable file
15
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_hello.pl
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
use Node;
|
||||
|
||||
my $topNode = Node->new("myname", "mytype", "myvalue");
|
||||
print "\n::: ";
|
||||
print $topNode->getName(), " ::: ";
|
||||
print $topNode->getType(), " ::: ";
|
||||
print $topNode->getValue(), " :::\n";
|
550
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_insert.pl
Executable file
550
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_insert.pl
Executable file
|
@ -0,0 +1,550 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
|
||||
use Node; # Use Node.pm tool
|
||||
|
||||
#####################################################################
|
||||
# WARNING: This is a difficult exercise. Do not attempt this exercise
|
||||
# until you have completed the prerequisites listed in the README.otl
|
||||
# file.
|
||||
#
|
||||
# I suggest you approach this example starting with the main routine
|
||||
# at the bottom of the file, and then drilling down into subroutines
|
||||
# and callbacks. Understand the big picture before drilling down.
|
||||
#
|
||||
# This exercise demonstrates insertion of nodes, and much, much more.
|
||||
# Insertion is accomplished by the insertFirstChild(),
|
||||
# insertSiblingBeforeYou(), insertSiblingAfterYou(), and
|
||||
# insertLastChild() methods. The insertLastChild() method is not
|
||||
# demonstrated.
|
||||
#
|
||||
# This exercise is VERY contrived. It is contrived to show techniques
|
||||
# of building a node tree using insertions, and also how to switch
|
||||
# two nodes. The switching of the two nodes is especially contrived,
|
||||
# but I could think of no better way of demonstrating node moving.
|
||||
#
|
||||
# This exercise builds a tree that represents a date book type calendar.
|
||||
# Level 0 is Calender, level 1 are the years, of which there is only 2004,
|
||||
# Level 2 are the months, level 3 the days, and level 4 the hour long
|
||||
# timeslots. There is no provision for weekends, nor after hours
|
||||
# appointments. It is a demonstration only.
|
||||
#
|
||||
# Using an array of month names and an array of days per month, you build
|
||||
# the month and day levels using a nested loop. The hour level is built
|
||||
# using a Walker. Node names are things like "January" or 31 or
|
||||
# "11:00-12:00". Node types are things like "Year", "Month", "Day" or
|
||||
# "Hour". Node values are undefined unless an appointment is made, in
|
||||
# which case the value is the node text.
|
||||
#
|
||||
# A special Walker is used to mark any day, month or year entities
|
||||
# if they contain appointments. Specifically, all appointments in that
|
||||
# day, month or year are counted, and that number of stars are placed
|
||||
# beside the day, month or year. This is implemented by using an
|
||||
# return callback so that by the time the callback is called, all children
|
||||
# have been calculated.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
package Callbacks;
|
||||
sub new()
|
||||
{
|
||||
my($type) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $type);
|
||||
$self->{'errors'} = 0;
|
||||
$self->{'warnings'} = 0;
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub getErrors(){return $_[0]->{'errors'};}
|
||||
sub getWarnings(){return $_[0]->{'warnings'};}
|
||||
|
||||
#=================================================================
|
||||
# The cbMakeMarks() callback is called on return to a node from
|
||||
# its children (return callback). It executes only on year, month
|
||||
# and day nodes. It iterates through all its immediate children,
|
||||
# totalling up the "appointments" attribute and setting its
|
||||
# own attribute to that total. Remember, because this is a
|
||||
# callback triggered on return from children, it is guaranteed
|
||||
# that all children have been counted, and that all those children
|
||||
# have totalled their children, etc.
|
||||
#
|
||||
# In the case of a day node, instead of totalling the "appointments"
|
||||
# attribute, it counts the number of hour nodes with defined values.
|
||||
# A defined value on an hour node is an appointment.
|
||||
#
|
||||
# Last but not least, on non-zero counts, this callback sets the
|
||||
# day, month or year node's value to a number of asterisks equal
|
||||
# to the number of appointments in its subtree.
|
||||
#
|
||||
# Read this code carefully. Once you understand it, you'll have
|
||||
# many insights to Node.pm.
|
||||
#=================================================================
|
||||
sub cbMakeMarks()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
#### PROCESS ONLY DAY, MONTH OR YEAR NODES
|
||||
unless (
|
||||
$checker->getType() eq "Day" ||
|
||||
$checker->getType() eq "Month" ||
|
||||
$checker->getType() eq "Year"
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
my $count = 0;
|
||||
my $childNode = $checker->getFirstChild();
|
||||
while(defined($childNode))
|
||||
{
|
||||
if($checker->getType() eq "Day")
|
||||
{
|
||||
if(defined($childNode->getValue()))
|
||||
{
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($childNode->hasAttribute("appointments"))
|
||||
{
|
||||
$count += $childNode->getAttribute("appointments");
|
||||
}
|
||||
}
|
||||
$childNode = $childNode->getNextSibling();
|
||||
}
|
||||
$checker->setAttribute("appointments", $count);
|
||||
if($count > 0)
|
||||
{
|
||||
my $string;
|
||||
for(my $n=0; $n < $count; $n++){$string .= '*';}
|
||||
$checker->setValue($string);
|
||||
}
|
||||
}
|
||||
|
||||
#=================================================================
|
||||
# The cbInsertHours() callback operates ONLY on day nodes. When
|
||||
# called from a day node, it inserts hourlong appointment slots
|
||||
# starting at 8am and ending at 5pm. The code is pretty
|
||||
# straightforward.
|
||||
#=================================================================
|
||||
sub cbInsertHours()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
|
||||
return unless $checker->getType() eq "Day"; # Insert hours under days only
|
||||
|
||||
my $checker2;
|
||||
for(my $n=8; $n <= 16; $n++)
|
||||
{
|
||||
my $startHour = "$n:00";
|
||||
my $n2 = $n + 1;
|
||||
my $endHour = "$n2:00";
|
||||
my $node = Node->new("$startHour" . "-" . "$endHour", "Hour", undef);
|
||||
if($checker->hasFirstChild())
|
||||
{
|
||||
$checker2 = $checker2->insertSiblingAfterYou($node);
|
||||
}
|
||||
else
|
||||
{
|
||||
$checker2 = $checker->insertFirstChild($node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#=================================================================
|
||||
# The cbPrintNode() callback prints the name of the node,
|
||||
# and its value if a value is defined. It's very straighforward.
|
||||
#=================================================================
|
||||
sub cbPrintNode()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
#### DON'T PRINT LEVEL 0 (CALENDER)
|
||||
return if $level == 0;
|
||||
|
||||
for(my $n=1; $n < $level; $n++) { print "\t";}
|
||||
|
||||
print $checker->getName() if $checker->hasName();
|
||||
print ": ";
|
||||
|
||||
print $checker->getValue() if $checker->hasValue();
|
||||
print "\n";
|
||||
}
|
||||
|
||||
|
||||
#=================================================================
|
||||
# The cbPrintNodeDiagnosic() callback is not used, but provided
|
||||
# for any necessary debugging.
|
||||
#=================================================================
|
||||
sub cbPrintNodeDiagnostic()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
|
||||
for(my $n=0; $n < $level; $n++) { print "\t";}
|
||||
|
||||
print ">";
|
||||
print $checker->getName() if $checker->hasName();
|
||||
print " ::: ";
|
||||
|
||||
print $checker->getType() if $checker->hasType();
|
||||
print " ::: ";
|
||||
|
||||
print $checker->getValue() if $checker->hasValue();
|
||||
print "<\n";
|
||||
}
|
||||
|
||||
package Main;
|
||||
|
||||
###########################################################################
|
||||
# The insertDays() subroutine handles insertion of days below all
|
||||
# month nodes.
|
||||
###########################################################################
|
||||
sub makeAppointments($)
|
||||
{
|
||||
my $yearNode = shift;
|
||||
#### MARCH 22 AT 8AM
|
||||
my $monthNode = $yearNode->getFirstChild() -> #January
|
||||
getNextSibling() -> #February
|
||||
getNextSibling(); #March
|
||||
my $dayNode = $monthNode->getFirstChild();
|
||||
while($dayNode->getName() != 22)
|
||||
{
|
||||
$dayNode = $dayNode->getNextSibling();
|
||||
unless(defined($dayNode))
|
||||
{
|
||||
die "No March 22\n";
|
||||
}
|
||||
}
|
||||
my $hourNode = $dayNode->getFirstChild();
|
||||
$hourNode->setValue("Spring Cleaning");
|
||||
|
||||
#### JUNE 22 AT 9AM
|
||||
#### WRONGLY LABELED AS FALL FESTIVAL
|
||||
#### INSTEAD OF SUMMER BREAK
|
||||
$monthNode = $monthNode->getNextSibling() -> # April
|
||||
getNextSibling() -> # May
|
||||
getNextSibling(); # June
|
||||
$dayNode = $monthNode->getFirstChild();
|
||||
while($dayNode->getName() != 22)
|
||||
{
|
||||
$dayNode = $dayNode->getNextSibling();
|
||||
unless(defined($dayNode))
|
||||
{
|
||||
die "No June 22\n";
|
||||
}
|
||||
}
|
||||
$hourNode = $dayNode->getFirstChild()->getNextSibling();
|
||||
$hourNode->setValue("Fall Festival");
|
||||
|
||||
#### SEPTEMBER 22 AT 10AM
|
||||
#### WRONGLY LABELED AS FALL FESTIVAL
|
||||
#### INSTEAD OF SUMMER BREAK
|
||||
$monthNode = $monthNode->getNextSibling() -> # July
|
||||
getNextSibling() -> # August
|
||||
getNextSibling(); # September
|
||||
$dayNode = $monthNode->getFirstChild();
|
||||
while($dayNode->getName() != 22)
|
||||
{
|
||||
$dayNode = $dayNode->getNextSibling();
|
||||
unless(defined($dayNode))
|
||||
{
|
||||
die "No September 22\n";
|
||||
}
|
||||
}
|
||||
$hourNode = $dayNode -> getFirstChild() -> #8-9
|
||||
getNextSibling() -> # 9-10
|
||||
getNextSibling(); # 10-11
|
||||
$hourNode->setValue("Summer Break");
|
||||
|
||||
#### DECEMBER 22 FROM 3PM TO 5PM (2 TIMESLOTS)
|
||||
#### HAPPY HOLIDAYS PARTY
|
||||
$monthNode = $monthNode->getNextSibling() -> # October
|
||||
getNextSibling() -> # November
|
||||
getNextSibling(); # December
|
||||
$dayNode = $monthNode->getFirstChild();
|
||||
while($dayNode->getName() != 22)
|
||||
{
|
||||
$dayNode = $dayNode->getNextSibling();
|
||||
unless(defined($dayNode))
|
||||
{
|
||||
die "No December 22\n";
|
||||
}
|
||||
}
|
||||
$hourNode = $dayNode->getFirstChild();
|
||||
while($hourNode->getName() ne "15:00-16:00")
|
||||
{
|
||||
$hourNode = $hourNode->getNextSibling();
|
||||
unless(defined($hourNode))
|
||||
{
|
||||
die "No 4pm slot\n";
|
||||
}
|
||||
}
|
||||
$hourNode->setValue("Happy Holidays Party");
|
||||
$hourNode = $hourNode->getNextSibling();
|
||||
$hourNode->setValue("Happy Holidays Party");
|
||||
|
||||
#### DECEMBER 30 AT 9AM BUY PARTY SUPPLIES
|
||||
while($dayNode->getName() != 30)
|
||||
{
|
||||
$dayNode = $dayNode->getNextSibling();
|
||||
unless(defined($dayNode))
|
||||
{
|
||||
die "No December 30\n";
|
||||
}
|
||||
}
|
||||
$hourNode = $dayNode->getFirstChild()->getNextSibling();
|
||||
$hourNode->setValue("Buy Party Supplies");
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# The insertMonthsAndDays() subroutine handles insertion of months
|
||||
# below the year, and days below every month. It works by iterating through
|
||||
# an array of months, and finding number of days in an array of month
|
||||
# lengths. It does NOT use the Node.pm navigational system to find months.
|
||||
# Use of the Node.pm navigational system for this purpose is demonstrated
|
||||
# in the insertion of hours in all days.
|
||||
#
|
||||
# Note that we could have avoided using a nested loop by using a Walker
|
||||
# and associated callback to install the days under every month. In such
|
||||
# a case the array of month lengths would have been placed in the Callback
|
||||
# object. However, for the sake of variety, we chose to use a nested loop
|
||||
# to load the months and days.
|
||||
###########################################################################
|
||||
sub insertMonthsAndDays($)
|
||||
{
|
||||
my $yearNode = shift;
|
||||
my $checker = $yearNode;
|
||||
my $checker2;
|
||||
my @monthNames=("January", "February", "March", "April", "May",
|
||||
"June", "July", "August", "September", "October",
|
||||
"November", "December");
|
||||
my @monthLengths=(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
|
||||
my $monthSS = 0;
|
||||
foreach my $monthName (@monthNames)
|
||||
{
|
||||
my $node = Node->new($monthName, "Month", undef);
|
||||
$node->setAttribute("days", $monthLengths[$monthSS]);
|
||||
if($yearNode->hasFirstChild())
|
||||
{
|
||||
$checker = $checker->insertSiblingAfterYou($node);
|
||||
}
|
||||
else
|
||||
{
|
||||
$checker = $yearNode->insertFirstChild($node);
|
||||
}
|
||||
for(my $n=1; $n <= $monthLengths[$monthSS]; $n++)
|
||||
{
|
||||
$node = Node->new($n, "Day", undef);
|
||||
if($checker->hasFirstChild())
|
||||
{
|
||||
$checker2 = $checker2->insertSiblingAfterYou($node);
|
||||
}
|
||||
else
|
||||
{
|
||||
$checker2 = $checker->insertFirstChild($node);
|
||||
}
|
||||
}
|
||||
$monthSS++;
|
||||
}
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# This subroutine switches the June 22 9am appointment and the
|
||||
# September 22 10am appointment. In each case, both the appointment
|
||||
# text and the time needed switching.
|
||||
#
|
||||
# The sane way to accomplish this task would have been to modify
|
||||
# the nodes in place. However, this subroutine was created solely to
|
||||
# demonstrate the movement of nodes, so that's what we did.
|
||||
#
|
||||
# Note that the fact that the two are at different times complicates the
|
||||
# situation. It's not enough to just trade nodes -- the Sept 9am node
|
||||
# must be placed after the existing June 10am node, which itself is after
|
||||
# the erroneous June 9am node containing what should be September's
|
||||
# appointment. After such placement, the original June 9am node must
|
||||
# have its name updated so that it is a 10am node. A similar process
|
||||
# takes place for September. The original nodes are also deleted.
|
||||
#
|
||||
# Please follow the (convoluted and contrived) logic:
|
||||
# 1. Store the June hour node in $juneNode
|
||||
# 2. Store the September hour node in $septNode
|
||||
# 3. After the existing June 10am, place a CLONE of the Sept appointment
|
||||
# 4. Before the existing Sept 9am, place a CLONE of the June appointment
|
||||
# 5. Delete the original June appointment
|
||||
# 6. Delete the original September appointment
|
||||
# 7. On the original June 10am node, make it 9am
|
||||
# 8. On the original September 9am node, make it 10am
|
||||
###########################################################################
|
||||
sub switchJuneAndSeptemberAppointments($)
|
||||
{
|
||||
my $yearNode = shift;
|
||||
|
||||
#### FIND NODE FOR JUNE 22 9AM APPOINTMENT
|
||||
my $juneNode = $yearNode->getFirstChild();
|
||||
while(defined($juneNode))
|
||||
{
|
||||
last if $juneNode->getName() eq "June";
|
||||
$juneNode = $juneNode->getNextSibling();
|
||||
}
|
||||
die "Cannot find month of June\n" unless defined($juneNode);
|
||||
|
||||
$juneNode = $juneNode->getFirstChild();
|
||||
while(defined($juneNode))
|
||||
{
|
||||
last if $juneNode->getName() eq "22";
|
||||
$juneNode = $juneNode->getNextSibling();
|
||||
}
|
||||
die "Cannot find June 22\n" unless defined($juneNode);
|
||||
|
||||
$juneNode = $juneNode->getFirstChild();
|
||||
while(defined($juneNode))
|
||||
{
|
||||
last if $juneNode->getName() eq "9:00-10:00";
|
||||
$juneNode = $juneNode->getNextSibling();
|
||||
}
|
||||
die "Cannot find June 22 at 9am\n" unless defined($juneNode);
|
||||
|
||||
#### FIND NODE FOR SEPTEMBER 22 10AM APPOINTMENT
|
||||
my $septNode = $yearNode->getFirstChild();
|
||||
while(defined($septNode))
|
||||
{
|
||||
last if $septNode->getName() eq "September";
|
||||
$septNode = $septNode->getNextSibling();
|
||||
}
|
||||
die "Cannot find month of September\n" unless defined($septNode);
|
||||
|
||||
$septNode = $septNode->getFirstChild();
|
||||
while(defined($septNode))
|
||||
{
|
||||
last if $septNode->getName() eq "22";
|
||||
$septNode = $septNode->getNextSibling();
|
||||
}
|
||||
die "Cannot find September 22\n" unless defined($septNode);
|
||||
|
||||
$septNode = $septNode->getFirstChild();
|
||||
while(defined($septNode))
|
||||
{
|
||||
last if $septNode->getName() eq "10:00-11:00";
|
||||
$septNode = $septNode->getNextSibling();
|
||||
}
|
||||
die "Cannot find September 22 at 9am\n" unless defined($septNode);
|
||||
|
||||
#### SWITCH THE NODES
|
||||
my $newJune = $juneNode->getNextSibling()->insertSiblingAfterYou($septNode->clone());
|
||||
my $newSept = $septNode->getPrevSibling()->insertSiblingBeforeYou($juneNode->clone());
|
||||
$juneNode->deleteSelf();
|
||||
$septNode->deleteSelf();
|
||||
|
||||
#### FIX NAMES OF SURROUNDING CLONES
|
||||
$newJune->getPrevSibling()->setName("9:00-10:00");
|
||||
$newSept->getNextSibling()->setName("10:00-11:00");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
###########################################################################
|
||||
# In the main routine, you carry out or delegate the following tasks
|
||||
# in order to create an appointment calendar:
|
||||
# 1. Insert single level 0 and 1 nodes
|
||||
# 2. Instantiate the Callbacks object
|
||||
# 3. Insert all month and day nodes
|
||||
# 4. Insert all hour nodes
|
||||
# 5. Make appointments
|
||||
# erroneously switching the june 22 & Sept 22 appointments
|
||||
# 6. Mark days, months and years containing appointments
|
||||
# 7. Output the calendar
|
||||
# 8. Switch back June22 and Sept22
|
||||
# 9. Re mark days, months and years
|
||||
# 10. Output a separator between bad and good calendars
|
||||
# 11. Re output the calendar
|
||||
#
|
||||
###########################################################################
|
||||
sub main()
|
||||
{
|
||||
#### INSERT SINGLE LEVEL 0 AND 1 NODES
|
||||
my $topNode=Node->new("Calender", "Calender", "Calender");
|
||||
my $yearNode=$topNode->insertFirstChild(Node->new("2004", "Year", undef));
|
||||
|
||||
#### INSTANTIATE THE Callbacks OBJECT
|
||||
my $callbacks = Callbacks->new();
|
||||
|
||||
#### INSERT MONTH AND DAY NODES
|
||||
insertMonthsAndDays($yearNode);
|
||||
|
||||
#### INSERT THE HOURS USING A Walker
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
[\&Callbacks::cbInsertHours, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
|
||||
|
||||
#### MAKE A FEW APPOINTMENTS
|
||||
#### ACCIDENTALLY SWITCHING SUMMER AND FALL
|
||||
makeAppointments($yearNode);
|
||||
|
||||
#### MARK DAYS, MONTHS AND YEAR THAT HAVE APPOINTMENTS
|
||||
#### USING A WALKER WITH ONLY A RETURN CALLBACK
|
||||
$walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
undef,
|
||||
[\&Callbacks::cbMakeMarks, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
|
||||
#### WALK THE NODE TREE,
|
||||
#### OUTPUTTING THE CALENDER
|
||||
$walker = Walker->new
|
||||
(
|
||||
$topNode, # start with this node
|
||||
[\&Callbacks::cbPrintNode, $callbacks] # do this on entry to each node
|
||||
);
|
||||
$walker->walk();
|
||||
|
||||
#### CORRECT THE MISTAKE
|
||||
#### SWITCH JUNE 22 AND SEPT 22
|
||||
switchJuneAndSeptemberAppointments($yearNode);
|
||||
|
||||
#### RE-MARK DAYS, MONTHS AND YEAR THAT HAVE APPOINTMENTS
|
||||
#### USING A WALKER WITH ONLY A RETURN CALLBACK
|
||||
$walker = Walker->new
|
||||
(
|
||||
$topNode,
|
||||
undef,
|
||||
[\&Callbacks::cbMakeMarks, $callbacks]
|
||||
);
|
||||
$walker->walk();
|
||||
|
||||
#### OUTPUT A SEPARATOR BETWEEN ORIGINAL AND CORRECTED CALENDARS
|
||||
for (my $n=0; $n<5; $n++)
|
||||
{
|
||||
print "######################################################\n";
|
||||
}
|
||||
|
||||
#### RE-WALK THE NODE TREE,
|
||||
#### RE-OUTPUTTING THE CALENDER
|
||||
$walker = Walker->new
|
||||
(
|
||||
$topNode, # start with this node
|
||||
[\&Callbacks::cbPrintNode, $callbacks] # do this on entry to each node
|
||||
);
|
||||
$walker->walk();
|
||||
}
|
||||
|
||||
main();
|
135
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_nodepath.pl
Executable file
135
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_nodepath.pl
Executable file
|
@ -0,0 +1,135 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
|
||||
#####################################################################
|
||||
# Node.pm is a tool you will probably use in many projects located
|
||||
# in varying directories. How do you enable those projects to
|
||||
# include Node.pm? Here are some ways:
|
||||
# 1. Place Node.pm in the project's directory
|
||||
# 2. Place Node.pm on Perl's module path
|
||||
# 3. Run the project as perl -I/path/to/Node project.pl
|
||||
# 4. Shebang line #!/usr/bin/perl -w -I/path/to/Node
|
||||
#
|
||||
# Number 1 can become problematic as the number of apps using Node.pm
|
||||
# increases. If you have 30 different copies in 30 different directories,
|
||||
# how do you keep them all up to date.
|
||||
#
|
||||
# Number 2 is a much better option. It works. However, which @INC
|
||||
# directory do you place it in? When you update Perl or your distribution,
|
||||
# it goes away.
|
||||
#
|
||||
# Number 3 is great, except you need to create a shellscript to call
|
||||
# Perl with your program as an argument. BE SURE not to leave a space
|
||||
# between the -I and the directory, or that space actually becomes
|
||||
# part of the directory.
|
||||
#
|
||||
# Number 4 is greater, because it doesn't require a shellscript. Once
|
||||
# again, no space between -I and the directory. In all cases where
|
||||
# you know what directory will contain Node.pm, number 4 is a great
|
||||
# alternative.
|
||||
#
|
||||
# But what if you don't know in advance what directory
|
||||
# will contain Node.pm? What if you're writing an application to be
|
||||
# run at varying locations with varying setups? What if, in addition,
|
||||
# you don't want the end user messing with the source code to change
|
||||
# the shebang line? In that case, you can actually place the path
|
||||
# to Node.pm in a configuration file. It takes several lines of code,
|
||||
# but it's certainly nice to be able to accommodate the user's
|
||||
# environment without requiring change to the source code.
|
||||
#
|
||||
# This exercise demonstrates how to set the Node.pm location from a
|
||||
# configuration file. Once again, if you're the sole user it might be
|
||||
# better to change the shebang line, but if you're distributing
|
||||
# your program like the autumn leaves, a configuration file is the
|
||||
# way to go.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
|
||||
#####################################################################
|
||||
# The loadNodeModule() subroutine is a complete substitute for:
|
||||
# use Node
|
||||
#
|
||||
# It includes:
|
||||
# require Node;
|
||||
# import Node;
|
||||
#
|
||||
# The preceding two calls completely replace a use Node statement,
|
||||
# and better still, unlike the use statement, they happen at
|
||||
# runtime instead of compile time. Therefore, this subroutine reads
|
||||
# the directory from a config file, then executes that directory
|
||||
# with the proper require and import statements. Obviously, the
|
||||
# loadNodeModule() subroutine must be executed before any code depending
|
||||
# on the Node.pm module is executed.
|
||||
#####################################################################
|
||||
sub loadNodeModule()
|
||||
{
|
||||
#### CHANGE THE FOLLOWING TO CHANGE THE DEFAULT APP FILENAME
|
||||
my $defaultConfFileName = "./myapp.cfg";
|
||||
|
||||
#### CHANGE THE FOLLOWING TO CHANGE APP FILENAME ENVIRONMENT VAR
|
||||
my $envVarName = "MY_APP_CONFIG";
|
||||
|
||||
my($conffile) = $ENV{$envVarName};
|
||||
print $conffile, "\n" if defined $conffile;
|
||||
$conffile = $defaultConfFileName unless defined($conffile);
|
||||
print "Using config file $conffile.\n";
|
||||
|
||||
open CONF, '<' . $conffile or die "FATAL ERROR: Could not open config file $conffile.";
|
||||
my @lines = <CONF>;
|
||||
close CONF;
|
||||
|
||||
my @nodedirs;
|
||||
foreach my $line (@lines)
|
||||
{
|
||||
chomp $line;
|
||||
if($line =~ m/^\s*nodedir\s*=\s*([^\s]*)/)
|
||||
{
|
||||
my $dir = $1;
|
||||
if($dir =~ m/(.*)\$HOME(.*)/)
|
||||
{
|
||||
$dir = $1 . $ENV{'HOME'} . $2;
|
||||
}
|
||||
push @nodedirs, ($dir);
|
||||
}
|
||||
}
|
||||
|
||||
if(@nodedirs)
|
||||
{
|
||||
unshift @INC, @nodedirs;
|
||||
}
|
||||
|
||||
require Node;
|
||||
import Node;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# The main() routine calls loadNodeModule to include Node.pm,
|
||||
# and then runs a few lines of code to conclusively prove that
|
||||
# Node.pm is loaded. It also prints out the @INC array to show that
|
||||
# directory in which Node.pm resides is now in the @INC path.
|
||||
#
|
||||
# Note that in the absense of any change to the environment variable
|
||||
# defined in loadNodeModule(), the configuration file will be ./myapp.cfg.
|
||||
#####################################################################
|
||||
sub main()
|
||||
{
|
||||
loadNodeModule();
|
||||
my $topNode = Node->new("myname", "mytype", "myvalue");
|
||||
print "\n::: ";
|
||||
print $topNode->getName(), " ::: ";
|
||||
print $topNode->getType(), " ::: ";
|
||||
print $topNode->getValue(), " :::\n";
|
||||
foreach my $line (@INC)
|
||||
{
|
||||
print $line, "\n";
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
123
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_otl2markup.pl
Executable file
123
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_otl2markup.pl
Executable file
|
@ -0,0 +1,123 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
#####################################################################
|
||||
# This exercise demonstrates use of the return callback routine. The
|
||||
# return callback routine occurs when node navigation returns to a
|
||||
# node from its children. Therefore, the return callback routine is
|
||||
# never executed by nodes without children.
|
||||
#
|
||||
# An obvious use of the return callback routine is to print end tags
|
||||
# for nested markup. A node's end tag must follow all markup for all
|
||||
# the node's children, so the return callback is perfect for that
|
||||
# purpose.
|
||||
#
|
||||
# Because childless nodes never execute the return callback routine,
|
||||
# in the case of childless nodes this program prints the end tags
|
||||
# from the entry callback routine.
|
||||
#
|
||||
# This program prints the attributes of each Node object. You'll
|
||||
# immediately note that the "children" attributes you set are printed.
|
||||
# But you'll also observe that a "_lineno" attribute has been set for
|
||||
# all nodes except the top one. That attribute was set by the Parser
|
||||
# object, and corresponds to the line in the parsed outline file. This
|
||||
# attribute is extremely helpful in printing error messages.
|
||||
#####################################################################
|
||||
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
|
||||
use Node; # Use Note.pm tool
|
||||
|
||||
package Callbacks;
|
||||
sub new()
|
||||
{
|
||||
my($type) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $type);
|
||||
$self->{'errors'} = 0;
|
||||
$self->{'warnings'} = 0;
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub getErrors(){return $_[0]->{'errors'};}
|
||||
sub getWarnings(){return $_[0]->{'warnings'};}
|
||||
|
||||
##############################################################
|
||||
# cbPrintTag is the entry callback, and is called on first
|
||||
# entry to each node. It prints the start tag and text. If
|
||||
# the node is a leaf level node, it also prints the end tag
|
||||
# on the same line.
|
||||
##############################################################
|
||||
sub cbPrintTag()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;}
|
||||
|
||||
#### PRINT START TAG AND CONTENT
|
||||
for(my $n = 0; $n < $level; $n++) {print "\t";}
|
||||
print "<node level=", $level, ">";
|
||||
print $checker->getValue() if $checker->hasValue();
|
||||
|
||||
#### IF THIS IS A LEAF LEVEL ITEM, PRINT THE
|
||||
#### END TAG IMMEDIATELY. OTHERWISE, THE
|
||||
#### RETURN CALLBACK WILL TAKE CARE OF THE END TAG.
|
||||
unless($checker->hasFirstChild())
|
||||
{
|
||||
print "</node>";
|
||||
}
|
||||
|
||||
#### PRINT NEWLINE
|
||||
print "\n";
|
||||
}
|
||||
|
||||
##############################################################
|
||||
# cbPrintEndTag is the return callback, and is called on reentry
|
||||
# to the node, after all its children have been processed.
|
||||
# It is not called by leaf level (childless) nodes. The purpose
|
||||
# of this routine is to print the end tag.
|
||||
#
|
||||
# For nodes with children, the end tag must be printed after
|
||||
# all information for the node's children has been printed,
|
||||
# in order to preserve proper nesting.
|
||||
##############################################################
|
||||
sub cbPrintEndTag()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;}
|
||||
|
||||
#### PRINT END TAG FOR PARENT
|
||||
for(my $n = 0; $n < $level; $n++) {print "\t";}
|
||||
print "</node>";
|
||||
print "\n";
|
||||
}
|
||||
|
||||
package Main;
|
||||
|
||||
sub main()
|
||||
{
|
||||
#### PARSE FROM FILE README.otl
|
||||
my $parser = OutlineParser->new();
|
||||
$parser->setCommentChar("#");
|
||||
$parser->fromFile();
|
||||
my $topNode=$parser->parse("README.otl");
|
||||
|
||||
#### INSTANTIATE THE Callbacks OBJECT
|
||||
my $callbacks = Callbacks->new();
|
||||
|
||||
#### WALK THE NODE TREE,
|
||||
#### OUTPUTTING LEVEL AND TEXT
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode, # start with this node
|
||||
[\&Callbacks::cbPrintTag, $callbacks], # do this on entry to each node
|
||||
[\&Callbacks::cbPrintEndTag, $callbacks]# do this on return from node's children
|
||||
);
|
||||
$walker->walk();
|
||||
}
|
||||
|
||||
main();
|
114
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_parse.pl
Executable file
114
pack/acp/start/vimoutliner/vimoutliner/scripts/Node/example_parse.pl
Executable file
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2004 by Steve Litt
|
||||
# Licensed with the GNU General Public License, Version 2
|
||||
# ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK
|
||||
# See http://www.gnu.org/licenses/gpl.txt
|
||||
|
||||
use strict; # prevent hard to find errors
|
||||
|
||||
use Node; # Use Node.pm tool
|
||||
|
||||
#####################################################################
|
||||
# This exercise demonstrates the most elemental use of Node.pm.
|
||||
# It does nothing more than read README.otl into a Node tree, and
|
||||
# then print the tree.
|
||||
#
|
||||
# Here's the high level logic:
|
||||
# Set up a Callback object to house the callback routines
|
||||
# Instantiate and configure a Parser object to parse README.otl
|
||||
# Instantiate a Walker object to walk the resulting node tree
|
||||
# Link Callbacks::cbPrintNode() as the Walker's entry callback
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
##############################################################
|
||||
# You need an object to house callback routines. The object can
|
||||
# be named anything, but it should have facilities to count up
|
||||
# errors and warnings. Its new() method should always be something
|
||||
# like what you see below, and there should have getErrors() and
|
||||
# getWarnings() methods.
|
||||
#
|
||||
# The cbPrintNode() method is typical of a simple callback routine.
|
||||
# All callback routines have exactly three arguments, $self,
|
||||
# $checker and $level. $self refers to the object containing
|
||||
# the callback routine, $checker is the node that called this
|
||||
# callback routine, and $level is the level of that node in the
|
||||
# hierarchy. Armed with these pieces of information, you can
|
||||
# perform almost any operation on the current node ($checker).
|
||||
#
|
||||
# The callback routines are called by the Parser object during
|
||||
# parsing. A callback routine can be called upon first entry
|
||||
# into a node, or it can be called upon reentry into that node
|
||||
# after processing all that node's children. The latter is
|
||||
# an excellent way of outputting end tags at the proper time.
|
||||
##############################################################
|
||||
package Callbacks;
|
||||
sub new()
|
||||
{
|
||||
my($type) = $_[0];
|
||||
my($self) = {};
|
||||
bless($self, $type);
|
||||
$self->{'errors'} = 0;
|
||||
$self->{'warnings'} = 0;
|
||||
return($self);
|
||||
}
|
||||
|
||||
sub getErrors(){return $_[0]->{'errors'};}
|
||||
sub getWarnings(){return $_[0]->{'warnings'};}
|
||||
|
||||
sub cbPrintNode()
|
||||
{
|
||||
my($self, $checker, $level) = @_;
|
||||
unless (defined($checker)) {return -999;} # don't process undef node
|
||||
print $level, " ::: "; # print the level
|
||||
print $checker->getValue(); # print the text of the node
|
||||
print "\n";
|
||||
}
|
||||
|
||||
package Main;
|
||||
|
||||
sub main()
|
||||
{
|
||||
#### PARSE FROM FILE README.otl
|
||||
my $parser = OutlineParser->new(); # instantiate parser
|
||||
$parser->setCommentChar("#"); # ignore lines starting with #
|
||||
$parser->fromFile(); # get input from file
|
||||
my $topNode=$parser->parse("README.otl");
|
||||
|
||||
#====================================================================
|
||||
# The preceding statement parses file README.otl into a node hierarchy
|
||||
# and assigns the top level node of that hierarchy to $topNode. When
|
||||
# you run the program you'll notice that the text in $topNode does
|
||||
# not appear in README.otl, but instead has value
|
||||
# "Inserted by OutlineParser".
|
||||
#
|
||||
# This is a feature, not a bug. In order to accommodate the typical
|
||||
# case of an outline having several top level items, and yet still
|
||||
# be able to represent the whole hierarchy as a single top node,
|
||||
# the OutlineParser object creates a new node with value
|
||||
# " Inserted by OutlineParser"
|
||||
# and places all the outline's top level items under that newly
|
||||
# created node.
|
||||
#
|
||||
# If the outline you're working on is guaranteed to have only
|
||||
# a single top level item, and if you want that to be the top
|
||||
# level node, you can simply do the following:
|
||||
#
|
||||
# $topNode=$topNode->getFirstChild();
|
||||
#====================================================================
|
||||
|
||||
#### INSTANTIATE THE Callbacks OBJECT
|
||||
my $callbacks = Callbacks->new();
|
||||
|
||||
#### WALK THE NODE TREE,
|
||||
#### OUTPUTTING LEVEL AND TEXT
|
||||
my $walker = Walker->new
|
||||
(
|
||||
$topNode, # start with this node
|
||||
[\&Callbacks::cbPrintNode, $callbacks] # do this on entry to each node
|
||||
);
|
||||
$walker->walk();
|
||||
}
|
||||
|
||||
main();
|
|
@ -0,0 +1,4 @@
|
|||
#### THIS FILE CONFIGURES example_nodepath.pl.
|
||||
#### IN ORDER TO USE example_nodepath.pl,
|
||||
#### CHANGE FOLLOWING PATH TO THE DIRECTORY WHERE YOU PLACED Node.pm ####
|
||||
nodedir=/path/to/nodemodule
|
7
pack/acp/start/vimoutliner/vimoutliner/scripts/fs2otl
Executable file
7
pack/acp/start/vimoutliner/vimoutliner/scripts/fs2otl
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
echo "$1"
|
||||
echo "$1" | perl -pe 's/./-/g;'
|
||||
cd "$1"
|
||||
find . \
|
||||
| sort \
|
||||
| perl -pe 's|^\./||; s|[^/]+/|\t|g; s/([^\t])/[_] $1/;'
|
284
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2aft.awk
Normal file
284
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2aft.awk
Normal file
|
@ -0,0 +1,284 @@
|
|||
# *Title: otl2aft
|
||||
# *Author: Todd Coram (http://maplefish.com/todd)
|
||||
# *TOC
|
||||
#
|
||||
# ~Version 1.3~
|
||||
#
|
||||
# ~This source is hereby placed into the Public Domain.~
|
||||
# ~What you do with it is your own business.~
|
||||
# ~Just please do no harm.~
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# * Introduction
|
||||
#
|
||||
# Otl2aft converts VimOutliner files into
|
||||
# [AFT (http://www.maplefish.com/todd/aft.html)] documents. This file
|
||||
# can be run with nawk, mawk or gawk.
|
||||
#
|
||||
# This tool was created upon the request/inspiration of David J Patrick
|
||||
#(of http://linuxcaffe.ca fame).
|
||||
#
|
||||
# You can downloaded the most up to date
|
||||
# source [here (http://www.maplefish.com/todd/otl2aft.awk)].
|
||||
# A PDF version of this file resides
|
||||
# [here (http://www.maplefish.com/todd/otl2aft.pdf)].
|
||||
#
|
||||
# AEY: Changed all # symbols within regular expressions to \043
|
||||
# to avoid problems with # being the comment character.
|
||||
#
|
||||
# * Code
|
||||
#
|
||||
# In the beginning we want to print out the AFT title and author.
|
||||
# We expect the otl file to contain two top level headlines. The first
|
||||
# will be used as the title and the second as the author.
|
||||
#
|
||||
# We also print out some control bits and a table of contents placeholder.
|
||||
#
|
||||
BEGIN {
|
||||
VERSION="v1.3 9/04/2009";
|
||||
# AEY: Note first line is now for OTL use only; we ignore it here.
|
||||
getline; # expect title
|
||||
print "#---SET-CONTROL tableparser=new"
|
||||
# AEY: Commented out following lines, since this info is now metadata.
|
||||
#print "*Title: " $0;
|
||||
#getline; # expect author
|
||||
#print "*Author: " $0;
|
||||
#print "\n*TOC\n"
|
||||
}
|
||||
|
||||
# AEY: > now starts an inline comment. We ignore these.
|
||||
/^[\t]+>/ {
|
||||
next;
|
||||
}
|
||||
|
||||
# AEY: < is now used for metadata. We only act on certain ones.
|
||||
#/^[\t]+<[ \t]*title:[ \t]*/ {
|
||||
/^[\t]+</ {
|
||||
# "Munch" off the first part, which we don't care about
|
||||
#sub(/^[\t]+<[ \t]*/,"");
|
||||
# If there's no colon, there won't be a tag, so we don't care.
|
||||
spec = rightpart($0,"<");
|
||||
if (match(spec,/:/)) {
|
||||
key = leftpart(spec,":");
|
||||
value = rightpart(spec,":");
|
||||
|
||||
if (key == "title") {
|
||||
print "*Title: " value;
|
||||
} else if (key == "author") {
|
||||
print "*Author: " value;
|
||||
} else if (key == "aft") {
|
||||
print value; # "aft:" is an all-purpose "aft"-code insertion tag
|
||||
}
|
||||
} else {
|
||||
if (spec == "toc") {
|
||||
print "*TOC";
|
||||
}
|
||||
}
|
||||
next;
|
||||
|
||||
}
|
||||
|
||||
# AEY: Any other metadata line starting with < is currently ignored.
|
||||
#/^[\t]+</ {
|
||||
# next;
|
||||
#}
|
||||
|
||||
# AEY: Stop processing after ---END--- line
|
||||
#/^---END---/ {
|
||||
/^\043--- END ---/ {
|
||||
exit;
|
||||
}
|
||||
|
||||
# AEY: If we find a VIM Outliner checkbox, get rid of it
|
||||
/\[[_X]\][ ]/ {
|
||||
gsub(/\[[_X]\][ ]/, "");
|
||||
}
|
||||
|
||||
# Scan for one or more tabs followed by a colon (:). This is the outliner's
|
||||
# markup for ''body text (wrapping)''.
|
||||
# If we are not nested inside a list (subheaders), then [reset] before doing
|
||||
# any work. This makes sure we properly terminatel tables and other modes.
|
||||
#
|
||||
# Our work here involves simply killing tabs and removing the colon.
|
||||
# We then continue reading the rest of the file.
|
||||
#
|
||||
/^[\t]+:/ {
|
||||
if (!list_level) reset();
|
||||
gsub(/\t/,"");
|
||||
sub(/[ ]*:/, "");
|
||||
# AEY: Need to handle bulleted and numbered lists too,
|
||||
# but not here. From our point of view, ": * " is now verboten.
|
||||
#sub(/^[\t ]*\*/,"\t*");
|
||||
#sub(/^[\t ]*\043\./,"\t#.");
|
||||
# End changes
|
||||
print $0; next;
|
||||
}
|
||||
|
||||
# AEY: Support for our own style of bulleted and numbered lists (experimental).
|
||||
/^[\t]+(\*|\043[\.\)])/ {
|
||||
if (!list_level) reset();
|
||||
gsub(/\t/,"");
|
||||
if (list_level || $0 ~ /[ ]*(\*|\043[\.\)])/) {
|
||||
handlelist();
|
||||
}
|
||||
print $0; next;
|
||||
}
|
||||
# AEY: * now handled like heading, but must add extra space to avoid confusing Aft
|
||||
#/^[\t]+\*/ {
|
||||
# gsub("*"," *");
|
||||
# # Continue on and handle as normal
|
||||
#}
|
||||
|
||||
# Scan for ''user defined text block (wrapping)''. If we get this, we
|
||||
# kill the tabs, remove the |>| and if we discover a crosshatch |#|, we
|
||||
# start a list. If we are already in a list, we continue the list. Both
|
||||
# starting and continuing is handled by [handlelist].
|
||||
#
|
||||
# AEY: Removed this
|
||||
#/^[\t]+>/ {
|
||||
# if (!list_level) reset();
|
||||
# gsub(/\t/,"");
|
||||
# sub(/>/, "");
|
||||
#
|
||||
# if (list_level || $0 ~ /[ ]*[\043*]/) {
|
||||
# handlelist();
|
||||
# }
|
||||
# print $0; next;
|
||||
#}
|
||||
|
||||
# Scan for |;| or |<| which indicate ''preformatted body text'' and
|
||||
# ''user-defined preformatted text block'' respectively. Both of these
|
||||
# are non wrapping but we ignore that (for now). We handle lists just like
|
||||
# the previous scan action.
|
||||
#
|
||||
# AEY: Removed < handling
|
||||
/^[\t]+;/ { # Handle ";" and "<" (preformated text)
|
||||
if (!list_level) reset();
|
||||
gsub(/\t/,"");
|
||||
sub(/;/, "");
|
||||
|
||||
if (list_level || $0 ~ /[ ]*\043/) { # Convert "< #" into numbered lists.
|
||||
handlelist();
|
||||
}
|
||||
print $0; next;
|
||||
}
|
||||
|
||||
# Scan for a table. This is tricky. We want to cast the Outliner table
|
||||
# into the AFT ''new table'' format. AFT tables (especially as rendered
|
||||
# by LaTeX) really want to have captions/headers. We fake that for now
|
||||
# by using a |-| place holder. This should be fixed!
|
||||
#
|
||||
/^[\t]+\|/ {
|
||||
if (!in_table) reset();
|
||||
in_table = 1
|
||||
gsub(/\t/,"");
|
||||
if ($1 ~ /\|\|/) {
|
||||
print "\t! _ !";
|
||||
print "\t!----------!"
|
||||
}
|
||||
gsub(/\|\|/,"!");
|
||||
gsub(/\|/,"!");
|
||||
print "\t"$0
|
||||
print "\t!----------!"
|
||||
next;
|
||||
}
|
||||
|
||||
# The default scan matches anything not matching the above scan. We simply
|
||||
# go through and set the known indent level based on the number of tabs
|
||||
# seen.
|
||||
#
|
||||
{ match($0,/^[\t]+/); indent = RLENGTH; if (indent == -1) indent = 0; }
|
||||
|
||||
# Given the iden level set by the default scan (above), we now determine
|
||||
# what type of AFT output to do.
|
||||
#
|
||||
# Indent levels lower than 7 are represented directly
|
||||
# using AFT sections.
|
||||
#
|
||||
# AEY: Added $0 = "*"$0; back in to ensure top-level headings remain headings!
|
||||
# (This existed in earlier versions, but not in version 1.3.)
|
||||
#indent < 7 { gsub(/\t/,"*"); print "";}
|
||||
indent < 7 { gsub(/\t/,"*"); $0 = "*"$0; print "";}
|
||||
|
||||
# Indent levels greater than 6 are represented by AFT bullet lists.
|
||||
# This is done by first killing some tabs (we don't want to start off
|
||||
# nesting too deeply), and using the remaining tabs to adjust to the
|
||||
# appropriate list nesting level.
|
||||
#
|
||||
indent > 6 {
|
||||
gsub(/\t\t\t/, "");
|
||||
match($0,/^[\t]+/);
|
||||
remtabs = substr($0,RSTART,RLENGTH);
|
||||
text = substr($0,RSTART+RLENGTH);
|
||||
$0 = remtabs"* "text;
|
||||
print "";
|
||||
}
|
||||
|
||||
# After adjusting indentation, just print out the line.
|
||||
#
|
||||
{ print $0 }
|
||||
|
||||
# **handlelist
|
||||
# Look at the indentation and produce lists accordingly.
|
||||
#
|
||||
function handlelist() {
|
||||
if (!list_level) {
|
||||
list_indent = length(indent) + 1;
|
||||
}
|
||||
list_level = list_indent - length(indent);
|
||||
|
||||
if ($0 ~ /[ ]*\043/) { # Convert " #" into numbered lists.
|
||||
for (i=0; i < list_level; i++)
|
||||
printf("\t");
|
||||
gsub(/[ ]*\\043/,"#.");
|
||||
} else if ($0 ~ /[ ]*\*/) { # Convert " *" into bullet lists.
|
||||
for (i=0; i < list_level; i++)
|
||||
printf("\t");
|
||||
gsub(/[ ]*\*/,"*");
|
||||
} else if (list_level) {
|
||||
for (i=0; i < list_level; i++)
|
||||
printf("\t");
|
||||
}
|
||||
}
|
||||
|
||||
# **reset
|
||||
# Reset various parameters to get us out of various modes.
|
||||
#
|
||||
function reset() {
|
||||
if (list_level) {
|
||||
print " ";
|
||||
list_level = 0;
|
||||
}
|
||||
if (in_table) {
|
||||
print "\t!----------!\n"
|
||||
in_table = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# AEY: "Trim" function, added for sanity's sake.
|
||||
function trim(str) {
|
||||
sub(/^[ \t]*/,"",str);
|
||||
sub(/[ \t]*$/,"",str);
|
||||
return str;
|
||||
}
|
||||
|
||||
# AEY: Get everything to left of specified regex, and trim it too.
|
||||
function leftpart(str,regex) {
|
||||
if (match(str,regex)) {
|
||||
return trim(substr(str,1,RSTART-1));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
# AEY: Get everything to right of specified regex, and trim it too.
|
||||
function rightpart(str,regex) {
|
||||
if (match(str,regex)) {
|
||||
return trim(substr(str,RSTART+RLENGTH));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
# That's all folks!
|
BIN
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2aft.pdf
Normal file
BIN
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2aft.pdf
Normal file
Binary file not shown.
270
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2docbook.pl
Executable file
270
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2docbook.pl
Executable file
|
@ -0,0 +1,270 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use XML::Writer;
|
||||
use vars qw($writer $section_has_contents $VERSION);
|
||||
|
||||
use constant DEBUG => 0;
|
||||
|
||||
$VERSION = '2.0';
|
||||
|
||||
sub debug {
|
||||
if ( DEBUG )
|
||||
{
|
||||
print STDERR @_;
|
||||
}
|
||||
}
|
||||
|
||||
sub start_docbook {
|
||||
$writer = XML::Writer->new(DATA_MODE => 1,
|
||||
DATA_INDENT => 1);
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "starting new docbook\n");
|
||||
|
||||
$writer->xmlDecl();
|
||||
|
||||
# my $system = '/usr/share/sgml/docbook/xml-dtd-4.1/docbookx.dtd';
|
||||
my $system = 'http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd';
|
||||
|
||||
$writer->doctype('article',
|
||||
'-//OASIS//DTD DocBook XML V4.1//EN',
|
||||
$system);
|
||||
}
|
||||
|
||||
sub start_article {
|
||||
my $id = shift;
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "starting new article\n");
|
||||
|
||||
my @attributes = (
|
||||
'class' => 'whitepaper',
|
||||
);
|
||||
|
||||
if ( $id )
|
||||
{
|
||||
push @attributes, ( 'id' => $id );
|
||||
}
|
||||
|
||||
$writer->startTag('article', @attributes);
|
||||
}
|
||||
|
||||
sub start_section {
|
||||
my $title = shift;
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "starting new section\n");
|
||||
|
||||
$writer->startTag('section');
|
||||
|
||||
$section_has_contents = 0;
|
||||
|
||||
if ( $title )
|
||||
{
|
||||
$writer->dataElement('title', $title);
|
||||
}
|
||||
}
|
||||
|
||||
sub start_list {
|
||||
debug(' 'x$writer->getDataIndent(), "starting new list\n");
|
||||
|
||||
$writer->startTag('itemizedlist');
|
||||
}
|
||||
|
||||
sub append_list_item {
|
||||
my $text = shift;
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "starting new listitem\n");
|
||||
|
||||
$writer->startTag('listitem');
|
||||
|
||||
$writer->dataElement('para', $text);
|
||||
|
||||
$writer->endTag('listitem');
|
||||
}
|
||||
|
||||
sub end_list {
|
||||
$writer->endTag('itemizedlist');
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "ending list\n");
|
||||
}
|
||||
|
||||
sub append_code {
|
||||
my $code = shift;
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "starting new programlisting\n");
|
||||
|
||||
$section_has_contents = 1;
|
||||
|
||||
$writer->dataElement('programlisting', $code, role=>'C');
|
||||
}
|
||||
|
||||
sub append_para {
|
||||
my $text = shift;
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "starting new para\n");
|
||||
|
||||
$section_has_contents = 1;
|
||||
|
||||
$writer->dataElement('para', $text);
|
||||
}
|
||||
|
||||
sub end_section {
|
||||
if ( ! $section_has_contents )
|
||||
{
|
||||
$writer->emptyTag('para');
|
||||
$section_has_contents = 1;
|
||||
}
|
||||
|
||||
$writer->endTag('section');
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "ending section\n");
|
||||
}
|
||||
|
||||
sub end_article {
|
||||
$writer->endTag('article');
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "ending article\n");
|
||||
}
|
||||
|
||||
sub end_docbook {
|
||||
$writer->end();
|
||||
|
||||
debug(' 'x$writer->getDataIndent(), "ending docbook\n");
|
||||
}
|
||||
|
||||
####################################################
|
||||
|
||||
start_docbook();
|
||||
start_article();
|
||||
|
||||
my $section_level = 0;
|
||||
my $line;
|
||||
my $para = '';
|
||||
my $list_mode = 0;
|
||||
my $code_mode = 0;
|
||||
my $first_line = 1;
|
||||
|
||||
sub list_done {
|
||||
if ( $list_mode ) {
|
||||
end_list();
|
||||
$list_mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub para_done {
|
||||
if ( $para )
|
||||
{
|
||||
chomp $para;
|
||||
if ( $code_mode )
|
||||
{
|
||||
append_code($para);
|
||||
$code_mode = 0;
|
||||
}
|
||||
elsif ( $list_mode )
|
||||
{
|
||||
append_list_item($para);
|
||||
}
|
||||
else
|
||||
{
|
||||
append_para($para);
|
||||
}
|
||||
}
|
||||
$para = '';
|
||||
}
|
||||
|
||||
while ( defined ($line = <>) )
|
||||
{
|
||||
if ( $first_line and $line =~ /^-\*-/ )
|
||||
{
|
||||
next;
|
||||
}
|
||||
$first_line = 0;
|
||||
|
||||
if ( $line =~ /^\t*\* (.*)/ )
|
||||
{
|
||||
para_done();
|
||||
|
||||
$para = $1;
|
||||
|
||||
if ( ! $list_mode )
|
||||
{
|
||||
start_list();
|
||||
$list_mode = 1;
|
||||
}
|
||||
|
||||
next;
|
||||
}
|
||||
|
||||
if ( $line =~ /^\t*[^\t: ]/ )
|
||||
{
|
||||
para_done();
|
||||
list_done();
|
||||
}
|
||||
|
||||
if ( $line =~ /^(\t*)([^\t\n: ].*)/ )
|
||||
{
|
||||
my $title = $2;
|
||||
my $new_section_level = length($1) + 1;
|
||||
|
||||
para_done();
|
||||
list_done();
|
||||
|
||||
for ( my $i = 0 ; $section_level - $new_section_level >= $i ; $i++ )
|
||||
{
|
||||
end_section();
|
||||
}
|
||||
|
||||
chomp $title;
|
||||
start_section($title);
|
||||
|
||||
$section_level = $new_section_level;
|
||||
next;
|
||||
}
|
||||
|
||||
# Code mode not supported yet
|
||||
# if ( ! $list_mode and $line =~ /^\s+/ )
|
||||
# {
|
||||
# debug("enabling code mode\n");
|
||||
# $code_mode = 1;
|
||||
# }
|
||||
|
||||
$line =~ s/^\t*(\: ?| )//;
|
||||
if ($line =~ /^$/) {
|
||||
para_done();
|
||||
list_done();
|
||||
next;
|
||||
}
|
||||
$para .= $line;
|
||||
}
|
||||
para_done();
|
||||
|
||||
for ( my $i = 0 ; $section_level > $i ; $i++ )
|
||||
{
|
||||
end_section();
|
||||
}
|
||||
|
||||
end_article();
|
||||
end_docbook();
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
outline2dockbook - Generate DocBook XML from VimOutliner outline
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
outline2docbook < input > output
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<outline2docbook> reads an VimOutliner outline-mode type text file on
|
||||
standard input and outputs DocBook XML on standard output.
|
||||
|
||||
The original version was written by Thomas R. Fullhart to convert from Emacs
|
||||
outline mode. It is available at
|
||||
http://genetikayos.com/code/repos/outline2docbook/distribution/.
|
||||
|
||||
This program uses the B<XML::Writer> perl module, which is available
|
||||
on B<CPAN>.
|
||||
|
||||
=cut
|
1111
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2html.py
Executable file
1111
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2html.py
Executable file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,269 @@
|
|||
/* copyright notice and filename */
|
||||
body {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
/* title at the top of the page */
|
||||
H1 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 14pt;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: black;
|
||||
background-color: #ddddee;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
H2 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
H3 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
H4 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
H5 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
/* outline level spacing */
|
||||
OL {
|
||||
padding-bottom: 8pt;
|
||||
counter-reset: section;
|
||||
margin-left: 1.0em;
|
||||
padding-left:0 ;
|
||||
}
|
||||
OL LI { counter-increment: section; }
|
||||
OL LI:before { content: counters(section, ".") ". "; }
|
||||
/* global heading settings */
|
||||
LI {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
color: black;
|
||||
font-weight: normal;
|
||||
list-style: lower-alpha;
|
||||
padding-top: 4px;
|
||||
}
|
||||
/* level 1 heading overrides */
|
||||
LI.L1 {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 2 heading overrides */
|
||||
LI.L2 {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 3 heading overrides */
|
||||
LI.L3 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 4 heading overrides */
|
||||
LI.L4 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 5 heading overrides */
|
||||
LI.L5 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 6 heading overrides */
|
||||
LI.L6 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 7 heading overrides */
|
||||
LI.L7 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 8 heading overrides */
|
||||
LI.L8 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 9 heading overrides */
|
||||
LI.L9 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 10 heading overrides */
|
||||
LI.L10 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 11 heading overrides */
|
||||
LI.L11 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 1 bullet heading overrides */
|
||||
LI.LB1 {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 2 bullet heading overrides */
|
||||
LI.LB2 {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 3 bullet heading overrides */
|
||||
LI.LB3 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 4 bullet heading overrides */
|
||||
LI.LB4 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 5 bullet heading overrides */
|
||||
LI.LB5 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 6 bullet heading overrides */
|
||||
LI.LB6 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 7 bullet heading overrides */
|
||||
LI.LB7 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 1 numeric heading overrides */
|
||||
LI.LN1 {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 2 numeric heading overrides */
|
||||
LI.LN2 {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 3 numeric heading overrides */
|
||||
LI.LN3 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 4 numeric heading overrides */
|
||||
LI.LN4 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 5 numeric heading overrides */
|
||||
LI.LN5 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 6 numeric heading overrides */
|
||||
LI.LN6 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 7 numeric heading overrides */
|
||||
LI.LN7 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* body text */
|
||||
P {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 9pt;
|
||||
font-weight: normal;
|
||||
color: black;
|
||||
}
|
||||
/* preformatted text */
|
||||
PRE {
|
||||
font-family: fixed,monospace;
|
||||
font-size: 9pt;
|
||||
font-weight: normal;
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
TABLE {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
TH {
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
background-color: #eeddee;
|
||||
}
|
||||
|
||||
TD {
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
background-color: #ddeeee;
|
||||
}
|
||||
|
||||
CODE {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
TABLE.TAB1 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB2 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 11pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB3 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB4 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB5 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB6 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
|
@ -0,0 +1,246 @@
|
|||
/* copyright notice and filename */
|
||||
body {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
/* title at the top of the page */
|
||||
H1 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 14pt;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: black;
|
||||
background-color: #ddddee;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
H2 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
H3 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
H4 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
H5 {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
text-align: left;
|
||||
color: black;
|
||||
}
|
||||
/* outline level spacing */
|
||||
OL {
|
||||
margin-left: 1.0em;
|
||||
padding-left: 0;
|
||||
padding-bottom: 8pt;
|
||||
}
|
||||
/* global heading settings */
|
||||
LI {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
color: black;
|
||||
font-weight: normal;
|
||||
list-style: lower-alpha;
|
||||
padding-top: 4px;
|
||||
}
|
||||
/* level 1 heading overrides */
|
||||
LI.L1 {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 2 heading overrides */
|
||||
LI.L2 {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 3 heading overrides */
|
||||
LI.L3 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 4 heading overrides */
|
||||
LI.L4 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 5 heading overrides */
|
||||
LI.L5 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 6 heading overrides */
|
||||
LI.L6 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 7 heading overrides */
|
||||
LI.L7 {
|
||||
font-size: 10pt;
|
||||
list-style: none;
|
||||
}
|
||||
/* level 1 bullet heading overrides */
|
||||
LI.LB1 {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 2 bullet heading overrides */
|
||||
LI.LB2 {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 3 bullet heading overrides */
|
||||
LI.LB3 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 4 bullet heading overrides */
|
||||
LI.LB4 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 5 bullet heading overrides */
|
||||
LI.LB5 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 6 bullet heading overrides */
|
||||
LI.LB6 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 7 bullet heading overrides */
|
||||
LI.LB7 {
|
||||
font-size: 10pt;
|
||||
list-style: disc;
|
||||
}
|
||||
/* level 1 numeric heading overrides */
|
||||
LI.LN1 {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 2 numeric heading overrides */
|
||||
LI.LN2 {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 3 numeric heading overrides */
|
||||
LI.LN3 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 4 numeric heading overrides */
|
||||
LI.LN4 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 5 numeric heading overrides */
|
||||
LI.LN5 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 6 numeric heading overrides */
|
||||
LI.LN6 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* level 7 numeric heading overrides */
|
||||
LI.LN7 {
|
||||
font-size: 10pt;
|
||||
list-style: decimal;
|
||||
}
|
||||
/* body text */
|
||||
P {
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 9pt;
|
||||
font-weight: normal;
|
||||
color: darkgreen;
|
||||
}
|
||||
/* preformatted text */
|
||||
PRE {
|
||||
font-family: fixed,monospace;
|
||||
font-size: 9pt;
|
||||
font-weight: normal;
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
TABLE {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
TH {
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
background-color: #eeddee;
|
||||
}
|
||||
|
||||
TD {
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
background-color: #ddeeee;
|
||||
}
|
||||
|
||||
CODE {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
TABLE.TAB1 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 12pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB2 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 11pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB3 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB4 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB5 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
TABLE.TAB6 {
|
||||
margin-top: 1em;
|
||||
font-family: helvetica,arial,sans-serif;
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
border-collapse: collapse;
|
|
@ -0,0 +1,44 @@
|
|||
" local .vimrc for working with otl2latex
|
||||
"
|
||||
" Used to write notes in vim outlier file (.otl) and have dynamically
|
||||
" generated beamer-latex files produced.
|
||||
"
|
||||
" requires the script otl2latex.py is in the same directory as this script.
|
||||
" also requires that your user ~/.vimrc file has "set exrc" specified
|
||||
"
|
||||
" This can be added to as more functionality is desired.
|
||||
"
|
||||
" Author: Serge Rey <sjsrey@gmail.com>
|
||||
" Last Revision: 2007-01-21
|
||||
|
||||
version 6.0
|
||||
|
||||
"get rid of blank lines
|
||||
map ,n :g/^$/d
|
||||
|
||||
"make the next paragraph a text block (in Vim Outliner terms)
|
||||
map ,t ma}k^mb'a'bI|
|
||||
|
||||
"make an itemized list out of the following contiguous lines (each line is an
|
||||
"item)
|
||||
map ,i ^ma}k^mb'a'bI\item 'aObegin{itemize}'aki\'bo\end{itemize}
|
||||
|
||||
"make an itemized list out of the following contiguous lines (each line is an
|
||||
"item) and then mark block as otl text
|
||||
map ,I ^ma}k^mb'a'bI\item 'aObegin{itemize}'aki\'bo\end{itemize}'akma}k^mb'a'bI|
|
||||
|
||||
map ,f ^Obegin{center}jo\end{center}k^i\includegraphics[width=.8\linewidth]{A}k^i\^jjmbkk'bI|
|
||||
|
||||
"process the otl file to produce a pdf presentation
|
||||
map ,b :!python otl2latex.py -p % %<.tex;pdflatex %<.tex
|
||||
|
||||
"pdflatex the current buffer
|
||||
map ,p :!pdflatex %
|
||||
|
||||
"set up menus
|
||||
amenu o&2l.&process<Tab>,b ,b
|
||||
amenu o&2l.&delete\ blank\ lines<Tab>,n ,n
|
||||
amenu o2l.-Sep- :
|
||||
amenu o&2l.&itemize<Tab>,i ,i
|
||||
amenu o&2l.&textualize<Tab>,t ,t
|
||||
amenu o&2l.&itemize_and_textualize<Tab>,t ,I
|
|
@ -0,0 +1,23 @@
|
|||
otl2latex
|
||||
|
||||
Translate a Vim Outliner file to a LaTeX document.
|
||||
|
||||
Author: Serge Rey <sjsrey@gmail.com>
|
||||
Version 0.1 (2007-01-21)
|
||||
|
||||
REQUIREMENTS
|
||||
The Vim Outliner http://bike-nomad.com/vim/vimoutliner.html
|
||||
beamer http://latex-beamer.sourceforge.net/
|
||||
Python http://www.python.org
|
||||
|
||||
|
||||
INSTRUCTIONS
|
||||
The user's guide is in otl2latex.pdf
|
||||
|
||||
To reproduce it:
|
||||
python otl2latex.py -p otl2latex.otl otl2latex.tex
|
||||
pdflatex otl2latex
|
||||
|
||||
DEVELOPMENT
|
||||
otl2latex development is hosted at:
|
||||
http://http://code.google.com/p/otl2latex/
|
|
@ -0,0 +1,95 @@
|
|||
preamble
|
||||
@author Serge Rey
|
||||
@institute sjsrey@gmail.com
|
||||
@instituteShort sjsrey@gmail.com
|
||||
@title otl2latex
|
||||
@subtitle User's Guide
|
||||
@titleShort http://code.google.com/p/otl2latex/
|
||||
@date November 3, 2007
|
||||
@dateShort otl2latex
|
||||
Introduction
|
||||
What is otl2latex?
|
||||
Translator
|
||||
otl to tex
|
||||
|otl2latex allows you to
|
||||
|* prepare your document in a powerful outliner
|
||||
|* generate \LaTeX\ markup of your content
|
||||
Requirements
|
||||
Operating Systems
|
||||
Operating Systems Supported
|
||||
|otl2latex has been used successfully on
|
||||
|* Linux
|
||||
|* Mac OS X
|
||||
|* Windows
|
||||
Software Required
|
||||
Packages and Programs
|
||||
|* Python http://www.python.org
|
||||
|* \LaTeX
|
||||
|* Beamer http://latex-beamer.sourceforge.net/
|
||||
|* The Vim Outliner http://bike-nomad.com/vim/vimoutliner.html
|
||||
Usage
|
||||
Basics
|
||||
Usage
|
||||
From the command line
|
||||
| \texttt{python otl2latex.py -p filename.otl filename.tex}
|
||||
|
|
||||
Notes
|
||||
|* \texttt{filename.tex} will be generated, you don't edit that one.
|
||||
|* You can run all this from withing Vim (see Vim Mappings below).
|
||||
Basics
|
||||
Presentations/Beamer
|
||||
|* Level 1 in the outline become sections
|
||||
|* Level 2 in the outline become subsections
|
||||
|* Level 3 in the outline become frame titles
|
||||
|* Level 4 in the outline become block titles
|
||||
|* Text in the outline is treated as \LaTeX\ markup
|
||||
Using Bullets
|
||||
| Placing a '*' at the begining of a line will tell otl2latex to begin an itemize list. otl2latex currently supports 3 levels of Itemization.
|
||||
|* First Level
|
||||
|** Second Level
|
||||
|*** Third Level
|
||||
|** Second Level
|
||||
Advanced
|
||||
Tips
|
||||
|* Level 4 can be omitted
|
||||
|* You will have no blocks on that frame
|
||||
Vim mappings
|
||||
Vim Mappings: .vimrc
|
||||
Processing
|
||||
|* ,b will generate a pdf file from your outline
|
||||
|* ,nb will remove all empty lines in your otl file
|
||||
|* ,p will run the current vim buffer through pdflatex
|
||||
Vim Mappings: .vimrc
|
||||
Lists
|
||||
|* ,i on the first line will create an itemized list of a block of lines
|
||||
|* ,t will mark a block as otl text
|
||||
|* ,I itemize and mark block as otl text
|
||||
|You need to have a blank line at the end of the block to apply these.
|
||||
Vim Mappings: .vimrc
|
||||
Figures
|
||||
|\begin{itemize}
|
||||
|\item ,f (insert mode) will generate stub for figures
|
||||
|\end{itemize}
|
||||
A figure
|
||||
| \begin{center}
|
||||
| \includegraphics[width=.8\linewidth]{otl2latex.png}
|
||||
| \end{center}
|
||||
A figure
|
||||
|\begin{center}
|
||||
|\includegraphics[width=.8\linewidth]{otl2latex.png}
|
||||
|\end{center}
|
||||
Future Extensions
|
||||
Move to vim script
|
||||
.vimrc to otl2latex.vim
|
||||
|\begin{itemize}
|
||||
|\item Currently we are just embedding mappings in .vimrc
|
||||
|\item Ok for testing, not very polished for end user
|
||||
|\end{itemize}
|
||||
Reverse Engineering
|
||||
latex2otl
|
||||
|\begin{itemize}
|
||||
|\item take a tex file
|
||||
|\item generate the otl file
|
||||
|\end{itemize}
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
315
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2latex/otl2latex.py
Executable file
315
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2latex/otl2latex.py
Executable file
|
@ -0,0 +1,315 @@
|
|||
usage="""
|
||||
otl2latex.py
|
||||
|
||||
Translate a Vim Outliner file to a LaTeX document.
|
||||
|
||||
|
||||
Usage:
|
||||
otl2latex.py -[abp] file.otl [file.tex]
|
||||
|
||||
-a: Output to article class
|
||||
-b: Output to book class
|
||||
-p: Output to Beamer (presentation) class (default)
|
||||
|
||||
|
||||
Author: Serge Rey <sjsrey@gmail.com>
|
||||
Version 0.1 (2007-01-21)
|
||||
"""
|
||||
|
||||
import os,sys
|
||||
|
||||
class Line:
|
||||
"""Class for markup lines"""
|
||||
def __init__(self, content):
|
||||
ntabs=content.count("\t")
|
||||
content=content.lstrip("\t")
|
||||
level = ntabs - content.count("\t")
|
||||
self.level=level
|
||||
self.content = content
|
||||
self.markup=0
|
||||
if content[0]=="|":
|
||||
self.markup=1
|
||||
|
||||
#3 lines added here
|
||||
self.bullet=0
|
||||
if len(content) > 2 and (content[2]=='*' or content[1]=='*'):
|
||||
self.bullet=1
|
||||
#print "%d: %s"%(self.bullet,content)
|
||||
|
||||
class Manager:
|
||||
"""Abstract class for LaTeX document classes"""
|
||||
def __init__(self, content, fileOut):
|
||||
self.content=content
|
||||
self.fileOut=open(fileOut,'w')
|
||||
self.parse()
|
||||
self.fileOut.write(self.markup)
|
||||
self.fileOut.close()
|
||||
def parse(self):
|
||||
self.lines=[ Line(line) for line in self.content]
|
||||
preambleStart=0
|
||||
nl=len(self.lines)
|
||||
id=zip(range(nl),self.lines)
|
||||
level1=[i for i,line in id if line.level==0]
|
||||
preambleEnd=level1[1]
|
||||
preamble=self.lines[0:preambleEnd]
|
||||
self.level1=level1
|
||||
preambleMarkup=[]
|
||||
for line in preamble:
|
||||
if line.content.count("@"):
|
||||
tmp=line.content.split("@")[1]
|
||||
tmp=tmp.split()
|
||||
env=tmp[0]
|
||||
content=" ".join(tmp[1:])
|
||||
mu="\\%s{%s}"%(env,content)
|
||||
preambleMarkup.append(mu)
|
||||
self.preamble=preambleMarkup
|
||||
self.preambleLines=preamble
|
||||
self.documentLines=self.lines[preambleEnd:]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Beamer(Manager):
|
||||
"""Manager for Beamer document class"""
|
||||
def __init__(self, content,fileOut):
|
||||
self.top1="""
|
||||
\documentclass[nototal,handout]{beamer}
|
||||
\mode<presentation>
|
||||
{
|
||||
\usetheme{Madrid}
|
||||
\setbeamercovered{transparent}
|
||||
}
|
||||
|
||||
\usepackage{verbatim}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage[latin1]{inputenc}
|
||||
\usepackage{times}
|
||||
\usepackage{tikz}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{graphicx} %sjr added
|
||||
\graphicspath{{figures/}}
|
||||
\usepackage{hyperref}"""
|
||||
self.top2="""
|
||||
% Delete this, if you do not want the table of contents to pop up at
|
||||
% the beginning of each subsection:
|
||||
\AtBeginSubsection[]
|
||||
{
|
||||
\\begin{frame}<beamer>
|
||||
\\frametitle{Outline}
|
||||
\\tableofcontents[currentsection,currentsubsection]
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
|
||||
% If you wish to uncover everything in a step-wise fashion, uncomment
|
||||
% the following command:
|
||||
\\beamerdefaultoverlayspecification{<+->}
|
||||
\\begin{document}
|
||||
\\begin{frame}
|
||||
\\titlepage
|
||||
\end{frame}
|
||||
\\begin{frame}
|
||||
\\frametitle{Outline}
|
||||
\\tableofcontents[pausesections]
|
||||
% You might wish to add the option [pausesections]
|
||||
\end{frame}
|
||||
"""
|
||||
self.bulletLevel = 0
|
||||
Manager.__init__(self, content, fileOut)
|
||||
|
||||
def itemize(self,line):
|
||||
nstars=line.content.count("*")
|
||||
content=line.content.lstrip("|").lstrip().lstrip("*")
|
||||
self.currentBLevel = nstars - content.count("*")
|
||||
stuff=[]
|
||||
if self.currentBLevel == self.bulletLevel and line.bullet:
|
||||
mu='\\item '+line.content.lstrip("|").lstrip().lstrip("*")
|
||||
elif line.bullet and self.currentBLevel > self.bulletLevel:
|
||||
self.bulletLevel += 1
|
||||
stuff.append("\\begin{itemize}\n")
|
||||
mu='\\item '+line.content.lstrip("|").lstrip().lstrip("*")
|
||||
elif self.currentBLevel < self.bulletLevel and line.bullet:
|
||||
self.bulletLevel -= 1
|
||||
stuff.append("\\end{itemize}\n")
|
||||
mu='\\item '+line.content.lstrip("|").lstrip().lstrip("*")
|
||||
elif self.currentBLevel < self.bulletLevel:
|
||||
self.bulletLevel -= 1
|
||||
stuff.append("\\end{itemize}\n")
|
||||
mu=line.content.lstrip("|")
|
||||
else:
|
||||
panic()
|
||||
return stuff,mu
|
||||
|
||||
def parse(self):
|
||||
Manager.parse(self)
|
||||
#print self.content
|
||||
#print self.lines
|
||||
#print self.level1
|
||||
#for info in self.preamble:
|
||||
# print info
|
||||
|
||||
# do my own preamble
|
||||
field=("author ","instituteShort ","dateShort ","date ","subtitle ",
|
||||
"title ", "institute ", "titleShort ")
|
||||
pattern=["@"+token for token in field]
|
||||
f=zip(field,pattern)
|
||||
d={}
|
||||
for field,pattern in f:
|
||||
t=[line.content for line in self.preambleLines if line.content.count(pattern)]
|
||||
if t:
|
||||
d[field]= t[0].split(pattern)[1].strip()
|
||||
else:
|
||||
d[field]=""
|
||||
preamble="\n\n\\author{%s}\n"%d['author ']
|
||||
preamble+="\\institute[%s]{%s}\n"%(d['instituteShort '],d['institute '])
|
||||
preamble+="\\title[%s]{%s}\n"%(d['titleShort '],d['title '])
|
||||
preamble+="\\subtitle{%s}\n"%(d['subtitle '])
|
||||
preamble+="\\date[%s]{%s}\n"%(d['dateShort '],d['date '])
|
||||
|
||||
print self.preamble
|
||||
self.preamble=preamble
|
||||
|
||||
|
||||
body=[]
|
||||
prev=0
|
||||
frameOpen=0
|
||||
blockOpen=0
|
||||
frameCount=0
|
||||
blockCount=0
|
||||
|
||||
for line in self.documentLines:
|
||||
if line.level==0:
|
||||
for i in range(0,self.bulletLevel):
|
||||
self.bulletLevel -= 1
|
||||
body.append("\\end{itemize}\n")
|
||||
if blockOpen:
|
||||
body.append("\\end{block}")
|
||||
blockOpen=0
|
||||
if frameOpen:
|
||||
body.append("\\end{frame}")
|
||||
frameOpen=0
|
||||
mu="\n\n\n\\section{%s}"%line.content.strip()
|
||||
elif line.level==1:
|
||||
for i in range(0,self.bulletLevel):
|
||||
self.bulletLevel -= 1
|
||||
body.append("\\end{itemize}\n")
|
||||
if blockOpen:
|
||||
body.append("\\end{block}")
|
||||
blockOpen=0
|
||||
if frameOpen:
|
||||
body.append("\\end{frame}")
|
||||
frameOpen=0
|
||||
mu="\n\n\\subsection{%s}"%line.content.strip()
|
||||
elif line.level==2:
|
||||
# check if this frame has blocks or is nonblocked
|
||||
if line.markup:
|
||||
if line.bullet or self.bulletLevel:
|
||||
stuff,mu=self.itemize(line)
|
||||
if len(stuff) > 0:
|
||||
for i in stuff:
|
||||
body.append(i)
|
||||
else:
|
||||
mu=line.content.lstrip("|")
|
||||
else:
|
||||
for i in range(0,self.bulletLevel):
|
||||
self.bulletLevel -= 1
|
||||
body.append("\\end{itemize}\n")
|
||||
if blockOpen:
|
||||
body.append("\\end{block}")
|
||||
blockOpen=0
|
||||
if frameOpen:
|
||||
body.append("\\end{frame}")
|
||||
else:
|
||||
frameOpen=1
|
||||
# check for verbatim here
|
||||
tmp=line.content.strip()
|
||||
if tmp.count("@vb"):
|
||||
tmp=tmp.split("@")[0]
|
||||
mu="\n\n\\begin{frame}[containsverbatim]\n\t\\frametitle{%s}\n"%tmp
|
||||
else:
|
||||
mu="\n\n\\begin{frame}\n\t\\frametitle{%s}\n"%tmp
|
||||
frameCount+=1
|
||||
elif line.level==3:
|
||||
# check if it is a block or body content
|
||||
if line.markup:
|
||||
if line.bullet or self.bulletLevel:
|
||||
stuff,mu=self.itemize(line)
|
||||
if len(stuff) > 0:
|
||||
for i in stuff:
|
||||
body.append(i)
|
||||
else:
|
||||
mu=line.content.lstrip("\t")
|
||||
mu=mu.lstrip("|")
|
||||
else:
|
||||
for i in range(0,self.bulletLevel):
|
||||
self.bulletLevel -= 1
|
||||
body.append("\\end{itemize}\n")
|
||||
#block title
|
||||
if blockOpen:
|
||||
body.append("\\end{block}")
|
||||
else:
|
||||
blockOpen=1
|
||||
mu="\n\\begin{block}{%s}\n"%line.content.strip()
|
||||
blockCount+=1
|
||||
else:
|
||||
mu=""
|
||||
body.append(mu)
|
||||
for i in range(0,self.bulletLevel):
|
||||
self.bulletLevel -= 1
|
||||
body.append("\\end{itemize}\n")
|
||||
if blockOpen:
|
||||
body.append("\\end{block}")
|
||||
if frameOpen:
|
||||
body.append("\\end{frame}")
|
||||
|
||||
self.body=" ".join(body)
|
||||
self.markup=self.top1+self.preamble+self.top2
|
||||
self.markup+=self.body
|
||||
self.markup+="\n\\end{document}\n"
|
||||
print self.markup
|
||||
|
||||
# Process command line arguments
|
||||
args = sys.argv
|
||||
nargs=len(args)
|
||||
dispatch={}
|
||||
dispatch['beamer']=Beamer
|
||||
inputFileName=None
|
||||
outputFileName=None
|
||||
|
||||
def printUsage():
|
||||
print usage
|
||||
sys.exit()
|
||||
|
||||
if nargs==1:
|
||||
printUsage()
|
||||
else:
|
||||
docType='beamer'
|
||||
options=args[1]
|
||||
if options.count("-"):
|
||||
if options.count("a"):
|
||||
docType='article'
|
||||
elif options.count("b"):
|
||||
docType='book'
|
||||
if nargs==2:
|
||||
printUsage()
|
||||
elif nargs==3:
|
||||
inputFileName=args[2]
|
||||
elif nargs==4:
|
||||
inputFileName=args[2]
|
||||
outputFileName=args[3]
|
||||
else:
|
||||
printUsage()
|
||||
elif nargs==2:
|
||||
inputFileName=args[1]
|
||||
elif nargs==3:
|
||||
inputFileName=args[1]
|
||||
outputFileName=args[3]
|
||||
else:
|
||||
printUsage()
|
||||
# Dispatch to correct document class manager
|
||||
fin=open(inputFileName,'r')
|
||||
content=fin.readlines()
|
||||
fin.close()
|
||||
dispatch[docType](content,outputFileName)
|
|
@ -0,0 +1,223 @@
|
|||
|
||||
\documentclass[nototal,handout]{beamer}
|
||||
\mode<presentation>
|
||||
{
|
||||
\usetheme{Madrid}
|
||||
\setbeamercovered{transparent}
|
||||
}
|
||||
|
||||
\usepackage{verbatim}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage[latin1]{inputenc}
|
||||
\usepackage{times}
|
||||
\usepackage{tikz}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{graphicx} %sjr added
|
||||
\graphicspath{{figures/}}
|
||||
\usepackage{hyperref}
|
||||
|
||||
\author{Serge Rey}
|
||||
\institute[sjsrey@gmail.com]{sjsrey@gmail.com}
|
||||
\title[http://code.google.com/p/otl2latex/]{otl2latex}
|
||||
\subtitle{User's Guide}
|
||||
\date[otl2latex]{November 3, 2007}
|
||||
|
||||
% Delete this, if you do not want the table of contents to pop up at
|
||||
% the beginning of each subsection:
|
||||
\AtBeginSubsection[]
|
||||
{
|
||||
\begin{frame}<beamer>
|
||||
\frametitle{Outline}
|
||||
\tableofcontents[currentsection,currentsubsection]
|
||||
\end{frame}
|
||||
}
|
||||
|
||||
|
||||
% If you wish to uncover everything in a step-wise fashion, uncomment
|
||||
% the following command:
|
||||
\beamerdefaultoverlayspecification{<+->}
|
||||
\begin{document}
|
||||
\begin{frame}
|
||||
\titlepage
|
||||
\end{frame}
|
||||
\begin{frame}
|
||||
\frametitle{Outline}
|
||||
\tableofcontents[pausesections]
|
||||
% You might wish to add the option [pausesections]
|
||||
\end{frame}
|
||||
|
||||
|
||||
|
||||
\section{Introduction}
|
||||
|
||||
\subsection{What is otl2latex?}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Translator}
|
||||
|
||||
\begin{block}{otl to tex}
|
||||
otl2latex allows you to
|
||||
\begin{itemize}
|
||||
\item prepare your document in a powerful outliner
|
||||
\item generate \LaTeX\ markup of your content
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\subsection{Requirements}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Operating Systems}
|
||||
|
||||
\begin{block}{Operating Systems Supported}
|
||||
otl2latex has been used successfully on
|
||||
\begin{itemize}
|
||||
\item Linux
|
||||
\item Mac OS X
|
||||
\item Windows
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Software Required}
|
||||
|
||||
\begin{block}{Packages and Programs}
|
||||
\begin{itemize}
|
||||
\item Python http://www.python.org
|
||||
\item \LaTeX
|
||||
\item Beamer http://latex-beamer.sourceforge.net/
|
||||
\item The Vim Outliner http://bike-nomad.com/vim/vimoutliner.html
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
|
||||
\section{Usage}
|
||||
|
||||
\subsection{Basics}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Usage}
|
||||
|
||||
\begin{block}{From the command line}
|
||||
\texttt{python otl2latex.py -p filename.otl filename.tex}
|
||||
|
||||
\end{block}
|
||||
\begin{block}{Notes}
|
||||
\begin{itemize}
|
||||
\item \texttt{filename.tex} will be generated, you don't edit that one.
|
||||
\item You can run all this from withing Vim (see Vim Mappings below).
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Basics}
|
||||
|
||||
\begin{block}{Presentations/Beamer}
|
||||
\begin{itemize}
|
||||
\item Level 1 in the outline become sections
|
||||
\item Level 2 in the outline become subsections
|
||||
\item Level 3 in the outline become frame titles
|
||||
\item Level 4 in the outline become block titles
|
||||
\item Text in the outline is treated as \LaTeX\ markup
|
||||
\end{itemize}
|
||||
\end{block}
|
||||
\begin{block}{Using Bullets}
|
||||
Placing a '*' at the begining of a line will tell otl2latex to begin an itemize list. otl2latex currently supports 3 levels of Itemization.
|
||||
\begin{itemize}
|
||||
\item First Level
|
||||
\begin{itemize}
|
||||
\item Second Level
|
||||
\begin{itemize}
|
||||
\item Third Level
|
||||
\end{itemize}
|
||||
\item Second Level
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Advanced}
|
||||
|
||||
\begin{block}{Tips}
|
||||
\begin{itemize}
|
||||
\item Level 4 can be omitted
|
||||
\item You will have no blocks on that frame
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\subsection{Vim mappings}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Vim Mappings: .vimrc}
|
||||
|
||||
\begin{block}{Processing}
|
||||
\begin{itemize}
|
||||
\item ,b will generate a pdf file from your outline
|
||||
\item ,nb will remove all empty lines in your otl file
|
||||
\item ,p will run the current vim buffer through pdflatex
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Vim Mappings: .vimrc}
|
||||
|
||||
\begin{block}{Lists}
|
||||
\begin{itemize}
|
||||
\item ,i on the first line will create an itemized list of a block of lines
|
||||
\item ,t will mark a block as otl text
|
||||
\item ,I itemize and mark block as otl text
|
||||
\end{itemize}
|
||||
You need to have a blank line at the end of the block to apply these.
|
||||
\end{block} \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Vim Mappings: .vimrc}
|
||||
|
||||
\begin{block}{Figures}
|
||||
\begin{itemize}
|
||||
\item ,f (insert mode) will generate stub for figures
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{A figure}
|
||||
\begin{center}
|
||||
\includegraphics[width=.8\linewidth]{otl2latex.png}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{A figure}
|
||||
\begin{center}
|
||||
\includegraphics[width=.8\linewidth]{otl2latex.png}
|
||||
\end{center}
|
||||
\end{frame}
|
||||
|
||||
\subsection{Future Extensions}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Move to vim script}
|
||||
|
||||
\begin{block}{.vimrc to otl2latex.vim}
|
||||
\begin{itemize}
|
||||
\item Currently we are just embedding mappings in .vimrc
|
||||
\item Ok for testing, not very polished for end user
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Reverse Engineering}
|
||||
|
||||
\begin{block}{latex2otl}
|
||||
\begin{itemize}
|
||||
\item take a tex file
|
||||
\item generate the otl file
|
||||
\end{itemize}
|
||||
\end{block} \end{frame}
|
||||
|
||||
|
||||
\section{}
|
||||
|
||||
|
||||
\section{}
|
||||
\end{document}
|
|
@ -0,0 +1,9 @@
|
|||
\beamer@endinputifotherversion {3.07pt}
|
||||
\select@language {english}
|
||||
\beamer@sectionintoc {1}{Introduction}{3}{0}{1}
|
||||
\beamer@subsectionintoc {1}{1}{What is otl2latex?}{3}{0}{1}
|
||||
\beamer@subsectionintoc {1}{2}{Requirements}{4}{0}{1}
|
||||
\beamer@sectionintoc {2}{Usage}{6}{0}{2}
|
||||
\beamer@subsectionintoc {2}{1}{Basics}{6}{0}{2}
|
||||
\beamer@subsectionintoc {2}{2}{Vim mappings}{9}{0}{2}
|
||||
\beamer@subsectionintoc {2}{3}{Future Extensions}{14}{0}{2}
|
149
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2lyx.awk
Normal file
149
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2lyx.awk
Normal file
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/gawk -f
|
||||
|
||||
# Copyright (C) 2007 by Steve Litt, all rights reserved.
|
||||
# Licensed under the GNU General Public License, version 2.
|
||||
# otl2lyx.awk version 0.1.1 pre-alpha
|
||||
# 4/23/2007
|
||||
# Fixed insertion of other environments at bodytext to bodytext
|
||||
# borders.
|
||||
#
|
||||
# USAGE: ./otl2lyx level-environment-table-file outline-file
|
||||
#
|
||||
# level-table-structure:
|
||||
# 1: Top-level-environment-name
|
||||
# 2: 2nd-level-environment-name
|
||||
# 3: 3rd-level-environment-name
|
||||
# 4: 4th-level-environment-name
|
||||
# 5: 5th-level-environment-name
|
||||
# 6: 6th-level-environment-name
|
||||
# bodytext: environment-name-for-normal-text
|
||||
#
|
||||
# Example for a book:
|
||||
# 1: Chapter
|
||||
# 2: Section
|
||||
# 3: Subsection
|
||||
# 4: Subsubsection
|
||||
# 5: Paragraph
|
||||
# 6: Subparagraph
|
||||
# 7: Garbage7
|
||||
# bodytext: Standard
|
||||
|
||||
|
||||
BEGIN{
|
||||
FS=":[ \t]*"
|
||||
OFS="\x09"
|
||||
lastinbodytext=0
|
||||
}
|
||||
|
||||
### BLOW OFF BLANKS OUTSIDE OF BODY TEXT
|
||||
$0~/^[ \t]*$/ && inbodytext==0{
|
||||
next
|
||||
}
|
||||
|
||||
### FILL THE ENVIRONMENTS ARRAY ###
|
||||
ARGIND==1{
|
||||
FS=":[ \t]*";
|
||||
sub(/[ \t]*$/,"",$2);
|
||||
environments[$1] = $2;
|
||||
next;
|
||||
}
|
||||
|
||||
FNR==101{
|
||||
for(i in environments) print "level=" i ", string=" environments[i];
|
||||
}
|
||||
|
||||
### FIELD SEPARATOR IS TAB ON THE OUTLINE FILE ###
|
||||
{FS="\x09"; }
|
||||
|
||||
### INCREMENT OUTLINE ID NUMBER
|
||||
{ol_id++}
|
||||
|
||||
### CALCULATE LEVEL ###
|
||||
{
|
||||
for(i=1;i<=NF;i++)
|
||||
if($i == ""){
|
||||
} else {
|
||||
break
|
||||
}
|
||||
this["level"] = i
|
||||
if(ol_id == ol_id_first)
|
||||
this["level"]--
|
||||
}
|
||||
|
||||
### FIGURE TEXT ###
|
||||
{
|
||||
this["text"] = ""
|
||||
for(i=1;i<=NF;i++){
|
||||
if($i != ""){
|
||||
if(this["text"] == ""){
|
||||
this["text"] = this["text"] $i
|
||||
} else {
|
||||
this["text"] = this["text"] " " $i
|
||||
}
|
||||
}
|
||||
}
|
||||
sub(/^[ \t]+/, "", this["text"]);
|
||||
sub(/[ \t]+$/, "", this["text"]);
|
||||
}
|
||||
|
||||
### SET BODYTEXT FLAGS ###
|
||||
{ inbodytext = 0; newbodytext = 0; endbodytext = 0; btblankline=0; }
|
||||
|
||||
|
||||
this["text"] ~ /^:[ \t]+[^ \t]/{
|
||||
inbodytext = 1;
|
||||
sub(/^:[ \t]*/, "", this["text"]);
|
||||
this["text"] = this["text"] " ";
|
||||
}
|
||||
|
||||
this["text"] == "" || this["text"] == ":"{
|
||||
this["text"] = "";
|
||||
inbodytext = lastinbodytext;
|
||||
if(inbodytext == 1){
|
||||
endbodytext = 1;
|
||||
newbodytext = 1;
|
||||
btblankline = 1;
|
||||
}
|
||||
}
|
||||
|
||||
lastinbodytext == 1 && inbodytext == 0{
|
||||
endbodytext = 1;
|
||||
}
|
||||
|
||||
lastinbodytext == 0 && inbodytext == 1{
|
||||
newbodytext = 1;
|
||||
}
|
||||
|
||||
{ lastinbodytext = inbodytext; }
|
||||
|
||||
|
||||
|
||||
### QUOTE SINGLE BACKSLASHES FOR LATEX ###
|
||||
{gsub(/\\/,"\r\\backslash\r", this["text"]);}
|
||||
|
||||
### PRINT LYX CONTENT ###
|
||||
|
||||
endbodytext == 1{
|
||||
print "\\end_layout"
|
||||
print ""
|
||||
}
|
||||
newbodytext == 1{
|
||||
print "\\begin_layout " environments["bodytext"]
|
||||
}
|
||||
inbodytext == 1{
|
||||
if(btblankline == 0) print this["text"]
|
||||
}
|
||||
|
||||
inbodytext == 0{
|
||||
print "\\begin_layout " environments[this["level"]]
|
||||
print this["text"]
|
||||
print "\\end_layout"
|
||||
print ""
|
||||
}
|
||||
|
||||
END{
|
||||
if(inbodytext == 1){
|
||||
print "\\end_layout"
|
||||
print ""
|
||||
}
|
||||
}
|
263
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2ooimpress.py
Executable file
263
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2ooimpress.py
Executable file
|
@ -0,0 +1,263 @@
|
|||
#!/usr/bin/python2
|
||||
# otl2ooimpress.py
|
||||
# needs otl2ooimpress.sh to work in an automated way
|
||||
#############################################################################
|
||||
#
|
||||
# Tool for Vim Outliner files to Open Office Impress files.
|
||||
# Copyright (C) 2003 by Noel Henson, all rights reserved.
|
||||
#
|
||||
# This tool is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; if not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
# ALPHA VERSION!!!
|
||||
|
||||
###########################################################################
|
||||
# Basic function
|
||||
#
|
||||
# This program accepts VO outline files and converts them
|
||||
# to the zipped XML files required by Open Office Impress.
|
||||
#
|
||||
# 10 outline levels are supported. These loosely correspond to the
|
||||
# HTML H1 through H9 tags.
|
||||
#
|
||||
|
||||
|
||||
###########################################################################
|
||||
# include whatever mdules we need
|
||||
|
||||
import sys
|
||||
###########################################################################
|
||||
# global variables
|
||||
|
||||
level = 0
|
||||
inputFile = ""
|
||||
outline = []
|
||||
flatoutline = []
|
||||
pageNumber = 0
|
||||
inPage = 0
|
||||
debug = 0
|
||||
|
||||
###########################################################################
|
||||
# function definitions
|
||||
|
||||
|
||||
# usage
|
||||
# print the simplest form of help
|
||||
# input: none
|
||||
# output: simple command usage is printed on the console
|
||||
def showUsage():
|
||||
print
|
||||
print "Usage:"
|
||||
print "otl2ooimpress.py [options] inputfile > outputfile"
|
||||
print ""
|
||||
print "output is on STDOUT"
|
||||
print
|
||||
|
||||
|
||||
# getArgs
|
||||
# Check for input arguments and set the necessary switches
|
||||
# input: none
|
||||
# output: possible console output for help, switch variables may be set
|
||||
def getArgs():
|
||||
global inputfile, debug
|
||||
if (len(sys.argv) == 1):
|
||||
showUsage()
|
||||
sys.exit()()
|
||||
else:
|
||||
for i in range(len(sys.argv)):
|
||||
if (i != 0):
|
||||
if (sys.argv[i] == "-d"):
|
||||
debug = 1 # test for debug flag
|
||||
elif (sys.argv[i] == "-?"): # test for help flag
|
||||
showUsage() # show the help
|
||||
sys.exit() # exit
|
||||
elif (sys.argv[i] == "--help"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i] == "-h"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i][0] == "-"):
|
||||
print "Error! Unknown option. Aborting"
|
||||
sys.exit()
|
||||
else: # get the input file name
|
||||
inputfile = sys.argv[i]
|
||||
|
||||
|
||||
# getLineLevel
|
||||
# get the level of the current line (count the number of tabs)
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a number 1 is the lowest
|
||||
def getLineLevel(linein):
|
||||
strstart = linein.lstrip() # find the start of text in line
|
||||
x = linein.find(strstart) # find the text index in the line
|
||||
n = linein.count("\t", 0, x) # count the tabs
|
||||
return(n + 1) # return the count + 1 (for level)
|
||||
|
||||
|
||||
# getLineTextLevel
|
||||
# get the level of the current line (count the number of tabs)
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a number 1 is the lowest
|
||||
def getLineTextLevel(linein):
|
||||
strstart = linein.lstrip() # find the start of text in line
|
||||
x = linein.find(strstart) # find the text index in the line
|
||||
n = linein.count("\t", 0, x) # count the tabs
|
||||
n = n + linein.count(" ", 0, x) # count the spaces
|
||||
return(n + 1) # return the count + 1 (for level)
|
||||
|
||||
|
||||
# colonStrip(line)
|
||||
# stip a leading ':', if it exists
|
||||
# input: line
|
||||
# output: returns a string with a stipped ':'
|
||||
def colonStrip(line):
|
||||
if (line[0] == ":"):
|
||||
return line[1:].lstrip()
|
||||
else:
|
||||
return line
|
||||
|
||||
|
||||
# processLine
|
||||
# process a single line
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# level - an integer between 1 and 9 that show the current level
|
||||
# (not to be confused with the level of the current line)
|
||||
# output: through standard out
|
||||
def processLine(linein):
|
||||
global inPage, pageNumber
|
||||
if (linein.lstrip() == ""):
|
||||
print
|
||||
return
|
||||
if (getLineLevel(linein) == 1):
|
||||
if (inPage == 1):
|
||||
print '</draw:text-box></draw:page>'
|
||||
inPage = 0
|
||||
pageNumber += 1
|
||||
outstring = '<draw:page draw:name="'
|
||||
outstring += 'page'
|
||||
outstring += str(pageNumber)
|
||||
outstring += '" draw:style-name="dp1" draw:id="1" ' + \
|
||||
'draw:master-page-name="Default" ' + \
|
||||
'presentation:presentation-page-layout-name="AL1T0">'
|
||||
print outstring
|
||||
outstring = '<draw:text-box presentation:style-name="pr1" ' + \
|
||||
'draw:layer="layout" svg:width="23.911cm" ' + \
|
||||
'svg:height="3.508cm" svg:x="2.057cm" svg:y="1.0cm" ' + \
|
||||
'presentation:class="title">'
|
||||
print outstring
|
||||
outstring = '<text:p text:style-name="P1">'
|
||||
outstring += linein.lstrip()
|
||||
outstring += "</text:p></draw:text-box>"
|
||||
print outstring
|
||||
outstring = '<draw:text-box presentation:style-name="pr1" ' + \
|
||||
'draw:layer="layout" svg:width="23.911cm" ' + \
|
||||
'svg:height="3.508cm" svg:x="2.057cm" svg:y="5.38cm" ' + \
|
||||
'presentation:class="subtitle">'
|
||||
print outstring
|
||||
inPage = 1
|
||||
else:
|
||||
outstring = '<text:p text:style-name="P1">'
|
||||
outstring += linein.lstrip()
|
||||
outstring += '</text:p>'
|
||||
print outstring
|
||||
|
||||
|
||||
# flatten
|
||||
# Flatten a subsection of an outline. The index passed is the outline section
|
||||
# title. All sublevels that are only one level deeper are indcluded in the
|
||||
# current subsection. Then there is a recursion for those items listed in the
|
||||
# subsection. Exits when the next line to be processed is of the same or lower
|
||||
# outline level.
|
||||
# (lower means shallower)
|
||||
# input: idx - the index into the outline. The indexed line is the title.
|
||||
# output: adds reformatted lines to flatoutline[]
|
||||
def flatten(idx):
|
||||
if (outline[idx] == ""):
|
||||
return
|
||||
if (len(outline) <= idx):
|
||||
return
|
||||
titleline = outline[idx]
|
||||
titlelevel = getLineLevel(titleline)
|
||||
if (getLineLevel(outline[idx + 1]) > titlelevel):
|
||||
if (titleline[titlelevel - 1] != " "):
|
||||
flatoutline.append(titleline.lstrip())
|
||||
exitflag = 0
|
||||
while (exitflag == 0):
|
||||
if (idx < len(outline) - 1):
|
||||
idx = idx + 1
|
||||
currlevel = getLineLevel(outline[idx])
|
||||
if (currlevel == titlelevel + 1):
|
||||
if (currlevel == outline[idx].find(" ") + 1):
|
||||
flatoutline.append("\t " + outline[idx].lstrip())
|
||||
else:
|
||||
flatoutline.append("\t" + outline[idx].lstrip())
|
||||
elif (currlevel <= titlelevel):
|
||||
exitflag = 1
|
||||
else:
|
||||
exitflag = 1
|
||||
return
|
||||
|
||||
|
||||
def printHeader(linein):
|
||||
print'''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE office:document-content PUBLIC
|
||||
"-//OpenOffice.org//DTD OfficeDocument 1.0//EN"
|
||||
"office.dtd">
|
||||
<office:document-content xmlns:office="http://openoffice.org/2000/office"
|
||||
xmlns:style="http://openoffice.org/2000/style"
|
||||
xmlns:text="http://openoffice.org/2000/text"
|
||||
xmlns:table="http://openoffice.org/2000/table"
|
||||
xmlns:draw="http://openoffice.org/2000/drawing"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:number="http://openoffice.org/2000/datastyle"
|
||||
xmlns:presentation="http://openoffice.org/2000/presentation"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:chart="http://openoffice.org/2000/chart"
|
||||
xmlns:dr3d="http://openoffice.org/2000/dr3d"
|
||||
xmlns:math="http://www.w3.org/1998/Math/MathML"
|
||||
xmlns:form="http://openoffice.org/2000/form"
|
||||
xmlns:script="http://openoffice.org/2000/script"
|
||||
office:class="presentation" office:version="1.0">
|
||||
<office:script/>
|
||||
<office:body>'''
|
||||
|
||||
|
||||
def printFooter():
|
||||
print '</draw:text-box></draw:page>'
|
||||
print'</office:body>'
|
||||
|
||||
|
||||
def main():
|
||||
getArgs()
|
||||
file = open(inputFile, "r")
|
||||
linein = file.readline().strip()
|
||||
outline.append(linein)
|
||||
linein = file.readline().strip()
|
||||
while linein != "":
|
||||
outline.append("\t" + linein)
|
||||
linein = file.readline().rstrip()
|
||||
for i in range(0, len(outline) - 1):
|
||||
flatten(i)
|
||||
|
||||
printHeader(flatoutline[0])
|
||||
for i in range(0, len(flatoutline)):
|
||||
processLine(flatoutline[i])
|
||||
printFooter()
|
||||
|
||||
file.close()
|
||||
|
||||
main()
|
34
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2ooimpress.sh
Executable file
34
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2ooimpress.sh
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
# otl2ooimpress.sh
|
||||
# needs otl2ooimpress.py to work at all
|
||||
#############################################################################
|
||||
#
|
||||
# Tool for Vim Outliner files to Open Office Impress files.
|
||||
# Copyright (C) 2003 by Noel Henson, all rights reserved.
|
||||
#
|
||||
# This tool is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; if not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
# Path to otl2ooimpress.py
|
||||
MYPATH=$HOME/bin
|
||||
# Path to rm
|
||||
RMPATH=/bin
|
||||
# Path to zip
|
||||
ZIPPATH=/usr/bin
|
||||
|
||||
$MYPATH/otl2ooimpress.py $1 > content.xml
|
||||
$ZIPPATH/zip $1.sxi content.xml
|
||||
$RMPATH/rm content.xml
|
199
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2table.py
Executable file
199
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2table.py
Executable file
|
@ -0,0 +1,199 @@
|
|||
#!/usr/bin/python2
|
||||
# otl2table.py
|
||||
# convert a tab-formatted outline from VIM to tab-delimited table
|
||||
#
|
||||
# Copyright (c) 2004 Noel Henson All rights reserved
|
||||
#
|
||||
# ALPHA VERSION!!!
|
||||
|
||||
###########################################################################
|
||||
# Basic function
|
||||
#
|
||||
# This program accepts text outline files and converts them
|
||||
# the tab-delimited text tables.
|
||||
# This:
|
||||
# Test
|
||||
# Dog
|
||||
# Barks
|
||||
# Howls
|
||||
# Cat
|
||||
# Meows
|
||||
# Yowls
|
||||
# Becomes this:
|
||||
# Test Dog Barks
|
||||
# Test Dog Howls
|
||||
# Test Cat Meows
|
||||
# Test Cat Yowls
|
||||
#
|
||||
# This will make searching for groups of data and report generation easier.
|
||||
#
|
||||
|
||||
|
||||
###########################################################################
|
||||
# include whatever mdules we need
|
||||
|
||||
import sys
|
||||
from string import *
|
||||
#from time import *
|
||||
|
||||
###########################################################################
|
||||
# global variables
|
||||
|
||||
level = 0
|
||||
inputFile = ""
|
||||
formatMode = "tab"
|
||||
noTrailing = 0
|
||||
columns = []
|
||||
|
||||
###########################################################################
|
||||
# function definitions
|
||||
|
||||
# usage
|
||||
# print the simplest form of help
|
||||
# input: none
|
||||
# output: simple command usage is printed on the console
|
||||
|
||||
def showUsage():
|
||||
print
|
||||
print "Usage:"
|
||||
print "otl2table.py [options] inputfile > outputfile"
|
||||
print "Options"
|
||||
print " -n Don't include trailing columns."
|
||||
print " -t type Specify field separator type."
|
||||
print " Types:"
|
||||
print " tab - separate fields with tabs (default)"
|
||||
print " csv - separate fields with ,"
|
||||
print " qcsv - separate fields with \",\""
|
||||
print " bullets - uses HTML tags <ul> and <li>"
|
||||
print "output is on STDOUT"
|
||||
print
|
||||
|
||||
# getArgs
|
||||
# Check for input arguments and set the necessary switches
|
||||
# input: none
|
||||
# output: possible console output for help, switch variables may be set
|
||||
|
||||
def getArgs():
|
||||
global inputfile, debug, noTrailing, formatMode
|
||||
if (len(sys.argv) == 1):
|
||||
showUsage()
|
||||
sys.exit()()
|
||||
else:
|
||||
for i in range(len(sys.argv)):
|
||||
if (i != 0):
|
||||
if (sys.argv[i] == "-d"): debug = 1 # test for debug flag
|
||||
if (sys.argv[i] == "-n"): noTrailing = 1 # test for noTrailing flag
|
||||
elif (sys.argv[i] == "-?"): # test for help flag
|
||||
showUsage() # show the help
|
||||
sys.exit() # exit
|
||||
elif (sys.argv[i] == "--help"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i] == "-h"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i] == "-t"): # test for the type flag
|
||||
formatMode = sys.argv[i+1] # get the type
|
||||
i = i + 1 # increment the pointer
|
||||
elif (sys.argv[i][0] == "-"):
|
||||
print "Error! Unknown option. Aborting"
|
||||
sys.exit()
|
||||
else: # get the input file name
|
||||
inputfile = sys.argv[i]
|
||||
|
||||
# getLineLevel
|
||||
# get the level of the current line (count the number of tabs)
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a number 1 is the lowest
|
||||
|
||||
def getLineLevel(linein):
|
||||
strstart = lstrip(linein) # find the start of text in line
|
||||
x = find(linein,strstart) # find the text index in the line
|
||||
n = count(linein,"\t",0,x) # count the tabs
|
||||
return(n+1) # return the count + 1 (for level)
|
||||
|
||||
# getLineTextLevel
|
||||
# get the level of the current line (count the number of tabs)
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a number 1 is the lowest
|
||||
|
||||
def getLineTextLevel(linein):
|
||||
strstart = lstrip(linein) # find the start of text in line
|
||||
x = find(linein,strstart) # find the text index in the line
|
||||
n = count(linein,"\t",0,x) # count the tabs
|
||||
n = n + count(linein," ",0,x) # count the spaces
|
||||
return(n+1) # return the count + 1 (for level)
|
||||
|
||||
# closeLevels
|
||||
# print the assembled line
|
||||
# input: columns - an array of 10 lines (for 10 levels)
|
||||
# level - an integer between 1 and 9 that show the current level
|
||||
# (not to be confused with the level of the current line)
|
||||
# noTrailing - don't print trailing, empty columns
|
||||
# output: through standard out
|
||||
|
||||
def closeLevels():
|
||||
global level,columns,noTrailing,formatMode
|
||||
if noTrailing == 1 :
|
||||
colcount = level
|
||||
else:
|
||||
colcount = 10
|
||||
if formatMode == "tab":
|
||||
for i in range(1,colcount+1):
|
||||
print columns[i] + "\t",
|
||||
print
|
||||
elif formatMode == "csv":
|
||||
output = ""
|
||||
for i in range(1,colcount):
|
||||
output = output + columns[i] + ","
|
||||
output = output + columns[colcount]
|
||||
print output
|
||||
elif formatMode == "qcsv":
|
||||
output = "\""
|
||||
for i in range(1,colcount):
|
||||
output = output + columns[i] + "\",\""
|
||||
output = output + columns[colcount] + "\""
|
||||
print output
|
||||
for i in range(level+1,10):
|
||||
columns[i] = ""
|
||||
|
||||
|
||||
# processLine
|
||||
# process a single line
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# format - a string indicating the mode to use for formatting
|
||||
# level - an integer between 1 and 9 that show the current level
|
||||
# (not to be confused with the level of the current line)
|
||||
# output: through standard out
|
||||
|
||||
def processLine(linein):
|
||||
global level, noTrailing, columns
|
||||
if (lstrip(linein) == ""): return
|
||||
lineLevel = getLineLevel(linein)
|
||||
if (lineLevel > level):
|
||||
columns[lineLevel] = lstrip(rstrip(linein))
|
||||
level = lineLevel
|
||||
elif (lineLevel == level):
|
||||
closeLevels()
|
||||
columns[lineLevel] = lstrip(rstrip(linein))
|
||||
else:
|
||||
closeLevels()
|
||||
level = lineLevel
|
||||
columns[lineLevel] = lstrip(rstrip(linein))
|
||||
|
||||
|
||||
def main():
|
||||
global columns
|
||||
getArgs()
|
||||
file = open(inputfile,"r")
|
||||
for i in range(11):
|
||||
columns.append("")
|
||||
linein = lstrip(rstrip(file.readline()))
|
||||
while linein != "":
|
||||
processLine(linein)
|
||||
linein = file.readline()
|
||||
closeLevels()
|
||||
file.close()
|
||||
|
||||
main()
|
||||
|
713
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2tags.py
Executable file
713
pack/acp/start/vimoutliner/vimoutliner/scripts/otl2tags.py
Executable file
|
@ -0,0 +1,713 @@
|
|||
#!/usr/bin/python2
|
||||
# otl2tags.py
|
||||
# Convert an OTL file to any tags-based file using config user-
|
||||
# definable configuration files. HTML, OPML, XML, LATEX and
|
||||
# many, many others should be easily supportables.
|
||||
#
|
||||
# Copyright (c) 2005-2010 Noel Henson All rights reserved
|
||||
|
||||
###########################################################################
|
||||
# Basic function
|
||||
#
|
||||
# This program accepts text outline files in Vim Outliners .otl format
|
||||
# and converts them to a tags-based equivalent
|
||||
|
||||
###########################################################################
|
||||
# include whatever mdules we need
|
||||
|
||||
import sys
|
||||
from ConfigParser import ConfigParser
|
||||
import re
|
||||
|
||||
###########################################################################
|
||||
# global variables
|
||||
|
||||
config = ConfigParser() # configuration
|
||||
linecount = 0 # outline size in lines
|
||||
parents = [] # parent stack, (linenum, enum) enum is an order numer
|
||||
v = {} # variable dictionary for substitution
|
||||
outline = [] # line tuples (value, indent)
|
||||
output = [] # output outline
|
||||
escapeDict = {} # dictionary of character escape codes
|
||||
debug = 0
|
||||
inputfile = ""
|
||||
|
||||
###########################################################################
|
||||
# arugment, help and debug functions
|
||||
|
||||
|
||||
# usage
|
||||
# print debug statements
|
||||
# input: string
|
||||
# output: string printed to standard out
|
||||
def dprint(*vals):
|
||||
global debug
|
||||
if debug != 0:
|
||||
print >> sys.stderr, vals
|
||||
|
||||
|
||||
# usage
|
||||
# print the simplest form of help
|
||||
# input: none
|
||||
# output: simple command usage is printed on the console
|
||||
def showUsage():
|
||||
print """
|
||||
Usage:
|
||||
otl2table.py [options] inputfile
|
||||
Options
|
||||
-c config-file
|
||||
-d debug
|
||||
--help show help
|
||||
output filenames are based on the input file name and the config file
|
||||
"""
|
||||
|
||||
|
||||
# getArgs
|
||||
# Check for input arguments and set the necessary switches
|
||||
# input: none
|
||||
# output: possible console output for help, switch variables may be set
|
||||
def getArgs():
|
||||
global inputfile, debug, noTrailing, formatMode, config
|
||||
if (len(sys.argv) == 1):
|
||||
showUsage()
|
||||
sys.exit()()
|
||||
else:
|
||||
for i in range(len(sys.argv)):
|
||||
if (i != 0):
|
||||
if (sys.argv[i] == "-c"): # test for the type flag
|
||||
config.read(sys.argv[i + 1]) # read the config
|
||||
i = i + 1 # increment the pointer
|
||||
elif (sys.argv[i] == "-d"):
|
||||
debug = 1
|
||||
elif (sys.argv[i] == "-?"): # test for help flag
|
||||
showUsage() # show the help
|
||||
sys.exit() # exit
|
||||
elif (sys.argv[i] == "--help"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i] == "-h"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i][0] == "-"):
|
||||
print "Error! Unknown option. Aborting"
|
||||
sys.exit()
|
||||
else: # get the input file name
|
||||
inputfile = sys.argv[i]
|
||||
|
||||
|
||||
# printConfig
|
||||
# Debugging routine to print the parsed configuration file
|
||||
# input: none
|
||||
# output: configuration data printed to console
|
||||
def printConfig():
|
||||
global config
|
||||
print >> sys.stderr, "Config ---------------------------------------------"
|
||||
list = config.sections()
|
||||
for i in range(len(list)):
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, list[i]
|
||||
for x in config.options(list[i]):
|
||||
if (x != "name") and (x != "__name__"):
|
||||
print >> sys.stderr, x, ":", config.get(list[i], x)
|
||||
print >> sys.stderr, "----------------------------------------------------"
|
||||
print >> sys.stderr
|
||||
|
||||
###########################################################################
|
||||
# low-level outline processing functions
|
||||
|
||||
|
||||
# indentLevel
|
||||
# get the level of the line specified by linenum
|
||||
# input: line
|
||||
# output: returns the level number, 1 is the lowest
|
||||
def indentLevel(line):
|
||||
strstart = line.lstrip() # find the start of text in line
|
||||
x = line.find(strstart) # find the text index in the line
|
||||
n = line.count("\t", 0, x) # count the tabs
|
||||
n = n + line.count(" ", 0, x) # count the spaces
|
||||
return(n + 1) # return the count + 1 (for level)
|
||||
|
||||
|
||||
# stripMarker
|
||||
# return a line without its marker and leading and trailing whitespace
|
||||
# input: line, marker
|
||||
# output: stripped line
|
||||
def stripMarker(line, marker):
|
||||
return line.lstrip(marker).strip()
|
||||
|
||||
|
||||
# getLineType
|
||||
# return the type of the line specified by linenum
|
||||
# input: line
|
||||
# output: returns text, usertext, table, preftext, etc.
|
||||
def getLineType(line):
|
||||
if (line[0] == ':'):
|
||||
return 'text'
|
||||
elif (line[0] == ';'):
|
||||
return 'preftext'
|
||||
elif (line[0] == '>'):
|
||||
return 'usertext'
|
||||
elif (line[0] == '<'):
|
||||
return 'userpreftext'
|
||||
elif (line[0] == '|'):
|
||||
return 'table'
|
||||
elif (line[0] == '-'):
|
||||
return 'bulletheading'
|
||||
elif (line[0] == '+'):
|
||||
return 'numberheading'
|
||||
# elif (line[0] == '['):
|
||||
# return 'checkboxheading'
|
||||
elif (line[0] == ''):
|
||||
return 'blank'
|
||||
else:
|
||||
return 'heading'
|
||||
|
||||
|
||||
# getChildren
|
||||
# return a list of line numbers for children of the passed line number
|
||||
# input: linenum
|
||||
# output: a (possibly) empty list of children
|
||||
def getChildren(linenum):
|
||||
global outline, linecount
|
||||
|
||||
children = []
|
||||
mylevel = outline[linenum][1]
|
||||
childlevel = mylevel + 1
|
||||
linenum = linenum + 1
|
||||
while (linenum < linecount) and (outline[linenum][1] > mylevel):
|
||||
if (outline[linenum][1] == childlevel):
|
||||
children.append(linenum)
|
||||
linenum = linenum + 1
|
||||
return children
|
||||
|
||||
|
||||
# subTags
|
||||
# substitute variables in output expressions
|
||||
# input: section - section from config
|
||||
# input: type - object type (to look up in config)
|
||||
# input: - substitution item (by name) from config array
|
||||
# output: string - the substitution expression with variables inserted
|
||||
def subTags(section, type):
|
||||
global config, v, parents
|
||||
|
||||
varlist = v.keys()
|
||||
pattern = config.get(section, type)
|
||||
if len(parents) > 0:
|
||||
v["%p"] = str(parents[len(parents) - 1])
|
||||
|
||||
for var in varlist:
|
||||
x = ""
|
||||
x = var
|
||||
y = ""
|
||||
y = v.get(var)
|
||||
pattern = re.sub(x, y, pattern)
|
||||
return pattern
|
||||
|
||||
|
||||
#getBlock
|
||||
#return a list of lines that match a mark (like : or ;)
|
||||
#input: line number
|
||||
#output: list of stripped lines
|
||||
def getBlock(linenum, marker):
|
||||
global outline, linecount
|
||||
|
||||
lines = []
|
||||
line = outline[linenum][0]
|
||||
while line[0] == marker:
|
||||
lines.append(stripMarker(line, marker))
|
||||
linenum = linenum + 1
|
||||
if linenum == linecount:
|
||||
break
|
||||
line = outline[linenum][0]
|
||||
return lines
|
||||
|
||||
|
||||
#getUnstrippedBlock
|
||||
#return a list of lines that match a mark (like : or ;)
|
||||
#input: line number
|
||||
#output: list of stripped lines
|
||||
def getUnstrippedBlock(linenum, marker):
|
||||
global outline, linecount
|
||||
|
||||
lines = []
|
||||
line = outline[linenum][0]
|
||||
while line[0] == marker:
|
||||
lines.append(line)
|
||||
linenum = linenum + 1
|
||||
if linenum == linecount:
|
||||
break
|
||||
line = outline[linenum][0]
|
||||
return lines
|
||||
|
||||
###########################################################################
|
||||
# embedded object processing functions
|
||||
|
||||
|
||||
# buildEscapes
|
||||
# construct the dictionary for escaping special characters
|
||||
# intput: config:escapes
|
||||
# output: filled escapes dictionary
|
||||
def buildEscapes():
|
||||
escapes = config.get("Document", "escapes")
|
||||
if len(escapes):
|
||||
list = escapes.split(" ")
|
||||
for pair in list:
|
||||
key, value = pair.split(",")
|
||||
escapeDict[key] = value
|
||||
|
||||
|
||||
# charEscape
|
||||
# escape special characters
|
||||
# input: line
|
||||
# output: modified line
|
||||
def charEscape(line):
|
||||
return "".join(escapeDict.get(c, c) for c in line)
|
||||
|
||||
|
||||
# getURL
|
||||
# if there is a url, [url text], return the extracted link, url and value
|
||||
# input: line
|
||||
# output: link, url, text
|
||||
def getURL(line):
|
||||
tags = []
|
||||
for tag in line.split("]"):
|
||||
tags.append(tag.split("["))
|
||||
|
||||
for tag in tags:
|
||||
if len(tag) > 1 and re.search(" ", tag[1]):
|
||||
link = tag[1]
|
||||
|
||||
url, text = link.split(" ", 1)
|
||||
link = "[" + tag[1] + "]"
|
||||
return link, url, text
|
||||
|
||||
# return link.group(0), url, text
|
||||
# else:
|
||||
# return None, None, None
|
||||
return None, None, None
|
||||
|
||||
|
||||
def handleURL(line):
|
||||
link, url, text = getURL(line)
|
||||
if link is None:
|
||||
return re.replace(line, "[url]", "")
|
||||
|
||||
v["%u"] = url
|
||||
v["%v"] = text
|
||||
|
||||
text = subTags("URLs", "url")
|
||||
line = re.replace(line, link, text)
|
||||
|
||||
url = subTags("URLs", "url-attr")
|
||||
line = re.replace(line, "[url]", url)
|
||||
|
||||
return line
|
||||
|
||||
|
||||
###########################################################################
|
||||
# outline header processing functions
|
||||
|
||||
|
||||
# all outline object processors accept and output the following:
|
||||
# input: linenum, enum
|
||||
# output: print the output for each object
|
||||
def handleHeading(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
line = outline[linenum][0]
|
||||
|
||||
# url handling
|
||||
# extract url data from line
|
||||
# replace url object in line
|
||||
# subTags line
|
||||
# replace url attribute marker
|
||||
|
||||
v["%%"] = line
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
children = getChildren(linenum)
|
||||
if enum == 1:
|
||||
output.append(subTags("Headings", "before-headings"))
|
||||
if children:
|
||||
output.append(subTags("Headings", "branch-heading"))
|
||||
parents.append([linenum, enum])
|
||||
handleObjects(children)
|
||||
parents.pop()
|
||||
output.append(subTags("Headings", "after-headings"))
|
||||
else:
|
||||
output.append(subTags("Headings", "leaf-heading"))
|
||||
|
||||
|
||||
def handleBulleted(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
v["%%"] = outline[linenum][0]
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
children = getChildren(linenum)
|
||||
if enum == 1:
|
||||
output.append(subTags("Headings", "before-bulleted-headings"))
|
||||
if children:
|
||||
output.append(subTags("Headings", "bulleted-branch-heading"))
|
||||
parents.append([linenum, enum])
|
||||
handleObjects(children)
|
||||
parents.pop()
|
||||
output.append(subTags("Headings", "after-bulleted-headings"))
|
||||
else:
|
||||
output.append(subTags("Headings", "bulleted-leaf-heading"))
|
||||
|
||||
|
||||
def handleNumbered(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
v["%%"] = outline[linenum][0]
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
children = getChildren(linenum)
|
||||
if enum == 1:
|
||||
output.append(subTags("Headings", "before-numbered-headings"))
|
||||
if children:
|
||||
output.append(subTags("Headings", "numbered-branch-heading"))
|
||||
parents.append([linenum, enum])
|
||||
handleObjects(children)
|
||||
parents.pop()
|
||||
output.append(subTags("Headings", "after-numbered-headings"))
|
||||
else:
|
||||
output.append(subTags("Headings", "numbered-leaf-heading"))
|
||||
|
||||
###########################################################################
|
||||
# outline text block processing functions
|
||||
|
||||
|
||||
# all outline object processors accept and output the following:
|
||||
# input: linenum, enum
|
||||
# output: print the output for each object
|
||||
def handleText(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
if enum != 1:
|
||||
return # only execute for first call
|
||||
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
list = getBlock(linenum, ':')
|
||||
output.append(subTags("Text", "before"))
|
||||
lines = ""
|
||||
for line in list:
|
||||
if line == "":
|
||||
lines = lines + config.get("Text", "paragraph-sep")
|
||||
else:
|
||||
lines = lines + line + config.get("Text", "line-sep")
|
||||
v["%%"] = lines
|
||||
output.append(subTags("Text", "text"))
|
||||
output.append(subTags("Text", "after"))
|
||||
|
||||
|
||||
def handleUserText(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
if enum != 1:
|
||||
return # only execute for first call
|
||||
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
list = getBlock(linenum, '>')
|
||||
output.append(subTags("UserText", "before"))
|
||||
lines = ""
|
||||
for line in list:
|
||||
if line == "":
|
||||
lines = lines + config.get("UserText", "paragraph-sep")
|
||||
else:
|
||||
lines = lines + line + config.get("UserText", "line-sep")
|
||||
v["%%"] = lines.strip() # remove a possible extra separator
|
||||
output.append(subTags("UserText", "text"))
|
||||
output.append(subTags("UserText", "after"))
|
||||
|
||||
|
||||
def handlePrefText(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
if enum != 1:
|
||||
return # only execute for first call
|
||||
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
list = getBlock(linenum, ';')
|
||||
output.append(subTags("PrefText", "before"))
|
||||
lines = ""
|
||||
for line in list:
|
||||
if line == "":
|
||||
lines = lines + config.get("PrefText", "paragraph-sep")
|
||||
else:
|
||||
lines = lines + line + config.get("PrefText", "line-sep")
|
||||
v["%%"] = lines.strip() # remove a possible extra separator
|
||||
output.append(subTags("PrefText", "text"))
|
||||
output.append(subTags("PrefText", "after"))
|
||||
|
||||
|
||||
def handleUserPrefText(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
if enum != 1:
|
||||
return # only execute for first call
|
||||
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
list = getBlock(linenum, '<')
|
||||
output.append(subTags("UserPrefText", "before"))
|
||||
lines = ""
|
||||
for line in list:
|
||||
if line == "":
|
||||
lines = lines + config.get("UserPrefText", "paragraph-sep")
|
||||
else:
|
||||
lines = lines + line + config.get("UserPrefText", "line-sep")
|
||||
v["%%"] = lines.strip() # remove a possible extra separator
|
||||
output.append(subTags("UserPrefText", "text"))
|
||||
output.append(subTags("UserPrefText", "after"))
|
||||
|
||||
###########################################################################
|
||||
# outline table processing functions
|
||||
|
||||
|
||||
# isAlignRight
|
||||
# return flag
|
||||
# input: col, a string
|
||||
def isAlignRight(col):
|
||||
l = len(col)
|
||||
if (col[0:2] == " ") and (col[l - 2:l] != " "):
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
# isAlignLeft
|
||||
# return flag
|
||||
# input: col, a string
|
||||
def isAlignLeft(col):
|
||||
l = len(col)
|
||||
if (col[0:2] != " ") and (col[l - 2:l] == " "):
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
# isAlignCenter
|
||||
# return flag
|
||||
# input: col, a string
|
||||
def isAlignCenter(col):
|
||||
l = len(col)
|
||||
if (col[0:2] == " ") and (col[l - 2:l] == " "):
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
# handleHeaderRow
|
||||
# process a non-header table row
|
||||
# input: row
|
||||
# output: print the output for each object
|
||||
def handleHeaderRow(row):
|
||||
global outline, parents
|
||||
|
||||
row = row.rstrip("|").lstrip("|")
|
||||
columns = row.split("|")
|
||||
output.append(subTags("Tables", "before-table-header"))
|
||||
for col in columns:
|
||||
v["%%"] = col.strip()
|
||||
if isAlignCenter:
|
||||
output.append(subTags("Tables", "table-header-column-center"))
|
||||
elif isAlignCenter:
|
||||
output.append(subTags("Tables", "table-header-column-center"))
|
||||
elif isAlignCenter:
|
||||
output.append(subTags("Tables", "table-header-column-center"))
|
||||
else:
|
||||
output.append(subTags("Tables", "table-header-column"))
|
||||
output.append(subTags("Tables", "after-table-header"))
|
||||
|
||||
|
||||
# handleRow
|
||||
# process a non-header table row
|
||||
# input: row
|
||||
# output: print the output for each object
|
||||
def handleRow(row):
|
||||
global outline, parents
|
||||
|
||||
if row[0:2] == "||":
|
||||
handleHeaderRow(row)
|
||||
return
|
||||
row = row.rstrip("|").lstrip("|")
|
||||
columns = row.split("|")
|
||||
output.append(subTags("Tables", "before-table-row"))
|
||||
for col in columns:
|
||||
v["%%"] = col.strip()
|
||||
if isAlignCenter:
|
||||
output.append(subTags("Tables", "table-column-center"))
|
||||
elif isAlignLeft:
|
||||
output.append(subTags("Tables", "table-column-left"))
|
||||
elif isAlignRight:
|
||||
output.append(subTags("Tables", "table-column-right"))
|
||||
else:
|
||||
output.append(subTags("Tables", "table-column"))
|
||||
output.append(subTags("Tables", "after-table-row"))
|
||||
|
||||
|
||||
# handleTable
|
||||
# process a table
|
||||
# input: linenum, enum
|
||||
# output: print the output for each object
|
||||
def handleTable(linenum, enum):
|
||||
global outline, parents
|
||||
|
||||
if enum != 1:
|
||||
return # only execute for first call
|
||||
|
||||
v["%l"] = str(outline[linenum][1])
|
||||
v["%n"] = str(linenum)
|
||||
v["%c"] = str(enum)
|
||||
list = getUnstrippedBlock(linenum, '|')
|
||||
output.append(subTags("Tables", "before"))
|
||||
for row in list:
|
||||
handleRow(row)
|
||||
output.append(subTags("Tables", "after"))
|
||||
|
||||
###########################################################################
|
||||
# outline wrapper processing functions
|
||||
|
||||
|
||||
# addPreamble
|
||||
# create the 'header' for the output document
|
||||
# input: globals
|
||||
# output: standard out
|
||||
def addPreamble():
|
||||
global outline, v
|
||||
|
||||
v["%%"] = ""
|
||||
output.append(subTags("Document", "preamble"))
|
||||
|
||||
|
||||
# addPostamble
|
||||
# create the 'header' for the output document
|
||||
# input: globals
|
||||
# output: standard out
|
||||
def addPostamble():
|
||||
global outline, v
|
||||
|
||||
v["%%"] = ""
|
||||
output.append(subTags("Document", "postamble"))
|
||||
|
||||
|
||||
###########################################################################
|
||||
# outline tree fuctions
|
||||
|
||||
|
||||
# handleObject
|
||||
# take an object and invoke the appropriate fuction to precess it
|
||||
# input: linenum, enum (enum is the child order number of a parent)
|
||||
# output: print the output of a object
|
||||
def handleObject(linenum, enum):
|
||||
global outline, linecount
|
||||
|
||||
obj = getLineType(outline[linenum][0])
|
||||
if obj == 'heading':
|
||||
handleHeading(linenum, enum)
|
||||
elif obj == 'bulled':
|
||||
handleBulleted(linenum, enum)
|
||||
elif obj == 'numbered':
|
||||
handleNumbered(linenum, enum)
|
||||
elif obj == 'text':
|
||||
handleText(linenum, enum)
|
||||
elif obj == 'usertext':
|
||||
handleUserText(linenum, enum)
|
||||
elif obj == 'preftext':
|
||||
handlePrefText(linenum, enum)
|
||||
elif obj == 'userpreftext':
|
||||
handleUserPrefText(linenum, enum)
|
||||
elif obj == 'table':
|
||||
handleTable(linenum, enum)
|
||||
else:
|
||||
print
|
||||
print "Error: unknown line type @ ", linenum
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# handleObjects
|
||||
# take an object list and invoke the appropriate fuctions to precess it
|
||||
# input: linenum
|
||||
# output: print the output of a object
|
||||
def handleObjects(objs):
|
||||
for i in range(len(objs)):
|
||||
handleObject(objs[i], i + 1)
|
||||
|
||||
###########################################################################
|
||||
# file functions
|
||||
|
||||
|
||||
# readFile
|
||||
# read the selected file into lines[]
|
||||
# input: filename to be loaded
|
||||
# output: a loaded-up lines[]
|
||||
def readFile(inputfile):
|
||||
global outline, linecount, config
|
||||
file = open(inputfile, "r")
|
||||
linein = file.readline()
|
||||
|
||||
while linein != "":
|
||||
indent = indentLevel(linein)
|
||||
line = charEscape(linein.strip())
|
||||
outline.append([line, indent])
|
||||
linein = file.readline()
|
||||
|
||||
file.close
|
||||
|
||||
outline[0][1] = 0 # set the first line to level 0
|
||||
|
||||
linecount = len(outline)
|
||||
|
||||
###########################################################################
|
||||
# Main Program Loop
|
||||
|
||||
|
||||
def main():
|
||||
global outline, inputfile, linecount
|
||||
|
||||
# get the arguments
|
||||
getArgs()
|
||||
|
||||
# constuct the escapes dictionary
|
||||
buildEscapes()
|
||||
|
||||
# read the input file
|
||||
readFile(inputfile)
|
||||
|
||||
# get the title
|
||||
v["%t"] = outline[0][0].strip()
|
||||
|
||||
# construct the initial data
|
||||
# parsing headings, text and tables
|
||||
# but not parsing links or images
|
||||
addPreamble()
|
||||
if config.get("Document", "first-is-node") == "true":
|
||||
objs = [0]
|
||||
else:
|
||||
objs = getChildren(0)
|
||||
handleObjects(objs)
|
||||
addPostamble()
|
||||
|
||||
# handle embeded objects
|
||||
# parsing and constructing links, images and other embedded objects
|
||||
for i in range(len(output)):
|
||||
output[i] = handleURL(output[i])
|
||||
|
||||
# output the final data
|
||||
for line in output:
|
||||
if line.strip() != "":
|
||||
print line.strip()
|
||||
|
||||
main()
|
|
@ -0,0 +1,96 @@
|
|||
# FreeMind configuration file
|
||||
# Variables:
|
||||
# %% - data
|
||||
# %l - outline level
|
||||
# %t - document title (the first line of the document)
|
||||
# %n - line number (document title is 0)
|
||||
# %N - line number of first line of block (for text blocks)
|
||||
# %p - parent line number
|
||||
# %c - my child number, a heading's order number under it's parent
|
||||
# %u - URL link field: http://www.a.com in [http://www.a.com link to me]
|
||||
# %v - URL text field: 'link to me' in [http://www.a.com link to me]
|
||||
#
|
||||
# Special Markers
|
||||
# [url] - a marker for an optional url/link attribute: url-attr
|
||||
#
|
||||
# Flags
|
||||
# first-is-node
|
||||
# true for output to programs like FreeMind and GraphViz
|
||||
# where the first line of the file is the top-most node
|
||||
|
||||
[Document]
|
||||
|
||||
escapes: &,& "," ',' >,> <,<
|
||||
first-is-node: true
|
||||
preamble: <map version="0.8.0">
|
||||
postamble: </map>
|
||||
|
||||
[Headings]
|
||||
|
||||
before-headings:
|
||||
branch-heading: <node [url] TEXT="%%">
|
||||
leaf-heading: <node [url] TEXT="%%"/>
|
||||
after-headings: </node>
|
||||
|
||||
before-bulleted-headings:
|
||||
bulleted-branch-heading: <node [url] TEXT="*%%">
|
||||
bulleted-leaf-heading: <node [url] TEXT="*%%"/>
|
||||
after-bulleted-headings: </node>
|
||||
|
||||
before-numbered-headings:
|
||||
numbered-branch-heading: <node [url] TEXT="%c %%">
|
||||
numbered-leaf-heading: <node [url] TEXT="%c %%"/>
|
||||
after-numbered-headings: </node>
|
||||
|
||||
[Text]
|
||||
|
||||
paragraph-sep: 

|
||||
line-sep: 

|
||||
before:
|
||||
text: <node TEXT="%%"/>
|
||||
after:
|
||||
|
||||
[PrefText]
|
||||
|
||||
paragraph-sep: \n
|
||||
line-sep: \n
|
||||
before: <node TEXT="<html><body><pre>
|
||||
text: %%
|
||||
after: </pre></body></html>"></node>
|
||||
|
||||
[UserPrefText]
|
||||
|
||||
user-pref-paragraph-sep:
|
||||
before-user-preftext:
|
||||
user-preftext:
|
||||
after-user-preftext:
|
||||
|
||||
[UserText]
|
||||
|
||||
user-paragraph-sep:
|
||||
before-user-text:
|
||||
user-text:
|
||||
after-user-text:
|
||||
|
||||
[Tables]
|
||||
|
||||
before: <node TEXT="<html><body><table>
|
||||
|
||||
before-table-header: <th>
|
||||
table-header-column-left: <td>%%</td>
|
||||
table-header-column-center: <td>%%</td>
|
||||
table-header-column-right: <td>%%</td>
|
||||
after-table-header: </th>
|
||||
|
||||
before-table-row: <tr>
|
||||
table-column-left: <td>%%</td>
|
||||
table-column-center: <td>%%</td>
|
||||
table-column-right: <td>%%</td>
|
||||
after-table-row: </tr>
|
||||
|
||||
after: </table></body></html>"/>
|
||||
|
||||
[URLs]
|
||||
|
||||
url: %v
|
||||
url-attr: LINK="%u"
|
|
@ -0,0 +1,104 @@
|
|||
# otl2html - medium complexity
|
||||
# Variables:
|
||||
# %% - data
|
||||
# %l - outline level
|
||||
# %t - document title (the first line of the document)
|
||||
# %n - line number (document title is 0)
|
||||
# %N - line number of first line of block (for text blocks)
|
||||
# %p - parent line number
|
||||
# %c - my child number, a heading's order number under it's parent
|
||||
#
|
||||
# first-is-node = true for output to programs like FreeMind and GraphViz
|
||||
# where the first line of the file is the top-most node.
|
||||
|
||||
[Document]
|
||||
|
||||
escapes:
|
||||
first-is-node: true
|
||||
preamble: digraph V {
|
||||
node [shape=box style=rounded]
|
||||
# comment out rankdir to use top-to-bottom placement
|
||||
rankdir=LR
|
||||
node0 [label="%t"]
|
||||
postamble: }
|
||||
|
||||
[Headings]
|
||||
|
||||
before-headings:
|
||||
branch-heading: node%n [label="%%"]
|
||||
node%p -> node%n
|
||||
leaf-heading: node%n [label="%%"]
|
||||
node%p -> node%n
|
||||
after-headings:
|
||||
|
||||
before-bulleted-headings:
|
||||
bulleted-branch-heading: node%n [label="*%%"]
|
||||
node%p -> node%n
|
||||
bulleted-leaf-heading: node%n [label="*%%"]
|
||||
node%p -> node%n
|
||||
after-bulleted-headings:
|
||||
|
||||
before-numbered-headings:
|
||||
numbered-branch-heading: node%n [label="%c %%"]
|
||||
node%p -> node%n
|
||||
numbered-leaf-heading: node%n [label="%c %%"]
|
||||
node%p -> node%n
|
||||
after-numbered-headings:
|
||||
|
||||
[Text]
|
||||
|
||||
paragraph-sep:
|
||||
line-sep:
|
||||
before: node%n [label="
|
||||
text: %%
|
||||
after: "]
|
||||
node%p -> node%N
|
||||
|
||||
[PrefText]
|
||||
|
||||
pref-paragraph-sep:
|
||||
before:
|
||||
preftext: node%n [label="%%"]
|
||||
after:
|
||||
node%p -> node%N
|
||||
|
||||
[UserPrefText]
|
||||
|
||||
user-pref-paragraph-sep:
|
||||
before-user-preftext:
|
||||
user-preftext: node%n [label="%%"]
|
||||
after-user-preftext:
|
||||
node%p -> node%N
|
||||
|
||||
[UserText]
|
||||
|
||||
user-paragraph-sep:
|
||||
before-user-text:
|
||||
user-text node%n: [label="%%"]
|
||||
after-user-text:
|
||||
node%p -> node%N
|
||||
|
||||
[Tables]
|
||||
|
||||
before:
|
||||
|
||||
before-table-header:
|
||||
table-header-column:
|
||||
table-header-column-left:
|
||||
table-header-column-center:
|
||||
table-header-column-right:
|
||||
after-table-header:
|
||||
|
||||
before-table-row:
|
||||
table-column:
|
||||
table-column-left:
|
||||
table-column-center:
|
||||
table-column-right:
|
||||
after-table-row:
|
||||
|
||||
after:
|
||||
|
||||
[URLs]
|
||||
|
||||
url: %v
|
||||
url-attr:
|
324
pack/acp/start/vimoutliner/vimoutliner/scripts/otl_handler/Apache/OTL.pm
Executable file
324
pack/acp/start/vimoutliner/vimoutliner/scripts/otl_handler/Apache/OTL.pm
Executable file
|
@ -0,0 +1,324 @@
|
|||
#
|
||||
# VimOutliner (OTL) XHTML pretty printer for mod_perl2/apache2.
|
||||
#
|
||||
# Copyright (c) 2006-2009, Mahlon E. Smith <mahlon@martini.nu>
|
||||
# All rights reserved.
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Mahlon E. Smith nor the names of his
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
package Apache::OTL;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Apache2::Const qw/ DECLINED OK /;
|
||||
use Apache2::Request;
|
||||
use Apache2::RequestRec;
|
||||
use Apache2::RequestUtil;
|
||||
use Apache2::RequestIO;
|
||||
use Apache2::Log;
|
||||
use Time::HiRes 'gettimeofday';
|
||||
|
||||
sub handler
|
||||
{
|
||||
my $VERSION = '0.6';
|
||||
my $ID = '$Id$';
|
||||
my $r = shift;
|
||||
my $t0 = Time::HiRes::gettimeofday;
|
||||
my (
|
||||
$file, # the absolute file path
|
||||
$title, # the file's title
|
||||
$uri, # the file uri
|
||||
$data, # file contents
|
||||
@blocks, # todo groupings
|
||||
$mtime, # last modification time of otl file
|
||||
$get, # get arguments (sorting, etc)
|
||||
%opt, # options from otl file
|
||||
);
|
||||
|
||||
# sanity checks
|
||||
return DECLINED unless $r->method eq 'GET';
|
||||
|
||||
( $file, $uri ) = ( $r->filename, $r->uri );
|
||||
return DECLINED unless -e $file;
|
||||
$mtime = localtime( (stat(_))[9] );
|
||||
|
||||
my $req = Apache2::Request->new($r);
|
||||
$get = $req->param || {};
|
||||
|
||||
my %re = (
|
||||
title => qr/(?:.+)?\/(.+).otl$/i,
|
||||
percent => qr/(\[.\]) (\d+)%/,
|
||||
todo => qr/(\[_\]) /,
|
||||
done => qr/(\[X\]) /,
|
||||
user => qr/^(?:\t+)?\<(.+)/,
|
||||
user_wrap => qr/^(?:\t+)?\>(.+)/,
|
||||
body_wrap => qr/^(?:\t+)?:(.+)/,
|
||||
body => qr/^(?:\t+)?;(.+)/,
|
||||
time => qr/(\d{2}:\d{2}:\d{2})/,
|
||||
date => qr/(\d{2,4}-\d{2}-\d{2})/,
|
||||
subitem => qr/^\t(?!\t)/,
|
||||
remove_tabs => qr/^(?:\t+)?(.+)/,
|
||||
linetext => qr/^(?:\[.\] (?:\d+%)?)? (.+)/,
|
||||
|
||||
comma_sep => qr/(?:\s+)?\,(?:\s+)?/,
|
||||
hideline => qr/(?:\t+)?\#/,
|
||||
);
|
||||
|
||||
# snag file
|
||||
open OTL, $file
|
||||
or ( $r->log_error("Unable to read $file: $!") && return DECLINED );
|
||||
do {
|
||||
local $/ = undef;
|
||||
$data = <OTL>; # shlorp
|
||||
};
|
||||
close OTL;
|
||||
|
||||
# just spit out the plain otl if requested.
|
||||
if ( $get->{'show'} && $get->{show} eq 'source' ) {
|
||||
$r->content_type('text/plain');
|
||||
$r->print( $data );
|
||||
return OK;
|
||||
}
|
||||
|
||||
# divide each outline into groups
|
||||
# skip blocks that start with a comment '#'
|
||||
@blocks = grep { $_ !~ /^\#/ } split /\n\n+/, $data;
|
||||
|
||||
# get optional settings and otl title
|
||||
{
|
||||
my $settings = shift @blocks;
|
||||
if ($settings =~ $re{user}) {
|
||||
%opt = map { split /=/ } split /\s?:/, $1;
|
||||
}
|
||||
|
||||
# if the first group wasn't a comment,
|
||||
# we probably just aren't using a settings
|
||||
# line. push the group back into place.
|
||||
else {
|
||||
unshift @blocks, $settings;
|
||||
}
|
||||
}
|
||||
|
||||
# Now that we have tried to detect settings,
|
||||
# remove any level 0 blocks that are user data.
|
||||
@blocks = grep { $_ !~ /^[\<\>]/ } @blocks;
|
||||
|
||||
# GET args override settings
|
||||
$opt{$_} = $get->{$_} foreach keys %$get;
|
||||
|
||||
# set title (fallback to file uri)
|
||||
$title =
|
||||
$opt{title}
|
||||
? $opt{title}
|
||||
: $1 if $uri =~ $re{title};
|
||||
|
||||
# start html output
|
||||
$r->content_type('text/html');
|
||||
$r->print(<<EHTML);
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html>
|
||||
<!--
|
||||
generated by otl_handler $VERSION
|
||||
Mahlon E. Smith <mahlon\@martini.nu>
|
||||
http://projects.martini.nu/apache-otl/
|
||||
|
||||
Get VimOutliner at: http://www.vimoutliner.org/
|
||||
-->
|
||||
<head>
|
||||
<title>$title</title>
|
||||
EHTML
|
||||
|
||||
# optional styles
|
||||
if ( $opt{style} ) {
|
||||
foreach ( split /$re{'comma_sep'}/, $opt{style} ) {
|
||||
my $media = $_ =~ /print/ ? 'print' : 'screen';
|
||||
print qq{\t<link href="$_" rel="stylesheet" media="$media" type="text/css" />\n};
|
||||
}
|
||||
}
|
||||
|
||||
# optional javascript
|
||||
if ( $opt{js} ) {
|
||||
$r->print( "\t<script type=\"text/javascript\" src=\"$_\"></script>\n" )
|
||||
foreach split /$re{'comma_sep'}/, $opt{js};
|
||||
$r->print( ' ' x 4, "</head>\n" );
|
||||
$r->print( ' ' x 4, "<body>\n" );
|
||||
} else {
|
||||
$r->print(<<EHTML);
|
||||
</head>
|
||||
<body>
|
||||
EHTML
|
||||
}
|
||||
|
||||
# title, last modification times
|
||||
$r->print("<div class=\"header\">$opt{title}</div>\n") if $opt{title};
|
||||
$r->print("<div class=\"last_mod\">Last modified: $mtime</div>\n") if $opt{last_mod};
|
||||
if ($opt{legend}) {
|
||||
$r->print(<<EHTML);
|
||||
<div class="legend">
|
||||
<span class="done">Item completed</span><br />
|
||||
<span class="todo">Item is incomplete</span><br />
|
||||
</div>
|
||||
EHTML
|
||||
}
|
||||
|
||||
# sorter
|
||||
if ($opt{sort}) {
|
||||
my %sorts = (
|
||||
alpha => 'alphabetical',
|
||||
percent => 'percentages',
|
||||
);
|
||||
$r->print("<div class=\"sort\">Sort: \n");
|
||||
foreach (sort keys %sorts) {
|
||||
if ($opt{sorttype} eq $_ && $opt{sortrev}) {
|
||||
$r->print("<a href=\"$uri?sorttype=$_\">$sorts{$_}</a> ");
|
||||
} elsif ($opt{sorttype} eq $_ && ! $opt{sortrev}) {
|
||||
$r->print("<a href=\"$uri?sorttype=$_&sortrev=1\">$sorts{$_}</a> ");
|
||||
} else {
|
||||
$r->print("<a href=\"$uri?sorttype=$_\">$sorts{$_}</a> ");
|
||||
}
|
||||
}
|
||||
$r->print("</div>\n");
|
||||
}
|
||||
|
||||
foreach my $block ( sort { sorter(\%opt, \%re) } @blocks ) {
|
||||
# separate outline items
|
||||
my @lines;
|
||||
foreach my $line ( split /\n/, $block ) {
|
||||
push @lines, $line unless $line =~ $re{hideline} ||
|
||||
$line =~ $re{user} || $line =~ $re{user_wrap};
|
||||
}
|
||||
|
||||
my $data = [];
|
||||
|
||||
# build structure and get item counts
|
||||
my ( $subs, $comments, $subsubs ) = ( 0, 0, 0 );
|
||||
foreach ( @lines ) {
|
||||
if (/$re{body_wrap}/) {
|
||||
$comments++;
|
||||
}
|
||||
elsif (/$re{subitem}/) {
|
||||
$subs++;
|
||||
}
|
||||
|
||||
my $level = 0;
|
||||
$level = $1 =~ tr/\t/\t/ if /^(\t+)/;
|
||||
$level++;
|
||||
|
||||
s#$re{remove_tabs}#$1# unless $opt{'debug'};
|
||||
push @$data, [ $level, $_ ];
|
||||
}
|
||||
$subsubs = ( scalar @lines - 1 ) - $subs - $comments;
|
||||
|
||||
# begin parsing structure
|
||||
$r->print("<div class=\"outline\">\n");
|
||||
$r->print("<ul>\n") unless $opt{'debug'};
|
||||
my $i = 0;
|
||||
foreach ( @$data ) {
|
||||
my ( $level, $line ) = @$_;
|
||||
|
||||
if ( $opt{'debug'} ) {
|
||||
my $in = " " x $level x 4;
|
||||
$r->print( "$level:$in $line<br />\n" );
|
||||
next;
|
||||
}
|
||||
|
||||
my $next_level = $data->[ $i+1 ] ? $data->[ $i+1 ]->[0] : 0;
|
||||
my $in = "\t" x $level;
|
||||
|
||||
$line =~ s#$re{'time'}#<span class="time">$1</span>#g;
|
||||
$line =~ s#$re{date}#<span class="date">$1</span>#g;
|
||||
$line =~ s#$re{percent}#$1 <span class="percent">$2%</span>#;
|
||||
|
||||
# append counts
|
||||
if ( $i == 0 && $opt{counts} && $line !~ $re{comment} ) {
|
||||
my $itmstr = $subs == 1 ? 'item' : 'items';
|
||||
my $sitmstr = $subsubs == 1 ? 'subitem' : 'subitems';
|
||||
$line .= " <span class=\"counts\">$subs $itmstr, $subsubs $sitmstr</span>";
|
||||
}
|
||||
|
||||
my $li_class = '>';
|
||||
$li_class = ' class="todo">' if $line =~ s#$re{todo}##;
|
||||
$li_class = ' class="done">' if $line =~ s#$re{done}##;
|
||||
$li_class = ' class="comment_pre">' if $line =~ s#$re{body}#$1#;
|
||||
$li_class = ' class="comment">' if $line =~ s#$re{body_wrap}#$1#;
|
||||
|
||||
if ( $next_level == $level || $next_level == 0 ) {
|
||||
$r->print( "$in<li" . $li_class . "$line</li>\n" );
|
||||
}
|
||||
|
||||
elsif ( $next_level < $level ) {
|
||||
$r->print( "$in<li" . $li_class . "$line</li>\n" );
|
||||
for (my $x = $level - 1; $x >= $next_level; $x--) {
|
||||
my $in = "\t" x $x;
|
||||
$r->print( "$in</ul>\n$in</li>\n" );
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
# implicit: $next_level > $level AND $next_level != 0
|
||||
$r->print("$in<li" . $li_class . "$line\n$in<ul>\n");
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
unless ( $opt{'debug'} ) {
|
||||
for (my $x = $data->[ scalar @$data - 1]->[0] - 1; $x > 0; $x--) {
|
||||
my $in = "\t" x $x;
|
||||
$r->print( "$in</ul>\n$in</li>\n" );
|
||||
}
|
||||
$r->print( "</ul>\n" );
|
||||
}
|
||||
$r->print( "</div>\n\n" );
|
||||
}
|
||||
|
||||
my $t1 = Time::HiRes::gettimeofday;
|
||||
my $td = sprintf("%0.3f", $t1 - $t0);
|
||||
$r->print(" <div class=\"timer\">OTL parsed in $td secs</div>\n") if $opt{timer};
|
||||
$r->print(<<EHTML);
|
||||
</body>
|
||||
</html>
|
||||
EHTML
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
sub sorter
|
||||
{
|
||||
my ($opt, $re) = @_;
|
||||
return 0 unless $opt->{sorttype};
|
||||
my ($sa, $sb);
|
||||
if ($opt->{sorttype} eq 'percent') {
|
||||
$sa = $2 if $a =~ $re->{percent};
|
||||
$sb = $2 if $b =~ $re->{percent};
|
||||
return $opt->{sortrev} ? $sb <=> $sa : $sa <=> $sb;
|
||||
}
|
||||
else {
|
||||
$sa = $1 if $a =~ $re->{linetext};
|
||||
$sb = $1 if $b =~ $re->{linetext};
|
||||
return $opt->{sortrev} ? $sb cmp $sa : $sa cmp $sb;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
|
||||
WHAT IS THIS?
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Vimoutliner already comes with some otl to HTML converters that work
|
||||
quite well. I maintain a few different otl files, that are displayed
|
||||
on a internal intranet - the step of converting to HTML on every little
|
||||
change before upload was becoming mildly irritating, and countering my
|
||||
near legendary laziness.
|
||||
|
||||
This mod_perl handler teaches apache how to pretty print otl natively.
|
||||
|
||||
Now, I can just edit the otl files directly - skip the conversion step
|
||||
altogether, and let Apache make some delicious looking outlines.
|
||||
|
||||
|
||||
INSTALLATION
|
||||
---------------------------------------------------------------------
|
||||
|
||||
First of all, prerequisites!
|
||||
|
||||
- apache2
|
||||
- mod_perl2
|
||||
- libapreq2 (Apache2::Request)
|
||||
|
||||
Add the following lines in your httpd.conf, or in a
|
||||
separate otl.conf in the apache Includes directory:
|
||||
|
||||
-------------------------
|
||||
PerlSwitches -I/path/to/perl/libraries
|
||||
PerlModule Apache::OTL
|
||||
|
||||
<FilesMatch ".*\.otl">
|
||||
SetHandler perl-script
|
||||
PerlResponseHandler Apache::OTL
|
||||
</FilesMatch>
|
||||
-------------------------
|
||||
|
||||
Doublecheck that your apreq2 module is setup to load, as well.
|
||||
|
||||
That's it. Apache will now pretty-print all your otl files.
|
||||
|
||||
|
||||
SETTINGS
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Settings for the otl_handler are stored on the first line of the otl
|
||||
files themselves, prefixed by the 'user no wrap' character, '<'. See
|
||||
the sample.otl for an example settings line. All settings are entirely
|
||||
optional.
|
||||
|
||||
title
|
||||
Type: string
|
||||
Default: filename
|
||||
|
||||
The title of the OTL. Used as a header, and the html title.
|
||||
If this is not set, the html title is derived from the filename.
|
||||
|
||||
|
||||
style
|
||||
Type: string
|
||||
Default: none
|
||||
|
||||
A path to css style(s).
|
||||
Comma separated values load different files in order.
|
||||
Media type defaults to 'screen', if the css name contains the
|
||||
string 'print' anywhere, the media type is changed to print.
|
||||
|
||||
:style=/css/otl_style.css,/css/print_style.css
|
||||
|
||||
js
|
||||
Type: string
|
||||
Default: none
|
||||
|
||||
Use javascript? If set, loads an external javascript library.
|
||||
Comma separated values load diff files in order.
|
||||
|
||||
|
||||
last_mod
|
||||
Type: boolean
|
||||
Default: 0
|
||||
|
||||
Show modification time of the otl file?
|
||||
|
||||
|
||||
legend
|
||||
Type: boolean
|
||||
Default: 0
|
||||
|
||||
Display small legend for todo and done items?
|
||||
|
||||
|
||||
sort
|
||||
Type: boolean
|
||||
Default: 0
|
||||
|
||||
Show sort links?
|
||||
|
||||
|
||||
sorttype
|
||||
Type: string
|
||||
Default: none
|
||||
|
||||
Default sorting method. Valid values are
|
||||
percent
|
||||
alpha
|
||||
|
||||
|
||||
sortrev
|
||||
Type: boolean
|
||||
Default: 0
|
||||
|
||||
Should we default to reverse sorting?
|
||||
|
||||
|
||||
counts
|
||||
Type: boolean
|
||||
Default: 0
|
||||
|
||||
Count and display sub items?
|
||||
|
||||
|
||||
timer
|
||||
Type: boolean
|
||||
Default: 0
|
||||
|
||||
Display how long the parser took to generate the html?
|
||||
|
||||
|
||||
|
||||
INCLUDED FILES
|
||||
---------------------------------------------------------------------
|
||||
|
||||
/Apache/OTL.pm
|
||||
The mod_perl content handler.
|
||||
|
||||
/javascript/*
|
||||
Example (but functional!) javascript. Create line numbers,
|
||||
various eye candies, and clickable folds.
|
||||
|
||||
This requires the 'jquery.js' library, also included.
|
||||
|
||||
/sample.otl
|
||||
An example vimoutliner file, with optional settings.
|
||||
|
||||
/styles/*
|
||||
"Theme" examples for customizing OTL display.
|
||||
|
||||
|
||||
ACKNOWLEDGEMENTS
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Thanks to Nathan Dabney <nathan.dabney@gmail.com> and
|
||||
Michael Granger <ged@faeriemud.org> for their help and advice!
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
PerlModule Apache2::Reload
|
||||
PerlInitHandler Apache2::Reload
|
||||
PerlSetVar ReloadAll Off
|
||||
PerlSetVar ReloadModules "Apache::OTL"
|
||||
PerlSetVar ReloadConstantRedefineWarnings Off
|
12
pack/acp/start/vimoutliner/vimoutliner/scripts/otl_handler/javascript/jquery.js
vendored
Normal file
12
pack/acp/start/vimoutliner/vimoutliner/scripts/otl_handler/javascript/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,38 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
// slide everything open on new page
|
||||
$(".outline:hidden").slideToggle("slow", function(){
|
||||
$(".percent:hidden").fadeIn("slow");
|
||||
});
|
||||
|
||||
// re-activate links (the event is stomped on by the li event)
|
||||
$(".outline a").click(function(){ window.location.href = this });
|
||||
|
||||
// highlight clicked items
|
||||
$("li").not("[ul]").click(function(){ $(this).toggleClass("selected") });
|
||||
|
||||
// add line numbers
|
||||
var line_counter = 0;
|
||||
$("li").each(function(){
|
||||
var str = '<span class="linenum">' + ++line_counter + ':</span>';
|
||||
$(this).prepend(str);
|
||||
});
|
||||
|
||||
// attach folds
|
||||
$(".outline ul li").toggle(
|
||||
|
||||
// hide
|
||||
function(){
|
||||
if ( $(this).children("ul").size() == 0 ) return;
|
||||
$(this).children("ul").slideUp("slow");
|
||||
$(this).find(".linenum").addClass("linenum-folded");
|
||||
},
|
||||
|
||||
// show
|
||||
function(){
|
||||
$(this).children("ul").slideDown("slow");
|
||||
$(this).find(".linenum").removeClass("linenum-folded");
|
||||
}
|
||||
);
|
||||
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
$(document).ready(function(){
|
||||
|
||||
// append content div
|
||||
$("body").prepend("<div id=\"content\">test</div>");
|
||||
$("#content").hide();
|
||||
|
||||
// FIXME - document.width + document.height
|
||||
$(".outline").click(function(){
|
||||
$("#content").html( $(this).html() );
|
||||
$("body").background("#7b7c8c");
|
||||
$("#content").show();
|
||||
});
|
||||
|
||||
$("#content").click(function(){
|
||||
$(this).hide();
|
||||
$("body").background("#acadc3");
|
||||
});
|
||||
|
||||
// re-activate links (the event is stomped on by the li event)
|
||||
$(".outline a").click(function(){ window.location.href = this; return false; });
|
||||
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
<:title=Sample OTL list :counts=1 :timer=1 :style=styles/theme1.css :legend=1 :last_mod=1
|
||||
|
||||
: Theme examples:
|
||||
: <a href="sample.otl">basic</a> <a href="sample.otl?counts=0&style=styles/theme2.css&legend=0&js=/javascript/jquery.js,/javascript/theme2.js">advanced</a> <a href="sample.otl?counts=0&style=styles/theme3.css&legend=0&timer=0&js=/javascript/jquery.js,/javascript/theme3.js&sort=1">advanced2</a>
|
||||
|
||||
[_] 29% Things to get for party
|
||||
[_] 25% Food
|
||||
[_] Chips
|
||||
[_] Dips
|
||||
[X] Honey roasted peanuts
|
||||
[_] Sausage
|
||||
[_] 33% Party favors
|
||||
[_] Hats
|
||||
[_] Whistles
|
||||
[X] Beer bong
|
||||
|
||||
[_] 19% House projects
|
||||
[_] 25% Paint
|
||||
[_] 50% Buy supplies
|
||||
[_] Paint
|
||||
[X] Brushes
|
||||
[X] Trays 2006-09-14
|
||||
[_] Overalls
|
||||
[_] 0% Rooms done
|
||||
[_] Bathroom
|
||||
[_] Bedroom
|
||||
: Red?
|
||||
[_] 13% Upgrade electrical
|
||||
[_] 2 circuits to computer room
|
||||
[_] 40% Get equipment
|
||||
[X] Romex wire
|
||||
[_] Entry feed wire
|
||||
: How much of this do I really need? I should probably go out to the street and measure stuff.
|
||||
: Make sure the inspector has access to examine stuff on side of house.
|
||||
[_] Service meter
|
||||
[X] Grounding rods
|
||||
[_] Breakers
|
||||
[_] Learn about electricity
|
||||
[_] Don't die
|
|
@ -0,0 +1,88 @@
|
|||
|
||||
body
|
||||
{
|
||||
width: 600px;
|
||||
font-size: 0.9em;
|
||||
font-family: sans;
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
list-style-type: none;
|
||||
line-height: 1.5em;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.date
|
||||
{
|
||||
font-size: 0.6em;
|
||||
}
|
||||
|
||||
.outline
|
||||
{
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.percent
|
||||
{
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.comment, .counts
|
||||
{
|
||||
font-size: 0.7em;
|
||||
line-height: 1em;
|
||||
padding-top: 2px;
|
||||
margin-bottom: 5px;
|
||||
font-family: sans;
|
||||
}
|
||||
|
||||
.comment_pre
|
||||
{
|
||||
font-style: normal;
|
||||
font-family: courier;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.counts
|
||||
{
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.counts:before { content: "("; }
|
||||
.counts:after { content: ")"; }
|
||||
|
||||
.todo
|
||||
{
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.done
|
||||
{
|
||||
background-color: #f4f4f4;
|
||||
color: #777;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.done:before
|
||||
{
|
||||
font-size: 1.5em;
|
||||
color: green;
|
||||
content: "\2611 ";
|
||||
}
|
||||
|
||||
.todo:before
|
||||
{
|
||||
font-size: 1.5em;
|
||||
color: #777;
|
||||
content: "\2610 ";
|
||||
}
|
||||
|
||||
.legend .todo, .legend .done { border: 0 }
|
||||
.legend
|
||||
{
|
||||
margin-bottom: 30px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
|
||||
body
|
||||
{
|
||||
background-color: #444;
|
||||
font: 11px/1.8em sans-serif;
|
||||
margin: 0;
|
||||
padding-bottom: 50px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
a, a:visited
|
||||
{
|
||||
text-decoration: none;
|
||||
color: #7f9ab5;
|
||||
}
|
||||
|
||||
.header
|
||||
{
|
||||
background-color: #aaa;
|
||||
padding: 3px 0 3px 120px;
|
||||
margin-top: 50px;
|
||||
color: #3a5f85;
|
||||
border-top: 5px solid #333;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.last_mod
|
||||
{
|
||||
padding-left: 120px;
|
||||
background-color: #333;
|
||||
border-bottom: 1px solid #000;
|
||||
font-size: 0.85em;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.percent
|
||||
{
|
||||
display: none;
|
||||
color: #7f9ab5;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
left: 115px;
|
||||
}
|
||||
|
||||
.linenum
|
||||
{
|
||||
color: #7f9ab5;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
font-size: 9px;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
width: 60px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.linenum-folded
|
||||
{
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.timer
|
||||
{
|
||||
color: #666;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.outline
|
||||
{
|
||||
width: 400px;
|
||||
margin: 20px 0 0 150px;
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.outline ul
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0 10px 0 5px;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.outline ul li
|
||||
{
|
||||
padding: 0 0 0 10px;
|
||||
display: block;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.outline ul li:hover
|
||||
{
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.outline ul li ul li
|
||||
{
|
||||
border-left: 1px solid #666;
|
||||
color: #ccc;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.outline ul li ul li:hover
|
||||
{
|
||||
border-left: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.done
|
||||
{
|
||||
color: #777 !important;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.done:after
|
||||
{
|
||||
font-size: 0.9em;
|
||||
content: " (done)";
|
||||
}
|
||||
|
||||
.comment
|
||||
{
|
||||
padding-right: 2px !important;
|
||||
font-style: italic;
|
||||
border-top: 1px solid #666;
|
||||
border-bottom: 1px solid #666;
|
||||
border-right: 1px solid #666;
|
||||
}
|
||||
|
||||
.comment_pre
|
||||
{
|
||||
font-style: normal;
|
||||
font-family: courier;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.comment:hover
|
||||
{
|
||||
border-top: 1px solid #aaa;
|
||||
border-bottom: 1px solid #aaa;
|
||||
border-right: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.selected
|
||||
{
|
||||
background-color: #3d3d3d;
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
|
||||
body
|
||||
{
|
||||
background-color: #acadc3;
|
||||
font: 12px Verdana, sans-serif;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a, a:visited
|
||||
{
|
||||
text-decoration: none;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.header
|
||||
{
|
||||
margin-top: 40px;
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.header:after { content: " ----|" }
|
||||
.header:before { content: "|---- " }
|
||||
|
||||
.last_mod { font-size: .85em; }
|
||||
.percent { font-weight: bold; }
|
||||
|
||||
.sort
|
||||
{
|
||||
margin-bottom: 30px;
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
.outline
|
||||
{
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
padding: 20px;
|
||||
border: 1px solid #8082a9;
|
||||
margin-left: 10px;
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.outline:hover
|
||||
{
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
.outline ul, #content ul
|
||||
{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.outline ul li ul li { display: none; }
|
||||
|
||||
#content ul li ul { padding-left: 20px; }
|
||||
|
||||
#content ul li
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: 1.5em;
|
||||
text-align: center;
|
||||
color: #3a3d85;
|
||||
}
|
||||
|
||||
#content ul li ul li
|
||||
{
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
font-size: 10px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#content .done { color: #777; }
|
||||
.comment { font-style: italic; }
|
||||
|
||||
#content ul li .percent { color: #ff7e00; }
|
||||
#content ul li ul li .percent { color: #000; }
|
||||
|
||||
#content .comment
|
||||
{
|
||||
font-style: italic;
|
||||
border-left: 1px solid #999;
|
||||
padding-left: 5px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
#content .comment_pre
|
||||
{
|
||||
font-style: normal;
|
||||
font-family: courier;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#content
|
||||
{
|
||||
position: absolute;
|
||||
left: 15%;
|
||||
width: 60%;
|
||||
height: 80%;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
border: 2px solid #3a3d85;
|
||||
padding: 10px;
|
||||
}
|
||||
|
212
pack/acp/start/vimoutliner/vimoutliner/scripts/otlgrep.py
Executable file
212
pack/acp/start/vimoutliner/vimoutliner/scripts/otlgrep.py
Executable file
|
@ -0,0 +1,212 @@
|
|||
#!/usr/bin/python2
|
||||
# otlgrep.py
|
||||
# grep an outline for a regex and return the branch with all the leaves.
|
||||
#
|
||||
# Copyright 2005 Noel Henson All rights reserved
|
||||
|
||||
###########################################################################
|
||||
# Basic function
|
||||
#
|
||||
# This program searches an outline file for a branch that contains
|
||||
# a line matching the regex argument. The parent headings (branches)
|
||||
# and the children (sub-branches and leaves) of the matching headings
|
||||
# are returned.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# Using this outline:
|
||||
#
|
||||
# Pets
|
||||
# Indoor
|
||||
# Cats
|
||||
# Sophia
|
||||
# Hillary
|
||||
# Rats
|
||||
# Finley
|
||||
# Oliver
|
||||
# Dogs
|
||||
# Kirby
|
||||
# Outdoor
|
||||
# Dogs
|
||||
# Kirby
|
||||
# Hoover
|
||||
# Goats
|
||||
# Primrose
|
||||
# Joey
|
||||
#
|
||||
# a grep for Sophia returns:
|
||||
#
|
||||
# Indoor
|
||||
# Cats
|
||||
# Sophia
|
||||
#
|
||||
# a grep for Dogs returns:
|
||||
#
|
||||
# Indoor
|
||||
# Dogs
|
||||
# Kirby
|
||||
# Hoover
|
||||
# Outdoor
|
||||
# Dogs
|
||||
# Kirby
|
||||
# Hoover
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
###########################################################################
|
||||
# include whatever mdules we need
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
###########################################################################
|
||||
# global variables
|
||||
|
||||
debug = 0
|
||||
ignorecase = 0
|
||||
pattern = ""
|
||||
inputfiles = []
|
||||
|
||||
###########################################################################
|
||||
# function definitions# usage
|
||||
#
|
||||
# print debug statements
|
||||
# input: string
|
||||
# output: string printed to standard out
|
||||
|
||||
|
||||
def dprint(*vals):
|
||||
global debug
|
||||
if debug != 0:
|
||||
print vals
|
||||
|
||||
|
||||
# usage
|
||||
# print the simplest form of help
|
||||
# input: none
|
||||
# output: simple command usage is printed on the console
|
||||
def showUsage():
|
||||
print """
|
||||
Usage:
|
||||
otlgrep.py [options] pattern [file...]
|
||||
Options
|
||||
-i Ignore case
|
||||
--help Show help.
|
||||
[file...] is zero or more files to search. Wildcards are supported.
|
||||
if no file is specified, input is expected on stdin.
|
||||
output is on STDOUT
|
||||
"""
|
||||
|
||||
|
||||
# getArgs
|
||||
# Check for input arguments and set the necessary switches
|
||||
# input: none
|
||||
# output: possible console output for help, switch variables may be set
|
||||
|
||||
def getArgs():
|
||||
global debug, pattern, inputfiles, ignorecase
|
||||
if (len(sys.argv) == 1):
|
||||
showUsage()
|
||||
sys.exit()()
|
||||
else:
|
||||
for i in range(len(sys.argv)):
|
||||
if (i != 0):
|
||||
if (sys.argv[i] == "-d"):
|
||||
debug = 1 # test for debug flag
|
||||
elif (sys.argv[i] == "-i"):
|
||||
ignorecase = 1 # test for debug flag
|
||||
elif (sys.argv[i] == "-?"): # test for help flag
|
||||
showUsage() # show the help
|
||||
sys.exit() # exit
|
||||
elif (sys.argv[i] == "--help"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i][0] == "-"):
|
||||
print "Error! Unknown option. Aborting"
|
||||
sys.exit()
|
||||
else: # get the input file name
|
||||
if (pattern == ""):
|
||||
pattern = sys.argv[i]
|
||||
else:
|
||||
inputfiles.append(sys.argv[i])
|
||||
|
||||
|
||||
# getLineLevel
|
||||
# get the level of the current line (count the number of tabs)
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a number 1 is the lowest
|
||||
def getLineLevel(linein):
|
||||
strstart = linein.lstrip() # find the start of text in line
|
||||
x = linein.find(strstart) # find the text index in the line
|
||||
n = linein.count("\t", 0, x) # count the tabs
|
||||
return(n) # return the count + 1 (for level)
|
||||
|
||||
|
||||
# processFile
|
||||
# split an outline file
|
||||
# input: file - the filehandle of the file we are splitting
|
||||
# output: output files
|
||||
def processFile(file):
|
||||
global debug, pattern, ignorecase
|
||||
|
||||
parents = []
|
||||
parentprinted = []
|
||||
for i in range(10):
|
||||
parents.append("")
|
||||
parentprinted.append(0)
|
||||
|
||||
matchlevel = 0
|
||||
line = file.readline() # read the outline title
|
||||
# and discard it
|
||||
line = file.readline() # read the first parent heading
|
||||
while (line != ""):
|
||||
level = getLineLevel(line)
|
||||
parents[level] = line
|
||||
parentprinted[level] = 0
|
||||
if (ignorecase == 1):
|
||||
linesearch = re.search(pattern, line.strip(), re.I)
|
||||
else:
|
||||
linesearch = re.search(pattern, line.strip())
|
||||
if (linesearch is not None):
|
||||
matchlevel = level
|
||||
for i in range(level): # print my ancestors
|
||||
if (parentprinted[i] == 0):
|
||||
print parents[i][:-1]
|
||||
parentprinted[i] = 1
|
||||
print parents[level][:-1] # print myself
|
||||
line = file.readline()
|
||||
while (line != "") and (getLineLevel(line) > matchlevel):
|
||||
print line[:-1]
|
||||
line = file.readline()
|
||||
else:
|
||||
line = file.readline()
|
||||
|
||||
|
||||
# main
|
||||
# split an outline
|
||||
# input: args and input file
|
||||
# output: output files
|
||||
|
||||
def main():
|
||||
global inputfiles, debug
|
||||
getArgs()
|
||||
if (len(inputfiles) == 0):
|
||||
processFile(sys.stdin)
|
||||
else:
|
||||
for i in range(len(inputfiles)):
|
||||
file = open(inputfiles[i], "r")
|
||||
processFile(file)
|
||||
file.close()
|
||||
|
||||
main()
|
12
pack/acp/start/vimoutliner/vimoutliner/scripts/otlhead.sh
Executable file
12
pack/acp/start/vimoutliner/vimoutliner/scripts/otlhead.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
echo " Usage: otlhead level < file"
|
||||
echo " Keep the number of levels specified, remove the rest."
|
||||
echo " Great for generating summaries."
|
||||
echo " level - the number of levels to include"
|
||||
echo " file - an otl file"
|
||||
echo " input - standard in"
|
||||
echo " output - standard out"
|
||||
exit 0
|
||||
fi
|
||||
sed "/^\(\t\)\{$1\}.*$/ { D }"
|
191
pack/acp/start/vimoutliner/vimoutliner/scripts/otlsplit.py
Executable file
191
pack/acp/start/vimoutliner/vimoutliner/scripts/otlsplit.py
Executable file
|
@ -0,0 +1,191 @@
|
|||
#!/usr/bin/python2
|
||||
# otlslit.py
|
||||
# split an outline into several files.
|
||||
#
|
||||
# Copyright 2005 Noel Henson All rights reserved
|
||||
|
||||
###########################################################################
|
||||
# Basic function
|
||||
#
|
||||
# This program accepts text outline files and splits them into
|
||||
# several smaller files. The output file names are produced from the
|
||||
# heading names of the parents.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
###########################################################################
|
||||
# include whatever mdules we need
|
||||
|
||||
import sys
|
||||
import re
|
||||
###########################################################################
|
||||
# global variables
|
||||
|
||||
debug = 0
|
||||
subdir = ""
|
||||
level = 1
|
||||
title = 0
|
||||
inputfile = ""
|
||||
|
||||
|
||||
###########################################################################
|
||||
# function definitions# usage
|
||||
#
|
||||
# print debug statements
|
||||
# input: string
|
||||
# output: string printed to standard out
|
||||
def dprint(*vals):
|
||||
global debug
|
||||
if debug != 0:
|
||||
print vals
|
||||
|
||||
|
||||
# usage
|
||||
# print the simplest form of help
|
||||
# input: none
|
||||
# output: simple command usage is printed on the console
|
||||
def showUsage():
|
||||
print """
|
||||
Usage:
|
||||
otlsplit.py [options] inputfile
|
||||
Options
|
||||
-l level The number of levels to split down to. The default is 1
|
||||
-D dir Specifiy a target directory for the output files
|
||||
-t Include a title line (the parerent heading) in split files
|
||||
-h Show help.
|
||||
output is on STDOUT
|
||||
"""
|
||||
|
||||
|
||||
# getArgs
|
||||
# Check for input arguments and set the necessary switches
|
||||
# input: none
|
||||
# output: possible console output for help, switch variables may be set
|
||||
def getArgs():
|
||||
global debug, level, inputfile, title, subdir
|
||||
if (len(sys.argv) == 1):
|
||||
showUsage()
|
||||
sys.exit()()
|
||||
else:
|
||||
for i in range(len(sys.argv)):
|
||||
if (i != 0):
|
||||
if (sys.argv[i] == "-d"):
|
||||
debug = 1 # test for debug flag
|
||||
elif (sys.argv[i] == "-?"): # test for help flag
|
||||
showUsage() # show the help
|
||||
sys.exit() # exit
|
||||
elif (sys.argv[i] == "-l"): # test for the level flag
|
||||
level = int(sys.argv[i + 1]) # get the level
|
||||
i = i + 1 # increment the pointer
|
||||
elif (sys.argv[i] == "-D"): # test for the subdir flag
|
||||
subdir = sys.argv[i + 1] # get the subdir
|
||||
i = i + 1 # increment the pointer
|
||||
elif (sys.argv[i] == "-t"):
|
||||
title = 1 # test for title flag
|
||||
elif (sys.argv[i] == "--help"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i] == "-h"):
|
||||
showUsage()
|
||||
sys.exit()
|
||||
elif (sys.argv[i][0] == "-"):
|
||||
print "Error! Unknown option. Aborting"
|
||||
sys.exit()
|
||||
else: # get the input file name
|
||||
inputfile = sys.argv[i]
|
||||
|
||||
|
||||
# getLineLevel
|
||||
# get the level of the current line (count the number of tabs)
|
||||
# input: linein - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a number 1 is the lowest
|
||||
def getLineLevel(linein):
|
||||
strstart = linein.lstrip() # find the start of text in line
|
||||
x = linein.find(strstart) # find the text index in the line
|
||||
n = linein.count("\t", 0, x) # count the tabs
|
||||
return(n + 1) # return the count + 1 (for level)
|
||||
|
||||
|
||||
# convertSensitiveChars
|
||||
# get the level of the current line (count the number of tabs)
|
||||
# input: line - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a string
|
||||
def convertSensitiveChars(line):
|
||||
line = re.sub('\W', '_', line.strip())
|
||||
return(line)
|
||||
|
||||
|
||||
# makeFileName
|
||||
# make a file name from the string array provided
|
||||
# input: line - a single line that may or may not have tabs at the beginning
|
||||
# output: returns a string
|
||||
def makeFileName(nameParts):
|
||||
global debug, level, subdir
|
||||
|
||||
filename = ""
|
||||
for i in range(level):
|
||||
filename = filename + convertSensitiveChars(nameParts[i]).strip() + "-"
|
||||
filename = filename[:-1] + ".otl"
|
||||
if subdir != "":
|
||||
filename = subdir + "/" + filename
|
||||
return(filename.lower())
|
||||
|
||||
|
||||
# processFile
|
||||
# split an outline file
|
||||
# input: file - the filehandle of the file we are splitting
|
||||
# output: output files
|
||||
def processFile(ifile):
|
||||
global debug, level, title
|
||||
|
||||
nameparts = []
|
||||
for i in range(10):
|
||||
nameparts.append("")
|
||||
|
||||
outOpen = 0
|
||||
|
||||
line = ifile.readline() # read the outline title
|
||||
# and discard it
|
||||
line = ifile.readline() # read the first parent heading
|
||||
dprint(level)
|
||||
while (line != ""):
|
||||
linelevel = getLineLevel(line)
|
||||
if (linelevel < level):
|
||||
if outOpen == 1:
|
||||
ifile.close()
|
||||
outOpen = 0
|
||||
nameparts[linelevel] = line
|
||||
dprint(level, linelevel, line)
|
||||
else:
|
||||
if outOpen == 0:
|
||||
ofile = open(makeFileName(nameparts), "w")
|
||||
outOpen = 1
|
||||
if title == 1:
|
||||
dprint("title:", title)
|
||||
ofile.write(nameparts[level - 1])
|
||||
ofile.write(line[level:])
|
||||
line = file.readline()
|
||||
|
||||
|
||||
# main
|
||||
# split an outline
|
||||
# input: args and input file
|
||||
# output: output files
|
||||
def main():
|
||||
global inputfile, debug
|
||||
getArgs()
|
||||
file = open(inputfile, "r")
|
||||
processFile(file)
|
||||
file.close()
|
||||
|
||||
main()
|
15
pack/acp/start/vimoutliner/vimoutliner/scripts/otltail.sh
Executable file
15
pack/acp/start/vimoutliner/vimoutliner/scripts/otltail.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
if [ "$#" -lt 1 ] ; then
|
||||
echo " Usage: otltail level < file"
|
||||
echo " Remove the specified number of parent headings."
|
||||
echo " This is a way to promote children. It is"
|
||||
echo " useful for converting a single outline into a"
|
||||
echo " number of pages for a web site or chapters for"
|
||||
echo " a book."
|
||||
echo " level - the number of levels to include"
|
||||
echo " file - an otl file"
|
||||
echo " input - standard in"
|
||||
echo " output - standard out"
|
||||
exit 0
|
||||
fi
|
||||
sed "/^\(\t\)\{$1\}.*$/! { D }" | sed "s/^\(\t\)\{$1\}//"
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,31 @@
|
|||
" add the calendar tag file to the tag search stack
|
||||
set tags^=~/Outlines/outline_calendar/vo_calendar_tags.tag
|
||||
|
||||
" open the calendar at date
|
||||
" a:1 is executed before the jump
|
||||
function ToDate(date, ...)
|
||||
let l:precmd = a:0>0 ? a:1 : ""
|
||||
exec l:precmd
|
||||
exec "tag " . a:date . "|normal zO"
|
||||
endfunction
|
||||
|
||||
" open the calendar at a requested date
|
||||
" default is today
|
||||
" a:1 is executed before the jump
|
||||
function ToSomeDay(...)
|
||||
let l:precmd = a:0>0 ? a:1 : ""
|
||||
let l:today = strftime("%Y-%m-%d")
|
||||
let l:date = input('Date To Goto (yyyy-mm-dd): ', today)
|
||||
call ToDate(l:date, l:precmd)
|
||||
endfunction
|
||||
|
||||
" small case jumps use same window
|
||||
nmap <leader>td :call ToDate(strftime("%Y-%m-%d"))<cr>
|
||||
nmap <leader>ts :call ToSomeDay()<cr>
|
||||
nmap <leader>tc :call ToDate(expand("<cWORD>"))<cr>
|
||||
|
||||
" upper case jumps open new window
|
||||
nmap <leader>tD :call ToDate(strftime("%Y-%m-%d"),"new")<cr>
|
||||
nmap <leader>tS :call ToSomeDay("new")<cr>
|
||||
nmap <leader>tC :call ToDate(expand("<cWORD>"),"new")<cr>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
--langdef=outline
|
||||
--langmap=outline:.otl
|
||||
--regex-outline=/_tag_ set ([^ ]+)/_tag_\1/
|
||||
--regex-outline=/^\t+([1-9][0-9]{3})_([01][0-9])_([0-3][0-9])/\1-\2-\3/
|
||||
|
||||
--languages=-all,+outline
|
||||
--recurse
|
||||
|
||||
--totals=yes
|
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
# usage:
|
||||
# calendar_generator.rb <calendar_folder> <years>
|
||||
|
||||
# indent for months, days are indented one more level
|
||||
# both 0 and 1 make sense
|
||||
MONTHINDENT = 0
|
||||
|
||||
|
||||
# insert _tag_ todo and _tag_ done items under each day
|
||||
# DIARY = ["Zu erledigen", "Tagebuch", "Abrechnen"]
|
||||
# DIARY = [] # for empty days.
|
||||
DIARY = ["To do", "Diary", "Timesheet"] # deluxe edition
|
||||
|
||||
|
||||
# adapt to your preference
|
||||
# Sunday should be first, Saturday last entry
|
||||
# DAYNAMES = %w(So Mo Di Mi Do Fr Sa)
|
||||
DAYNAMES = %w(Sun Mon Tue Wed Thu Fri Sat)
|
||||
|
||||
|
||||
# January should be first, December last entry
|
||||
# MONTHNAMES = %w(Januar Februar März April Mai Juni Juli August September Oktober November Dezember)
|
||||
MONTHNAMES = %w(January February March April May June July August September October November December)
|
||||
|
||||
# you should not need to change anything below here
|
||||
# but you are welcome to write equivalent functionality
|
||||
# in your language of choice.
|
||||
# ------------------------------------------------------------
|
||||
require "date"
|
||||
|
||||
TAGFORMAT = "%.4d_%.2d_%.2d"
|
||||
|
||||
|
||||
def indent(sublevel)
|
||||
"\t"*(MONTHINDENT+sublevel)
|
||||
end
|
||||
|
||||
def month(date)
|
||||
MONTHNAMES[date.month - 1] +
|
||||
(MONTHINDENT == 0 ? " " + date.year.to_s : "")
|
||||
end
|
||||
|
||||
class Shelf
|
||||
def initialize(path)
|
||||
begin
|
||||
@shelf = File.readlines(path)
|
||||
rescue
|
||||
@shelf = Array.new
|
||||
end
|
||||
@path = path
|
||||
end
|
||||
def parse
|
||||
unless @books
|
||||
@books = Hash.new
|
||||
(0...@shelf.size).step(2) do |i|
|
||||
@books[@shelf[i].strip] = @shelf[i+1].strip
|
||||
end
|
||||
end
|
||||
end
|
||||
def save()
|
||||
File.open(@path, "w") do |out|
|
||||
@books.sort.each do |key,value|
|
||||
out.puts(key)
|
||||
out.puts("\t" + value)
|
||||
end if @books
|
||||
end
|
||||
end
|
||||
def update(year)
|
||||
re = /^_tag_calendar_#{year}/
|
||||
unless @shelf.any? { |str| re.match(str) }
|
||||
parse
|
||||
@books["_tag_calendar_#{year}"] = "#{year}.otl"
|
||||
save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update_shelf(year)
|
||||
shelf = Shelf.new(CALENDAR + "/vo_calendar_shelf.otl")
|
||||
shelf.update(year)
|
||||
end
|
||||
|
||||
CALENDAR = ARGV.shift
|
||||
|
||||
ARGV.each do |arg|
|
||||
|
||||
File.open(CALENDAR + "/" + arg + ".otl", "w") do |out|
|
||||
|
||||
update_shelf(arg)
|
||||
year = arg.to_i
|
||||
d = Date.new(year, 1, 1)
|
||||
out.puts year if MONTHINDENT == 1
|
||||
|
||||
while d.year == year
|
||||
out.puts indent(0) + month(d)
|
||||
month = d.month
|
||||
while d.month == month
|
||||
out.puts indent(1) + (TAGFORMAT % [d.year, d.month, d.day]) +
|
||||
" " + DAYNAMES[d.wday]
|
||||
DIARY.each do |item|
|
||||
out.puts indent(2) + item
|
||||
end
|
||||
d += 1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,195 @@
|
|||
Outline Calendar 1.3
|
||||
What's new
|
||||
in 1.3
|
||||
vimrc-script by Lee Bigelow for easy calendar access
|
||||
small modifications to this outline
|
||||
update from 1.2.2
|
||||
edit tagfile path in outline_calendar/vimrc
|
||||
add 'source .../outline_calendar/vimrc' to your ~/.vimrc
|
||||
in 1.2.2
|
||||
changed personal _tag_ set definition
|
||||
: it may appear anywhere, but takes only next space-delimited
|
||||
: word into account. The advantage is that I can set a tag
|
||||
: behind a calendar date and jump to the current week via
|
||||
: _tag_kalender
|
||||
in 1.2.1
|
||||
removed spurious underscores in td function
|
||||
in 1.2
|
||||
use ~/.vimoutlinerrc to avoid tagfile collisions
|
||||
,,d-dates usable as links into calendar
|
||||
calendar dates (almost) without syntactic noise
|
||||
update to documentation
|
||||
in 1.1
|
||||
we are almost votl_maketags.pl-compatible again
|
||||
you can use vo_calendar_shelf.otl to attach your calendar shelf to your outline tree
|
||||
files follow vimoutliner naming convention
|
||||
all installation files are kept within one directory
|
||||
minor refinements to console user interface
|
||||
defaults and samples are in English now
|
||||
Prerequisites
|
||||
ruby
|
||||
used for generating the skeleton calendar and the shelf
|
||||
could be replaced by perl, awk, python, ...
|
||||
maybe even by a shell script or a small forth program ;-)
|
||||
bash
|
||||
use of special variable expansion in shell-frontend
|
||||
ctags
|
||||
create the tags-file for interoutline links and calendar access
|
||||
regex support necessary
|
||||
$ ctags --version
|
||||
: Exuberant Ctags 5.5.1, Copyright (C) 1996-2003 Darren Hiebert
|
||||
: Compiled: Aug 15 2003, 21:06:30
|
||||
: Addresses: <dhiebert@users.sourceforge.net>, http://ctags.sourceforge.net
|
||||
: Optional compiled features: +wildcards, +regex
|
||||
vimoutliner
|
||||
you should already have it
|
||||
Known incompatibilities
|
||||
none
|
||||
Installation and Configuration
|
||||
Installation
|
||||
I recommend keeping all Outlines in one directory
|
||||
it's easier on ctags
|
||||
move the distribution folder there
|
||||
: $ mv outline_calendar ~/Outlines
|
||||
add another tag file to vim's lookup table
|
||||
the following line should go into $HOME/.vimrc
|
||||
: source ~/Outlines/outline_calendar/vimrc
|
||||
configure the various scripts (see below)
|
||||
source vo_calendar_ui.sh into your shell
|
||||
$HOME/.bashrc is probably a good place for this
|
||||
something like the following should do it
|
||||
$ . $HOME/Outlines/outline_calendar/vo_calendar_ui.sh
|
||||
you're ready to run
|
||||
try
|
||||
$ calgen 2005 2006 2007
|
||||
: you get three yearly calendars plus a shelf to
|
||||
: access them through _tag_xxx linking
|
||||
$ tagvout
|
||||
: this should create a tag file inside the outline
|
||||
: calendar directory
|
||||
$ td
|
||||
: now vimoutliner should be positioned on today
|
||||
$ vim
|
||||
in normal mode type \tS
|
||||
enter a date after the prompt and hit return
|
||||
the calendar should open in a new window
|
||||
Configure the calendar layout in vo_calendar_generator.rb
|
||||
Month layout
|
||||
with MONTHINDENT=1
|
||||
2006
|
||||
January
|
||||
_2006-01-01_ Sun
|
||||
_2006-01-02_ Mon
|
||||
or with MONTHINDENT=0
|
||||
January 2006
|
||||
_2006-01-01_ Sun
|
||||
_2006-01-02_ Mon
|
||||
Optional diary headings for each day
|
||||
with DIARY=[]
|
||||
_2006-01-01_ Sun
|
||||
_2006-01-02_ Mon
|
||||
with DIARY=["Todo", "Billing", "Personal notes"]
|
||||
_2006-01-01_ Sun
|
||||
Todo
|
||||
Billing
|
||||
Personal notes
|
||||
_2006-01-02_ Mon
|
||||
Todo
|
||||
Billing
|
||||
Personal notes
|
||||
change the language of the calendar
|
||||
DAYNAMES
|
||||
names of weekdays starting with Sunday
|
||||
MONTHNAMES
|
||||
names of months
|
||||
calendar skeletons
|
||||
need not be generated with the ruby script
|
||||
but we do have an "API" to keep things compatible
|
||||
: I suggest an approach that can be executed in
|
||||
: the same way as my ruby script. If you did it
|
||||
: with perl, you could call the script
|
||||
: vo_calendar_generator.pl.
|
||||
: Its first command line parameter should be the
|
||||
: directory, where the calendar files are stored,
|
||||
: the remaining parameters denote the years, for which
|
||||
: calendar skeletons should be generated.
|
||||
calendar shelf
|
||||
do not edit manually, a really stupid parser (tm) is reading this
|
||||
: it contains the _tag_ format links into the various
|
||||
: yearly calendars. It is "parsed" (if you can call it
|
||||
: that) to insert a newly created calendar in the correct
|
||||
: position.
|
||||
Configure the directory layout in vo_calendar_ui.sh
|
||||
See the comments there for further explanations
|
||||
Ideally you only have to set the variable OUTLINES, but YMMV
|
||||
Configure tag harvesting in vo_calendar_ctags.conf
|
||||
it should not need any changes
|
||||
if it does, "man 1 ctags" is your friend
|
||||
what it does, line by line
|
||||
define a new language called outline
|
||||
outline handling rules are applied only to .otl files
|
||||
recognise headings starting with "_tag_ set "
|
||||
everything after "_tag_ set " is considered as tag content
|
||||
: this provides an alternative way of defining tags
|
||||
: for both interoutline and intraoutline jumps.
|
||||
: It can safely be removed without harming the
|
||||
: outline calendar.
|
||||
: If you keep it, your non-calendar tags will be
|
||||
: stored in the calendar tagfile, too, but this should
|
||||
: not be a problem.
|
||||
recognise headings starting with a yyyy_mm_dd date
|
||||
Underscore as date separator
|
||||
are distinct from ,,d dates
|
||||
date stamps will not be jumped to
|
||||
date stamps will only be jumped from
|
||||
they are mangled to hyphens as tag marker
|
||||
plain ,,d dates can be used to enter the calendar from anywhere
|
||||
all dates typed by you are in ISO-format yyyy-mm-dd
|
||||
only tag outline files
|
||||
handle files in subdirectories, too
|
||||
show some impressive statistics
|
||||
Usage
|
||||
administrative
|
||||
once: install and configure (see above)
|
||||
rarely: generate a new calendar
|
||||
$ calgen 2005 2006 2007
|
||||
this will go a long way
|
||||
often: refresh the tag file
|
||||
$ tagvout
|
||||
you might even want to put it in your crontab
|
||||
don't rely on shell functions there, use plain commands
|
||||
modulo local changes the crontab entry would look like this:
|
||||
: */10 * * * * /usr/bin/ctags -f $HOME/.vimoutliner/vo_tags.tag --options=$HOME/Outlines/outline_calendar/vo_calendar_ctags.conf $HOME/Outlines &> /dev/null
|
||||
refresh tag file every 10 minutes
|
||||
remove the configuration line --totals, you won't need it there
|
||||
open calendar from running shell
|
||||
edit today's calendar entries
|
||||
$ td
|
||||
: vimoutliner should open on today
|
||||
: if you're running X, you'll get a gvim, otherwise a vim
|
||||
: you'll be on today's entry
|
||||
move around, add some items to the outline
|
||||
move cursor on a ISO-format date yyyy-mm-dd and <C-k> it
|
||||
edit any available day
|
||||
$ td 2005-05-04
|
||||
: release day
|
||||
open calendar from running vim session
|
||||
mappings for normal mode
|
||||
\td and \tD
|
||||
jump to today
|
||||
\tc and \tC
|
||||
jump to the date at the cursor position
|
||||
\ts and \tS
|
||||
ask for date to jump to
|
||||
Notes
|
||||
the mappings are defined as <leader>t...
|
||||
the uppercase variant opens a new window within the current session
|
||||
Author(s)
|
||||
(c) Stefan Schmiedl <s@xss.de> 2005-05-04
|
||||
Contributors:
|
||||
Lee Bigelow brought the \t? functions into existence
|
||||
License
|
||||
thou shalt neither sue nor blame me
|
||||
it's worth what you paid for it
|
||||
thou can do whatever else thou want to do with it
|
||||
just remember to have fun on the way
|
|
@ -0,0 +1,6 @@
|
|||
_tag_calendar_2003
|
||||
2003.otl
|
||||
_tag_calendar_2004
|
||||
2004.otl
|
||||
_tag_calendar_2005
|
||||
2005.otl
|
|
@ -0,0 +1,39 @@
|
|||
# parent folder of all outlines
|
||||
OUTLINES=$HOME/Outlines
|
||||
|
||||
# folder for calendar files
|
||||
# should be a subfolder of $OUTLINES
|
||||
CALENDAR=$OUTLINES/outline_calendar
|
||||
|
||||
# file for calendar tags
|
||||
CALENDARTAGS=$CALENDAR/vo_calendar_tags.tag
|
||||
|
||||
# folders to tag for interoutline links and calendar access
|
||||
# if $CALENDAR is not below $OUTLINES, you need
|
||||
# TAGFOLDERS=($OUTLINES $CALENDAR)
|
||||
TAGFOLDERS=($OUTLINES)
|
||||
|
||||
# script to generate calendar skeletons
|
||||
CALGENSCRIPT=$CALENDAR/vo_calendar_generator.rb
|
||||
|
||||
# option file for ctags
|
||||
CTAGSOPTIONS=$CALENDAR/vo_calendar_ctags.conf
|
||||
|
||||
|
||||
# you should not need to change anything below here
|
||||
# that's what all the variables above are for
|
||||
# ------------------------------------------------------------
|
||||
|
||||
function td() {
|
||||
local date
|
||||
date=${1:-`date +%Y-%m-%d`}
|
||||
${DISPLAY:+g}vim -c ":ta $date" $CALENDAR/${date%%-*}.otl
|
||||
}
|
||||
|
||||
function tagvout() {
|
||||
ctags -f $CALENDARTAGS --options=$CTAGSOPTIONS ${TAGFOLDERS[*]}
|
||||
}
|
||||
|
||||
function calgen() {
|
||||
$CALGENSCRIPT $CALENDAR $*
|
||||
}
|
198
pack/acp/start/vimoutliner/vimoutliner/scripts/outline_freemind/freemind.py
Executable file
198
pack/acp/start/vimoutliner/vimoutliner/scripts/outline_freemind/freemind.py
Executable file
|
@ -0,0 +1,198 @@
|
|||
#!/usr/bin/python2
|
||||
|
||||
'''
|
||||
usage:
|
||||
freemind.py -o [fmt] <files>, where ofmt selects output format: {otl,mm}
|
||||
|
||||
freemind.py -o otl <files>:
|
||||
Read in an freemind XML .mm file and generate a outline file
|
||||
compatable with vim-outliner.
|
||||
freemind.py -o mm <files>:
|
||||
Read in an otl file and generate an XML mind map viewable in freemind
|
||||
|
||||
NOTE:
|
||||
Make sure that you check that round trip on your file works.
|
||||
|
||||
Author: Julian Ryde
|
||||
'''
|
||||
import sys
|
||||
import getopt
|
||||
import codecs
|
||||
|
||||
import otl
|
||||
import xml.etree.ElementTree as et
|
||||
from xml.etree.ElementTree import XMLParser
|
||||
|
||||
debug = False
|
||||
|
||||
|
||||
class Outline: # The target object of the parser
|
||||
depth = -1
|
||||
indent = '\t'
|
||||
current_tag = None
|
||||
|
||||
def start(self, tag, attrib): # Called for each opening tag.
|
||||
self.depth += 1
|
||||
self.current_tag = tag
|
||||
# print the indented heading
|
||||
if tag == 'node' and self.depth > 1:
|
||||
#if 'tab' in attrib['TEXT']:
|
||||
#import pdb; pdb.set_trace()
|
||||
print (self.depth - 2) * self.indent + attrib['TEXT']
|
||||
|
||||
def end(self, tag): # Called for each closing tag.
|
||||
self.depth -= 1
|
||||
self.current_tag = None
|
||||
|
||||
def data(self, data):
|
||||
if self.current_tag == 'p':
|
||||
bodyline = data.rstrip('\r\n')
|
||||
bodyindent = (self.depth - 5) * self.indent + ": "
|
||||
#textlines = textwrap.wrap(bodytext, width=77-len(bodyindent),
|
||||
# break_on_hyphens=False)
|
||||
#for line in textlines:
|
||||
print bodyindent + bodyline
|
||||
|
||||
def close(self): # Called when all data has been parsed.
|
||||
pass
|
||||
|
||||
|
||||
def mm2otl(*arg, **kwarg):
|
||||
fname = arg[0][0]
|
||||
file = codecs.open(fname, 'r', encoding='utf-8')
|
||||
|
||||
filelines = file.readlines()
|
||||
outline = Outline()
|
||||
parser = XMLParser(target=outline, encoding='utf-8')
|
||||
parser.feed(filelines[0].encode('utf-8'))
|
||||
parser.close()
|
||||
|
||||
|
||||
# TODO body text with manual breaks
|
||||
# TODO commandline arguments for depth, maxlength etc.
|
||||
# TODO do not read whole file into memory?
|
||||
# TODO handle decreasing indent by more than one tab
|
||||
# TODO handle body text lines sometimes not ending with space
|
||||
|
||||
depth = 99
|
||||
|
||||
|
||||
def attach_note(node, textlines):
|
||||
et.ElementTree
|
||||
# Format should look like
|
||||
#<richcontent TYPE="NOTE">
|
||||
#<html>
|
||||
# <head> </head>
|
||||
# <body>
|
||||
# %s
|
||||
# </body>
|
||||
#</html>
|
||||
#</richcontent>
|
||||
notenode = et.SubElement(node, 'richcontent')
|
||||
notenode.set('TYPE', 'NOTE')
|
||||
htmlnode = et.SubElement(notenode, 'html')
|
||||
bodynode = et.SubElement(htmlnode, 'body')
|
||||
for line in textlines:
|
||||
pnode = et.SubElement(bodynode, 'p')
|
||||
pnode.text = line
|
||||
|
||||
|
||||
def otl2mm(*arg, **kwarg):
|
||||
fname = arg[0][0]
|
||||
|
||||
# node ID should be based on the line number of line in the
|
||||
# otl file for easier debugging
|
||||
#for lineno, line in enumerate(open(fname)):
|
||||
# enumerate starts at 0 I want to start at 1
|
||||
# FIXME freemind.py|107| W806 local variable 'lineno' is assigned to but never used
|
||||
lineno = 0
|
||||
|
||||
mapnode = et.Element('map')
|
||||
mapnode.set('version', '0.9.0')
|
||||
|
||||
topnode = et.SubElement(mapnode, 'node')
|
||||
topnode.set('TEXT', fname)
|
||||
|
||||
parents = [mapnode, topnode]
|
||||
|
||||
#left_side = True # POSITION="right"
|
||||
|
||||
# read otl file into memory
|
||||
filelines = codecs.open(fname, 'r', encoding='utf-8')
|
||||
|
||||
# first handle the body texts turn it into a list of headings
|
||||
# with associated body text for each one this is because the
|
||||
# body text especially multi-line is what makes it awkward.
|
||||
headings = []
|
||||
bodytexts = []
|
||||
for line in filelines:
|
||||
if otl.is_heading(line):
|
||||
headings.append(line)
|
||||
bodytexts.append([])
|
||||
else:
|
||||
# TODO this ': ' removal should go in otl.py?
|
||||
bodytexts[-1].append(line.lstrip()[2:] + '\n')
|
||||
|
||||
#import pdb; pdb.set_trace()
|
||||
oldheading = ''
|
||||
for heading, bodytext in zip(headings, bodytexts):
|
||||
if debug:
|
||||
print heading, bodytext
|
||||
|
||||
level = otl.level(heading)
|
||||
oldlevel = otl.level(oldheading)
|
||||
|
||||
if level == oldlevel:
|
||||
pass
|
||||
elif level > oldlevel:
|
||||
# about to go down in the hierarchy so add this line
|
||||
# as a parent to the stack
|
||||
# FIXME freemind.py|149| W802 undefined name 'node'
|
||||
parents.append(node)
|
||||
elif level < oldlevel:
|
||||
# about to go up in the hierarchy so remove parents from the stack
|
||||
leveldiff = oldlevel - level
|
||||
parents = parents[:-leveldiff]
|
||||
|
||||
node = et.SubElement(parents[-1], 'node')
|
||||
node.set('TEXT', heading.lstrip().rstrip('\r\n'))
|
||||
#if len(bodytext) > 0:
|
||||
attach_note(node, bodytext)
|
||||
|
||||
oldheading = heading
|
||||
|
||||
xmltree = et.ElementTree(mapnode)
|
||||
xmltree.write(sys.stdout, 'utf-8')
|
||||
print
|
||||
|
||||
|
||||
def usage():
|
||||
print "usage: %s -[mo] <files>" % (sys.argv[0])
|
||||
|
||||
|
||||
def main():
|
||||
args = sys.argv
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'moh', [""])
|
||||
except getopt.GetoptError, err:
|
||||
usage()
|
||||
print str(err)
|
||||
sys.exit(2)
|
||||
|
||||
for o, a in opts:
|
||||
if o == "-m":
|
||||
otl2mm(args)
|
||||
elif o == "-o":
|
||||
mm2otl(args)
|
||||
elif o == "-h":
|
||||
usage()
|
||||
sys.exit(0)
|
||||
else:
|
||||
usage()
|
||||
assert False, "unhandled option: %s" % o
|
||||
return args
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# vim: set noet :
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/python2
|
||||
'''Converts a freemind xml .mm file to an outline file compatable with vim
|
||||
outliner.
|
||||
|
||||
Make sure that you check that round trip on your file works.
|
||||
|
||||
Author: Julian Ryde
|
||||
'''
|
||||
import sys
|
||||
from xml.etree.ElementTree import XMLParser
|
||||
import textwrap
|
||||
import codecs
|
||||
|
||||
class Outline: # The target object of the parser
|
||||
depth = -1
|
||||
indent = '\t'
|
||||
current_tag = None
|
||||
def start(self, tag, attrib): # Called for each opening tag.
|
||||
self.depth += 1
|
||||
self.current_tag = tag
|
||||
# print the indented heading
|
||||
if tag == 'node' and self.depth > 1:
|
||||
#if 'tab' in attrib['TEXT']:
|
||||
#import pdb; pdb.set_trace()
|
||||
print (self.depth-2)*self.indent + attrib['TEXT']
|
||||
def end(self, tag): # Called for each closing tag.
|
||||
self.depth -= 1
|
||||
self.current_tag = None
|
||||
def data(self, data):
|
||||
if self.current_tag == 'p':
|
||||
bodyline = data.rstrip('\r\n')
|
||||
bodyindent = (self.depth-5)*self.indent + ": "
|
||||
#textlines = textwrap.wrap(bodytext, width=77-len(bodyindent), break_on_hyphens=False)
|
||||
#for line in textlines:
|
||||
print bodyindent + bodyline
|
||||
|
||||
def close(self): # Called when all data has been parsed.
|
||||
pass
|
||||
|
||||
outline = Outline()
|
||||
parser = XMLParser(target=outline, encoding='utf-8')
|
||||
|
||||
fname = sys.argv[1]
|
||||
file = codecs.open(fname, 'r', encoding='utf-8')
|
||||
filelines = file.readlines();
|
||||
print "filelines", type(filelines[0]), filelines[0]
|
||||
parser.feed(filelines[0].encode('utf-8'))
|
||||
parser.close()
|
|
@ -0,0 +1,26 @@
|
|||
# Some integer IDs
|
||||
# headings are 1, 2, 3, ....
|
||||
bodynowrap = -1 # ;
|
||||
bodywrap = 0 # :
|
||||
|
||||
def level(line):
|
||||
'''return the heading level 1 for top level and down and 0 for body text'''
|
||||
if line.lstrip().find(':')==0: return bodywrap
|
||||
if line.lstrip().find(';')==0: return bodynowrap
|
||||
strstart = line.lstrip() # find the start of text in lin
|
||||
x = line.find(strstart) # find the text index in the line
|
||||
n = line.count("\t",0,x) # count the tabs
|
||||
return(n+1) # return the count + 1 (for level)
|
||||
|
||||
def is_bodywrap(line):
|
||||
return level(line) == bodywrap
|
||||
|
||||
def is_bodynowrap(line):
|
||||
return level(line) == bodynowrap
|
||||
|
||||
def is_heading(line):
|
||||
return level(line) > 0
|
||||
|
||||
def is_body(line):
|
||||
return not is_heading(line)
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bin/python2
|
||||
'''Read in an otl file and generate an xml mind map viewable in freemind
|
||||
|
||||
Make sure that you check that round trip on your file works.
|
||||
|
||||
Author: Julian Ryde
|
||||
'''
|
||||
|
||||
import sys
|
||||
import os
|
||||
import xml.etree.ElementTree as et
|
||||
import otl
|
||||
import codecs
|
||||
|
||||
fname = sys.argv[1]
|
||||
max_length = 40
|
||||
depth = 99
|
||||
|
||||
debug = False
|
||||
|
||||
# TODO body text with manual breaks
|
||||
# TODO commandline arguments for depth, maxlength etc.
|
||||
# TODO do not read whole file into memory?
|
||||
# TODO handle decreasing indent by more than one tab
|
||||
# TODO handle body text lines sometimes not ending with space
|
||||
|
||||
otlfile = open(fname)
|
||||
indent = ' '
|
||||
|
||||
def attach_note(node, textlines):
|
||||
et.ElementTree
|
||||
# Format should look like
|
||||
#<richcontent TYPE="NOTE">
|
||||
#<html>
|
||||
# <head> </head>
|
||||
# <body>
|
||||
# %s
|
||||
# </body>
|
||||
#</html>
|
||||
#</richcontent>
|
||||
notenode = et.SubElement(node, 'richcontent')
|
||||
notenode.set('TYPE', 'NOTE')
|
||||
htmlnode = et.SubElement(notenode, 'html')
|
||||
headnode = et.SubElement(htmlnode, 'head')
|
||||
bodynode = et.SubElement(htmlnode, 'body')
|
||||
for line in textlines:
|
||||
pnode = et.SubElement(bodynode, 'p')
|
||||
pnode.text = line
|
||||
|
||||
# node ID should be based on the line number of line in the otl file for easier
|
||||
# debugging
|
||||
#for lineno, line in enumerate(open(fname)):
|
||||
# enumerate starts at 0 I want to start at 1
|
||||
lineno = 0
|
||||
|
||||
mapnode = et.Element('map')
|
||||
mapnode.set('version', '0.9.0')
|
||||
|
||||
topnode = et.SubElement(mapnode, 'node')
|
||||
topnode.set('TEXT', fname)
|
||||
|
||||
parents = [mapnode, topnode]
|
||||
|
||||
#left_side = True # POSITION="right"
|
||||
|
||||
# read otl file into memory
|
||||
filelines = codecs.open(fname, 'r', encoding='utf-8')
|
||||
|
||||
# remove those that are too deep or body text and pesky end of line characters
|
||||
#filelines = [line.rstrip('\r\n') for line in filelines if otl.level(line) <= depth]
|
||||
#filelines = [line for line in filelines if otl.is_heading(line)]
|
||||
|
||||
# first handle the body texts turn it into a list of headings with associated
|
||||
# body text for each one this is because the body text especially multi-line is
|
||||
# what makes it awkward.
|
||||
headings = []
|
||||
bodytexts = []
|
||||
for line in filelines:
|
||||
if otl.is_heading(line):
|
||||
headings.append(line)
|
||||
bodytexts.append([])
|
||||
else:
|
||||
# TODO this ': ' removal should go in otl.py?
|
||||
bodytexts[-1].append(line.lstrip()[2:] + '\n')
|
||||
|
||||
#import pdb; pdb.set_trace()
|
||||
oldheading = ''
|
||||
for heading, bodytext in zip(headings, bodytexts):
|
||||
if debug: print heading, bodytext
|
||||
|
||||
level = otl.level(heading)
|
||||
oldlevel = otl.level(oldheading)
|
||||
|
||||
if level == oldlevel:
|
||||
pass
|
||||
elif level > oldlevel:
|
||||
# about to go down in the hierarchy so add this line as a parent to the
|
||||
# stack
|
||||
parents.append(node)
|
||||
elif level < oldlevel:
|
||||
# about to go up in the hierarchy so remove parents from the stack
|
||||
leveldiff = oldlevel - level
|
||||
parents = parents[:-leveldiff]
|
||||
|
||||
node = et.SubElement(parents[-1], 'node')
|
||||
node.set('TEXT', heading.lstrip().rstrip('\r\n'))
|
||||
#if len(bodytext) > 0:
|
||||
attach_note(node, bodytext)
|
||||
|
||||
oldheading = heading
|
||||
|
||||
xmltree = et.ElementTree(mapnode)
|
||||
xmltree.write(sys.stdout, 'utf-8')
|
||||
print
|
|
@ -0,0 +1,27 @@
|
|||
A
|
||||
: This is some early multi-line body text which should wrap. This is some
|
||||
: early multi-line body text which should wrap. This is some early
|
||||
: multi-line body text which should wrap.
|
||||
a
|
||||
: single line body text
|
||||
b
|
||||
1
|
||||
c
|
||||
B
|
||||
d
|
||||
2
|
||||
3
|
||||
4
|
||||
C
|
||||
|
||||
This is a very long heading line that should be longer than the wrap width and so tests this case
|
||||
Heading with a tab in the middle
|
||||
: body text with tab in it
|
||||
Body text with empy line in it
|
||||
: First line
|
||||
:
|
||||
: Third line
|
||||
Difficult characters
|
||||
[_] ' " &
|
||||
Last line body text
|
||||
: This is a last line of body text
|
10
pack/acp/start/vimoutliner/vimoutliner/scripts/outline_freemind/test.sh
Executable file
10
pack/acp/start/vimoutliner/vimoutliner/scripts/outline_freemind/test.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
tmp=/tmp
|
||||
dirname=`dirname $0`
|
||||
fname=$dirname/test.otl
|
||||
[ -n "$1" ] && fname=$1
|
||||
|
||||
$dirname/freemind.py -m $fname > $tmp/test.mm
|
||||
$dirname/freemind.py -o $tmp/test.mm > $tmp/return.otl
|
||||
diff -Nur $fname $tmp/return.otl
|
329
pack/acp/start/vimoutliner/vimoutliner/scripts/vo2html.rb
Normal file
329
pack/acp/start/vimoutliner/vimoutliner/scripts/vo2html.rb
Normal file
|
@ -0,0 +1,329 @@
|
|||
#! /usr/bin/ruby
|
||||
|
||||
# = Synopsis
|
||||
#
|
||||
# vo2xo: Converts VIM Outliner files to HTML slides.
|
||||
#
|
||||
# = Usage
|
||||
#
|
||||
# vo2html [OPTION] input-file
|
||||
#
|
||||
# -?, --help: show help
|
||||
#
|
||||
# -h, --head file-name:
|
||||
# insert the contents of the named file within the HTML HEAD element.
|
||||
#
|
||||
# -b, --body file-name:
|
||||
# insert the contents of the named file just after the start of the HTML BODY element.
|
||||
#
|
||||
# -t, --tail file-name:
|
||||
# insert the contents of the named file just before the end the HTML BODY element.
|
||||
#
|
||||
# input-file: The VIM Outliner file to be converted.
|
||||
|
||||
# LICENSE
|
||||
# Copyright (C) 2006 Bruce Perens
|
||||
#
|
||||
# This license incorporates by reference the terms of GPL Version 3 or, at
|
||||
# your choice, any later version of the GPL published by the Free Software
|
||||
# Foundation, Inc. of Boston, MA, USA.
|
||||
#
|
||||
# You may not modify this license. You must preserve it and the accompanying
|
||||
# copyright declaration in any whole or fragmentary verisons of the software
|
||||
# to which they apply.
|
||||
#
|
||||
require 'getoptlong'
|
||||
require 'rdoc/usage'
|
||||
require 'rubygems'
|
||||
require 'builder'
|
||||
gem 'ruby-mp3info'
|
||||
require 'mp3info'
|
||||
|
||||
class OutlineParser
|
||||
private
|
||||
LeadingTabPattern = /^(\t*)(.*)$/.freeze
|
||||
ColonPattern = /^:[ \t]*(.*)$/.freeze
|
||||
|
||||
protected
|
||||
def initialize(file)
|
||||
@file = file
|
||||
@pushback = nil
|
||||
@nesting = 0
|
||||
end
|
||||
|
||||
# Get a line, with push-back.
|
||||
def get_line
|
||||
if (line = @pushback)
|
||||
@pushback = nil
|
||||
return line
|
||||
else
|
||||
return @file.gets
|
||||
end
|
||||
end
|
||||
|
||||
# Recursive parser for VIM Outliner.
|
||||
#
|
||||
# Meant to be called from itself when nesting increases - it calls its
|
||||
# callers "nest" method, which calls "parse". This fits well with nesting
|
||||
# output paradigms like that of Builder::XmlMarkup.
|
||||
#
|
||||
# Returns when nesting decreases, or if got_heading is set, just before the
|
||||
# next top-level heading in the input stream. You should iteratively call
|
||||
# parse() until more() returns false. This facilitates per-heading handling
|
||||
# such as in the Xoxo converter, which uses first-level heading to demarcate
|
||||
# the boundaries of slides.
|
||||
#
|
||||
# got_heading: If set, this will return just before the next top-level
|
||||
# heading, leaving it in the push-back.
|
||||
#
|
||||
def parse(got_heading = false)
|
||||
|
||||
while (line = get_line())
|
||||
m = line.match(LeadingTabPattern)
|
||||
n = m[1].length # This line's nesting level.
|
||||
after_tabs = m[2] # Content after zero or more leading tabs.
|
||||
|
||||
# Drop empty lines, and lines with only tabs.
|
||||
next if after_tabs == ''
|
||||
|
||||
if n != @nesting # The nesting level changes with this line.
|
||||
previous = @nesting
|
||||
@nesting = n
|
||||
@pushback = line
|
||||
|
||||
# If nesting increases, recursively parse it through nest().
|
||||
# If nesting decreases, return to nest(), which will in turn
|
||||
# return here. Both of these can be true in sequence! Nest()
|
||||
# detects when a nesting level is closed by looking ahead one
|
||||
# line and then pushing it back. That line can be one or MORE
|
||||
# levels lesser than the current nesting level.
|
||||
#
|
||||
nest(n) if n > previous
|
||||
return true if n < previous
|
||||
elsif
|
||||
if (p = after_tabs.match(ColonPattern)) and p[1].length > 0
|
||||
text(p[1], n)
|
||||
else
|
||||
if got_heading and n == 0
|
||||
@pushback = line
|
||||
return true # Return before the next top-level heading.
|
||||
end
|
||||
|
||||
got_heading = true
|
||||
heading(after_tabs, n)
|
||||
end
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
public
|
||||
# Simple parser that returns true if there is any remaining content
|
||||
# and leaves that content in the push-back.
|
||||
# The return value is the content minus any leading tabs.
|
||||
#
|
||||
# Usage
|
||||
# Return true if there is more content:
|
||||
# if more
|
||||
# Return the content of the next line to be read.
|
||||
# more
|
||||
#
|
||||
# The second form is used to get the document title from the first line
|
||||
# in the file.
|
||||
#
|
||||
def more
|
||||
while (line = get_line())
|
||||
if (m = line.match(LeadingTabPattern)) and m[2].length > 0
|
||||
@pushback = line
|
||||
return m[2]
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class OutlineToHTML < OutlineParser
|
||||
private
|
||||
Type = [ :DOCTYPE,
|
||||
:html,
|
||||
:PUBLIC,
|
||||
'-//W3C//DTD XHTML 1.0 Strict//EN',
|
||||
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
|
||||
].freeze
|
||||
|
||||
def wrap(nesting)
|
||||
if nesting > 1
|
||||
@x.li { yield }
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def heading(text, nesting)
|
||||
if nesting == 0
|
||||
@x.h1(text)
|
||||
else
|
||||
@x.li(text)
|
||||
end
|
||||
end
|
||||
|
||||
def nest(nesting)
|
||||
wrap(nesting) { @x.ul(:class => "list-#{nesting}") { parse(true) } }
|
||||
end
|
||||
|
||||
def text(t, nesting)
|
||||
@x.p(t)
|
||||
end
|
||||
|
||||
public
|
||||
def initialize(input_file, head_insert, body_insert, tail_insert)
|
||||
@head_insert = head_insert.read if head_insert
|
||||
@body_insert = body_insert.read if body_insert
|
||||
@tail_insert = tail_insert.read if tail_insert
|
||||
super(input_file)
|
||||
end
|
||||
|
||||
def convert
|
||||
n = 0
|
||||
presentation_title = more
|
||||
|
||||
while (title = more)
|
||||
audio_filename = "#{n + 1}.mp3"
|
||||
next_audio_filename = "#{n + 2}.mp3"
|
||||
|
||||
@x = ::Builder::XmlMarkup.new(:indent => 2)
|
||||
@x.declare!(*Type)
|
||||
@x.html {
|
||||
body_parameters = {}
|
||||
|
||||
@x.head {
|
||||
if title != presentation_title
|
||||
@x.title("#{presentation_title} - #{title}")
|
||||
else
|
||||
@x.title("#{presentation_title}")
|
||||
end
|
||||
|
||||
@x << eval('"' + @head_insert + '"') if @head_insert
|
||||
|
||||
if File.exists?(audio_filename)
|
||||
seconds = nil
|
||||
|
||||
Mp3Info.open(audio_filename) { |mp3|
|
||||
seconds = mp3.length.ceil + 1
|
||||
}
|
||||
|
||||
parameters = {
|
||||
:'http-equiv' => 'refresh',
|
||||
:content => "#{seconds};url=#{n + 2}.html"
|
||||
}
|
||||
@x.meta(parameters)
|
||||
if File.exists?(next_audio_filename)
|
||||
program = "function Preload() { a = new Image(); a.src = '#{next_audio_filename}'; p = new Image(); p.src = '#{n + 2}.html' }"
|
||||
@x.script(program, :language => 'JavaScript')
|
||||
body_parameters[:onload] = "Preload()"
|
||||
end
|
||||
end
|
||||
}
|
||||
@x.body(body_parameters) {
|
||||
@x << eval('"' + @body_insert + '"') if @body_insert
|
||||
attributes = { :class => 'content' }
|
||||
# Fix: I don't yet know if this is the last slide, so I can't
|
||||
# decide whether to do this onclick action or not.
|
||||
# Oops. We have to generate the body tag after its contents.
|
||||
# This might be awkward to do within Builder.
|
||||
attributes[:onclick] = "document.location='#{n + 2}.html'"
|
||||
@x.div(attributes) {
|
||||
parse(false)
|
||||
}
|
||||
@x.div(:class => 'bottom') {
|
||||
@x << eval('"' + @tail_insert + '"') if @tail_insert
|
||||
|
||||
@x.div(:class => 'navbar-wrapper') {
|
||||
@x.ul(:class => 'navbar') {
|
||||
@x.li(:class => 'previous') {
|
||||
if n > 0
|
||||
@x.a('Previous', :href => "#{n}.html")
|
||||
end
|
||||
}
|
||||
|
||||
@x.li(:class => 'top') {
|
||||
@x.a(presentation_title, :href => "1.html")
|
||||
}
|
||||
|
||||
@x.li(:class => 'next') {
|
||||
if more
|
||||
@x.a('Next', :href => "#{n + 2}.html")
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
if File.exists?(audio_filename)
|
||||
@x.object(:type => 'audio/mpeg', :data => audio_filename, :width => "95%", :height => 42) {
|
||||
message = "Your web browser isn't configured correctly to play the audio file #{audio_filename}, and thus you are missing the sound-track to this program."
|
||||
|
||||
@x.param(:name => 'autoplay', :value => true)
|
||||
@x.param(:name => 'playcount', :value => 1)
|
||||
@x.param(:name => 'showcontrols', :value => false)
|
||||
@x.param(:name => 'showdisplay', :value => false)
|
||||
@x.span(message, :class => 'error')
|
||||
}
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
File.open("#{n += 1}.html", "w") { |f|
|
||||
f.write(@x.target!)
|
||||
}
|
||||
@x = nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
opts = GetoptLong.new(
|
||||
[ '--help', '-?', GetoptLong::NO_ARGUMENT ],
|
||||
[ '--head', '-h', GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ '--body', '-b', GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ '--tail', '-t', GetoptLong::REQUIRED_ARGUMENT ]
|
||||
)
|
||||
|
||||
head_insert = nil
|
||||
body_insert = nil
|
||||
tail_insert = nil
|
||||
|
||||
begin
|
||||
opts.each do |opt, arg|
|
||||
case opt
|
||||
when '--help'
|
||||
RDoc::usage
|
||||
when '--head'
|
||||
head_insert = File.new(arg, 'r')
|
||||
when '--body'
|
||||
body_insert = File.new(arg, 'r')
|
||||
when '--tail'
|
||||
tail_insert = File.new(arg, 'r')
|
||||
end
|
||||
end
|
||||
|
||||
if ARGV.length != 1
|
||||
RDoc::usage
|
||||
exit 0
|
||||
end
|
||||
|
||||
input_file = File.new(ARGV[0], 'r')
|
||||
rescue Exception => error
|
||||
$stderr.print("Error: #{error}\n")
|
||||
exit(1)
|
||||
end
|
||||
|
||||
c = OutlineToHTML.new(input_file, head_insert, body_insert, tail_insert)
|
||||
if not c.more
|
||||
$stderr.write("Error: Input file contains no content.\n")
|
||||
exit(1)
|
||||
end
|
||||
|
||||
c.convert
|
||||
exit(0)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue