Add vim-orgmode 35e94218c12a0c063b4b3a9b48e7867578e1e13c and vim-speeddating v20151024
This commit is contained in:
parent
15df158a9c
commit
35456e0e6f
106 changed files with 24643 additions and 0 deletions
|
@ -11,5 +11,7 @@ Git submodules are slow, so handle this manually.
|
||||||
* [start/mom.vim](https://github.com/vim-scripts/mom.vim)
|
* [start/mom.vim](https://github.com/vim-scripts/mom.vim)
|
||||||
* [start/rust.vim](https://github.com/rust-lang/rust.vim)
|
* [start/rust.vim](https://github.com/rust-lang/rust.vim)
|
||||||
* [start/vim-go](https://github.com/fatih/vim-go)
|
* [start/vim-go](https://github.com/fatih/vim-go)
|
||||||
|
* [start/vim-orgmode](https://github.com/jceb/vim-orgmode)
|
||||||
* [start/vim-ps1](https://github.com/PProvost/vim-ps1)
|
* [start/vim-ps1](https://github.com/PProvost/vim-ps1)
|
||||||
|
* [start/vim-speeddating](https://github.com/tpope/vim-speeddating)
|
||||||
* [start/vim-surround](https://github.com/tpope/vim-surround)
|
* [start/vim-surround](https://github.com/tpope/vim-surround)
|
||||||
|
|
6
pack/acp/start/vim-orgmode/.gitignore
vendored
Normal file
6
pack/acp/start/vim-orgmode/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
tags
|
||||||
|
.ropeproject
|
||||||
|
.cover*
|
||||||
|
cover*
|
238
pack/acp/start/vim-orgmode/.pylintrc
Normal file
238
pack/acp/start/vim-orgmode/.pylintrc
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
[MASTER]
|
||||||
|
|
||||||
|
# Specify a configuration file.
|
||||||
|
#rcfile=
|
||||||
|
|
||||||
|
# Python code to execute, usually for sys.path manipulation such as
|
||||||
|
# pygtk.require().
|
||||||
|
init-hook=sys.path.append(os.path.abspath('ftplugin'))
|
||||||
|
|
||||||
|
# Profiled execution.
|
||||||
|
profile=no
|
||||||
|
|
||||||
|
# Add files or directories to the blacklist. They should be base names, not
|
||||||
|
# paths.
|
||||||
|
ignore=.git
|
||||||
|
|
||||||
|
# Pickle collected data for later comparisons.
|
||||||
|
persistent=yes
|
||||||
|
|
||||||
|
# List of plugins (as comma separated values of python modules names) to load,
|
||||||
|
# usually to register additional checkers.
|
||||||
|
load-plugins=
|
||||||
|
|
||||||
|
|
||||||
|
[MESSAGES CONTROL]
|
||||||
|
|
||||||
|
# Enable the message, report, category or checker with the given id(s). You can
|
||||||
|
# either give multiple identifier separated by comma (,) or put this option
|
||||||
|
# multiple time.
|
||||||
|
#enable=
|
||||||
|
|
||||||
|
# Disable the message, report, category or checker with the given id(s). You
|
||||||
|
# can either give multiple identifier separated by comma (,) or put this option
|
||||||
|
# multiple time (only on the command line, not in the configuration file where
|
||||||
|
# it should appear only once).
|
||||||
|
#disable=
|
||||||
|
|
||||||
|
[REPORTS]
|
||||||
|
|
||||||
|
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||||
|
# (visual studio) and html
|
||||||
|
output-format=parseable
|
||||||
|
|
||||||
|
# Include message's id in output
|
||||||
|
include-ids=no
|
||||||
|
|
||||||
|
# Put messages in a separate file for each module / package specified on the
|
||||||
|
# command line instead of printing them on stdout. Reports (if any) will be
|
||||||
|
# written in a file name "pylint_global.[txt|html]".
|
||||||
|
files-output=no
|
||||||
|
|
||||||
|
# Tells whether to display a full report or only the messages
|
||||||
|
reports=yes
|
||||||
|
|
||||||
|
# Python expression which should return a note less than 10 (10 is the highest
|
||||||
|
# note). You have access to the variables errors warning, statement which
|
||||||
|
# respectively contain the number of errors / warnings messages and the total
|
||||||
|
# number of statements analyzed. This is used by the global evaluation report
|
||||||
|
# (RP0004).
|
||||||
|
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||||
|
|
||||||
|
# Add a comment according to your evaluation note. This is used by the global
|
||||||
|
# evaluation report (RP0004).
|
||||||
|
comment=no
|
||||||
|
|
||||||
|
|
||||||
|
[TYPECHECK]
|
||||||
|
|
||||||
|
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||||
|
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||||
|
ignore-mixin-members=yes
|
||||||
|
|
||||||
|
# List of classes names for which member attributes should not be checked
|
||||||
|
# (useful for classes with attributes dynamically set).
|
||||||
|
ignored-classes=SQLObject
|
||||||
|
|
||||||
|
# When zope mode is activated, add a predefined set of Zope acquired attributes
|
||||||
|
# to generated-members.
|
||||||
|
zope=no
|
||||||
|
|
||||||
|
# List of members which are set dynamically and missed by pylint inference
|
||||||
|
# system, and so shouldn't trigger E0201 when accessed. Python regular
|
||||||
|
# expressions are accepted.
|
||||||
|
generated-members=REQUEST,acl_users,aq_parent
|
||||||
|
|
||||||
|
|
||||||
|
[BASIC]
|
||||||
|
|
||||||
|
# Required attributes for module, separated by a comma
|
||||||
|
required-attributes=
|
||||||
|
|
||||||
|
# List of builtins function names that should not be used, separated by a comma
|
||||||
|
bad-functions=map,filter,apply,input
|
||||||
|
|
||||||
|
# Regular expression which should only match correct module names
|
||||||
|
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct module level names
|
||||||
|
const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct class names
|
||||||
|
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct function names
|
||||||
|
function-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct method names
|
||||||
|
method-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct instance attribute names
|
||||||
|
attr-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct argument names
|
||||||
|
argument-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct variable names
|
||||||
|
variable-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||||
|
|
||||||
|
# Regular expression which should only match correct list comprehension /
|
||||||
|
# generator expression variable names
|
||||||
|
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||||
|
|
||||||
|
# Good variable names which should always be accepted, separated by a comma
|
||||||
|
good-names=i,j,k,ex,Run,_
|
||||||
|
|
||||||
|
# Bad variable names which should always be refused, separated by a comma
|
||||||
|
bad-names=foo,bar,baz,toto,tutu,tata
|
||||||
|
|
||||||
|
# Regular expression which should only match functions or classes name which do
|
||||||
|
# not require a docstring
|
||||||
|
no-docstring-rgx=__.*__
|
||||||
|
|
||||||
|
|
||||||
|
[MISCELLANEOUS]
|
||||||
|
|
||||||
|
# List of note tags to take in consideration, separated by a comma.
|
||||||
|
notes=FIXME,XXX,TODO
|
||||||
|
|
||||||
|
|
||||||
|
[VARIABLES]
|
||||||
|
|
||||||
|
# Tells whether we should check for unused import in __init__ files.
|
||||||
|
init-import=no
|
||||||
|
|
||||||
|
# A regular expression matching the beginning of the name of dummy variables
|
||||||
|
# (i.e. not used).
|
||||||
|
dummy-variables-rgx=_|dummy
|
||||||
|
|
||||||
|
# List of additional names supposed to be defined in builtins. Remember that
|
||||||
|
# you should avoid to define new builtins when possible.
|
||||||
|
additional-builtins=
|
||||||
|
|
||||||
|
|
||||||
|
[SIMILARITIES]
|
||||||
|
|
||||||
|
# Minimum lines number of a similarity.
|
||||||
|
min-similarity-lines=4
|
||||||
|
|
||||||
|
# Ignore comments when computing similarities.
|
||||||
|
ignore-comments=yes
|
||||||
|
|
||||||
|
# Ignore docstrings when computing similarities.
|
||||||
|
ignore-docstrings=yes
|
||||||
|
|
||||||
|
|
||||||
|
[FORMAT]
|
||||||
|
|
||||||
|
# Maximum number of characters on a single line.
|
||||||
|
max-line-length=800
|
||||||
|
|
||||||
|
# Maximum number of lines in a module
|
||||||
|
max-module-lines=1000
|
||||||
|
|
||||||
|
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||||
|
# tab).
|
||||||
|
indent-string=\t
|
||||||
|
|
||||||
|
|
||||||
|
[CLASSES]
|
||||||
|
|
||||||
|
# List of interface methods to ignore, separated by a comma. This is used for
|
||||||
|
# instance to not check methods defines in Zope's Interface base class.
|
||||||
|
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
|
||||||
|
|
||||||
|
# List of method names used to declare (i.e. assign) instance attributes.
|
||||||
|
defining-attr-methods=__init__,__new__,setUp
|
||||||
|
|
||||||
|
|
||||||
|
[IMPORTS]
|
||||||
|
|
||||||
|
# Deprecated modules which should not be used, separated by a comma
|
||||||
|
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
|
||||||
|
|
||||||
|
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||||
|
# given file (report RP0402 must not be disabled)
|
||||||
|
import-graph=
|
||||||
|
|
||||||
|
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||||
|
# not be disabled)
|
||||||
|
ext-import-graph=
|
||||||
|
|
||||||
|
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||||
|
# not be disabled)
|
||||||
|
int-import-graph=
|
||||||
|
|
||||||
|
|
||||||
|
[DESIGN]
|
||||||
|
|
||||||
|
# Maximum number of arguments for function / method
|
||||||
|
max-args=5
|
||||||
|
|
||||||
|
# Argument names that match this expression will be ignored. Default to name
|
||||||
|
# with leading underscore
|
||||||
|
ignored-argument-names=_.*
|
||||||
|
|
||||||
|
# Maximum number of locals for function / method body
|
||||||
|
max-locals=15
|
||||||
|
|
||||||
|
# Maximum number of return / yield for function / method body
|
||||||
|
max-returns=6
|
||||||
|
|
||||||
|
# Maximum number of branch for function / method body
|
||||||
|
max-branchs=12
|
||||||
|
|
||||||
|
# Maximum number of statements in function / method body
|
||||||
|
max-statements=50
|
||||||
|
|
||||||
|
# Maximum number of parents for a class (see R0901).
|
||||||
|
max-parents=7
|
||||||
|
|
||||||
|
# Maximum number of attributes for a class (see R0902).
|
||||||
|
max-attributes=7
|
||||||
|
|
||||||
|
# Minimum number of public methods for a class (see R0903).
|
||||||
|
min-public-methods=2
|
||||||
|
|
||||||
|
# Maximum number of public methods for a class (see R0904).
|
||||||
|
max-public-methods=20
|
21
pack/acp/start/vim-orgmode/.travis.yml
Normal file
21
pack/acp/start/vim-orgmode/.travis.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
language: python
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get update && sudo apt-get --reinstall install -qq language-pack-pt
|
||||||
|
|
||||||
|
python:
|
||||||
|
- "2.7"
|
||||||
|
- "3.4"
|
||||||
|
- "3.5"
|
||||||
|
- "3.6"
|
||||||
|
|
||||||
|
install:
|
||||||
|
- pip install coverage
|
||||||
|
- pip install codecov
|
||||||
|
|
||||||
|
script:
|
||||||
|
- cd tests
|
||||||
|
- nosetests --with-coverage .
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- codecov
|
214
pack/acp/start/vim-orgmode/CHANGELOG.org
Normal file
214
pack/acp/start/vim-orgmode/CHANGELOG.org
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
* Changelog
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
This log is kept according to the [[http://keepachangelog.com/][Keep a CHANGELOG]] manifesto
|
||||||
|
** 0.7.0 :unreleased:
|
||||||
|
*** Added
|
||||||
|
- Subtracting when entering dates (PR #276)
|
||||||
|
*** Fixed
|
||||||
|
- =ir= text object now works with most operations (PR #284, closes #273)
|
||||||
|
** 0.6.0 <2017-11-06 Mon> :released:
|
||||||
|
*** Added
|
||||||
|
- Introduced sphinx documentation to Python modules. (PR #237)
|
||||||
|
- Add =Python3= support. (PR #231, closes #226)
|
||||||
|
- Implementing agenda overview for current buffer. (PR #229)
|
||||||
|
- =g:org_aggressive_conceal=, if value =1=, will conceal all simple format
|
||||||
|
identifying characters, default =0=. (PR #188)
|
||||||
|
- (testing on `g:org_aggressive_conceal=1' mode) Add possibility to escape
|
||||||
|
format indicating characters from leading inline markup, by escaping with
|
||||||
|
"\".
|
||||||
|
- Add alternative behavior: refrain from entering insert mode after
|
||||||
|
heading/checkbox creation through keybindings. Activate by setting
|
||||||
|
=g:org_prefer_insert_mode= to 0. (closes #211)
|
||||||
|
- Add export as LaTeX beamer slides (PR #206)
|
||||||
|
- Keybinding to create plainlist item directly. (closes #190)
|
||||||
|
- Make % jump between < and >. (PR #251, closes #250)
|
||||||
|
*** Changed
|
||||||
|
- Changed default value for =g:org_indent= from =1= to =0=. (closes #243)
|
||||||
|
- Revamped TODO keyword cycling rules. (PR #237)
|
||||||
|
- In [[syntax/org.vim][syntax/org.vim]], changed `\@<=' with computational faster `\zs'
|
||||||
|
- Using =<localleader>c[n/N]= to create new plainlist item following
|
||||||
|
current plainlist item. Now these keybindings will unconditionally
|
||||||
|
create empty checkbox. (closes #190)
|
||||||
|
*** Deprecated
|
||||||
|
- Nothing
|
||||||
|
*** Removed
|
||||||
|
- Removed the requirement for TODO state keywords to be upper-case.
|
||||||
|
(PR #235)
|
||||||
|
*** Fixed
|
||||||
|
- Avoid duplicate =InsertLeave= handlers (PR #222, closes #223)
|
||||||
|
- Fix python3 compatibility issue with regexes
|
||||||
|
(PR #266, closes #263, #265)
|
||||||
|
- Fixed python3 compatible issue within =CalendarAction=.
|
||||||
|
(PR #242, closes #241)
|
||||||
|
- Tree promoting/demoting no longer destroy list and checkbox structure.
|
||||||
|
(closes #217)
|
||||||
|
- Fixed bug when promote/demote headings when it contain lists.
|
||||||
|
(PR #239, partly fixes #217)
|
||||||
|
- Silenced =W18= warning when non-ASCII coded TODO keywords are used.
|
||||||
|
(PR #236)
|
||||||
|
- Fix non-English locale support issue in OrgDate and Agenda. (PR #234,
|
||||||
|
closes #230)
|
||||||
|
- Fix =concealcursor= mis-setting. (from ="nc"= to =nc=)
|
||||||
|
- Fix duplicate =InsertLeave= autocmd for =tag_complete=. (closes #223)
|
||||||
|
- Fix utl error when =\= or white space is in the link by auto-escaping.
|
||||||
|
(closes #220)
|
||||||
|
- Fix typo vbm -> vmb (PR #219)
|
||||||
|
- Fix toggling checkboxes with plain embedded lists (PR #212, closes #209)
|
||||||
|
- Return to right window before setting todo (closes #202)
|
||||||
|
- Fix link to calendar-vim (closes #197)
|
||||||
|
- Fix =out of bound= issue when creating heading/checkbox after last
|
||||||
|
instance in document on NeoVim. (closes #213)
|
||||||
|
** 0.5.0 <2015-10-10 Sat> :released:
|
||||||
|
*** Added
|
||||||
|
- show link description in headings when folded, instead of the whole
|
||||||
|
link
|
||||||
|
- add simplified mappings to create new headings with
|
||||||
|
[<localleader>|<leader>]<CR>
|
||||||
|
- improve incrementing and decrementing of list items
|
||||||
|
- moved changelog information to its own file
|
||||||
|
- add tests for the tags plugin
|
||||||
|
- copy type and indentation when creating new list items
|
||||||
|
- increase/decrease ordered list when adding new items
|
||||||
|
- add support for alphanumeric ordered lists
|
||||||
|
- add test cases for overlapping mappings
|
||||||
|
- add three dots after folded text, like in orgmode
|
||||||
|
- improve highlighting of org-mode properties (closes issue #130)
|
||||||
|
- implement global visibility as it works in Emacs org-mode (closes issue
|
||||||
|
#119)
|
||||||
|
- improve detection of speeddating plugin (closes issue #121)
|
||||||
|
- add support for high speed searching of headings that use certain tags
|
||||||
|
(closes issue #58)
|
||||||
|
- make echo, echom and echoe split messages a line ends and execute a
|
||||||
|
single vim command for each line
|
||||||
|
- add export commands OrgExportToPDF and OrgExportToHTML (closes issue
|
||||||
|
#107)
|
||||||
|
- add variables for customizing the export via Emacs: g:org_export_emacs,
|
||||||
|
g:org_export_verbose, g:org_export_init_script (closes issue #107)
|
||||||
|
- switch to subprocess.Popen for Emcas export (closes issue #107)
|
||||||
|
- add defaults and examples for all variables
|
||||||
|
- add support for inserting new checkboxes with the same keybinging as
|
||||||
|
inserting new headings (thanks to Powen Tan)
|
||||||
|
- implemented support for markdown export (issue #185)
|
||||||
|
*** Deprecated
|
||||||
|
- Nothing
|
||||||
|
*** Removed
|
||||||
|
- Nothing
|
||||||
|
*** Fixed
|
||||||
|
- allow checkbox status to be toggled when there is no indicator present
|
||||||
|
([])
|
||||||
|
- improve installation instructions (related to issues #111 and #176)
|
||||||
|
- optimize checkbox regex to match also just the type without status and
|
||||||
|
title
|
||||||
|
- fix broken unordered lists
|
||||||
|
- set org_tag_column to textwidth
|
||||||
|
- change commentstring to "# %s"
|
||||||
|
- fix syntax highlighting of list items
|
||||||
|
- fix indentation of first checkbox of a heading
|
||||||
|
- fix indentation of first checkbox of a heading
|
||||||
|
- disable highlighting of non-printable characters in todo state
|
||||||
|
selection window
|
||||||
|
- fix highlighting of todo keywords that are followed by additional
|
||||||
|
characters, i.e. TODOs
|
||||||
|
- omit status when entering new checkbox item if current checkbox doesn't
|
||||||
|
have one
|
||||||
|
- fix broken indentation of checkboxes (closes issue #146)
|
||||||
|
- fix CalendarAction is undefined (closes issue #142)
|
||||||
|
- correct overlapping mappings in PluginDate
|
||||||
|
- fix cache problems when inserting a new heading, together with multi
|
||||||
|
line text (closes issue #116)
|
||||||
|
- rename plug to OrgTodoToggleNonInteractive (closes issue #114)
|
||||||
|
- fix jumping to the first character within the body of a heading
|
||||||
|
- use Ignore highlighting instead of NonText for shaded stars (closes
|
||||||
|
issues #173)
|
||||||
|
- fix broken buffer number (closes issue #177)
|
||||||
|
- make exports work with emacs 24.4 (closes issue #178)
|
||||||
|
- improve comments
|
||||||
|
- fix syntax for #+BEGIN_* blocks (issue #186)
|
||||||
|
** 0.4.0-0 <2011-10-16 Sun> :released:
|
||||||
|
- fix broken repeat settings for moving a heading
|
||||||
|
- improve performance when moving a heading upward or downward (closes
|
||||||
|
issue #108)
|
||||||
|
- improve performance when changing the level of a heading (related to
|
||||||
|
issue #108)
|
||||||
|
- extend liborgmode.headings.HeadingList to allow headings to not be
|
||||||
|
tainted when moving them around
|
||||||
|
- change heading tree text object to ir/ar... because of vim's it/at text
|
||||||
|
object (closes issue #106)
|
||||||
|
- improve performance when inserting a new heading below (closes issue
|
||||||
|
#105)
|
||||||
|
- remove duplicate tags (closes issue #104)
|
||||||
|
- improve performance in insert mode (closes issue #103)
|
||||||
|
- improve performance when opening larger org files (closes issue #103)
|
||||||
|
- replace org.txt by orgguide.txt (closes issue #77)
|
||||||
|
- replace g:org_leader by <LocalLeader> (closes issue #101)
|
||||||
|
To restore the previous behavior add the following line to your vimrc:
|
||||||
|
>
|
||||||
|
let maplocalleader = ','
|
||||||
|
<
|
||||||
|
- change normal command execution to not remap any key (related to issue
|
||||||
|
#85)
|
||||||
|
- fix regression timeout when opening folds (closes issue #100)
|
||||||
|
- vim-orgmode multistate documentation (closes issue #77)
|
||||||
|
- add support for @-signs in tags (closes issue #98)
|
||||||
|
- enable file completion for hyperlinks by default (closes issue #97)
|
||||||
|
- fix traceback when pressing <Esc> while editing a link (closes issue
|
||||||
|
#96)
|
||||||
|
- implement reverse visibility cycling using <S-Tab> (closes issue #95)
|
||||||
|
- change ,, and ,. to remap zr and zm. (closes issue #73)
|
||||||
|
- add .cnf files to the vimball archive (closes #93)
|
||||||
|
- integrate pylint code checker (closes issue #87)
|
||||||
|
- solve encoding issues in the agenda plugin (closes issue #86)
|
||||||
|
- add description for writing test cases
|
||||||
|
- add coverage report target (closes issue #74)
|
||||||
|
- add support for plain lists, thanks to Aleksandar Dimitrov (closes issue
|
||||||
|
#81)
|
||||||
|
- add agenda view, many thanks to Stefan Otte (closes issue #34)
|
||||||
|
- move cursor to the current todo state when selecting the todo state
|
||||||
|
interactively (closes issue #61)
|
||||||
|
- add parameter scope to method settings.get
|
||||||
|
- add method settings.unset
|
||||||
|
- fix cursor positioning when selecting todo states
|
||||||
|
- improve date plugin
|
||||||
|
- update vba targets to its new name vmb
|
||||||
|
- demoting a newly created second level heading doesn't cause all children
|
||||||
|
to
|
||||||
|
be deleted anymore (closes issue #65)
|
||||||
|
- add error message for missing dependencies (closes issue #59)
|
||||||
|
- rename tests directory
|
||||||
|
- change licensing of the documentation to GNU Free Documentation License
|
||||||
|
- integrate orgguide (closes issue #57)
|
||||||
|
- replace DIRECTION_* with an enum (closes issue #56 and issue #49)
|
||||||
|
** 0.3.1-0 <2011-08-14 Sun> :released:
|
||||||
|
- demoting a newly created second level heading doesn't cause all children
|
||||||
|
to be deleted anymore (closes issue #65)
|
||||||
|
- add error message for missing dependencies (closes issue #59)
|
||||||
|
** 0.3.0-0 <2011-08-09 Tue> :released:
|
||||||
|
- fix completion menu popup that disappeared because of the usage of
|
||||||
|
vim.command (closes issue #48)
|
||||||
|
- implement interactive todo state selection (closes issue #5)
|
||||||
|
- add orgmode group to au commands in TagProperties plugin (closes issue
|
||||||
|
#53)
|
||||||
|
- allow demotion of first level headings (closes issue #27)
|
||||||
|
- fix encoding issues in Date plugin
|
||||||
|
- add general support for multiple todo sequences (closes Issue #46)
|
||||||
|
- fix folded text for headings containing backslashes or double quotes
|
||||||
|
(closes issue #26)
|
||||||
|
- add Document.get_todo_states() and Document.get_all_todo_states()
|
||||||
|
- don't confuse upper case words at the beginning of a heading with a todo
|
||||||
|
state (closes issue #28)
|
||||||
|
- fix error in setting tags (issue #25)
|
||||||
|
- improve split of heading (issue #24)
|
||||||
|
- add variable g:org_improve_split_heading to enable/disable improve the
|
||||||
|
split of headings (issue #24)
|
||||||
|
- implement shortcut for moving to the partent's next sibling (g}) (issue
|
||||||
|
#22)
|
||||||
|
- fix duplication of children when inserting a new heading (issue #20)
|
||||||
|
- always start insert mode when adding a new heading (issue #21)
|
||||||
|
** 0.2.1-0 <2011-06-26 Sun> :released:
|
||||||
|
- fix encoding of todo states set by the Todo plugin (thanks to Daniel
|
||||||
|
Carl and kien for pointing out the issue)
|
||||||
|
- add documentation for remapping shortcuts
|
||||||
|
- add documentation for customizing syntax highlighting
|
||||||
|
** 0.2.0-0 <2011-06-25 Sat> :released:
|
||||||
|
- initial release
|
60
pack/acp/start/vim-orgmode/LICENSE
Normal file
60
pack/acp/start/vim-orgmode/LICENSE
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
All source code is licensed under the terms of the following license:
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (C) 2010,2011 Jan Christoph Ebersbach
|
||||||
|
|
||||||
|
http://www.e-jc.de/
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
The source code of this program is made available under the terms of the
|
||||||
|
GNU Affero General Public License version 3 (GNU AGPL V3) as published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
Binary versions of this program provided by Univention to you as well as
|
||||||
|
other copyrighted, protected or trademarked materials like Logos,
|
||||||
|
graphics, fonts, specific documentations and configurations,
|
||||||
|
cryptographic keys etc. are subject to a license agreement between you
|
||||||
|
and Univention and not subject to the GNU AGPL V3.
|
||||||
|
|
||||||
|
In the case you use this program under the terms of the GNU AGPL V3, the
|
||||||
|
program is provided 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 Affero General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
with the Debian GNU/Linux or Univention distribution in file
|
||||||
|
/usr/share/common-licenses/AGPL-3; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
All documentation found in the directories doc and documentation are
|
||||||
|
licensed under the terms of the following license:
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
doc/org.txt
|
||||||
|
Copyright (C) 2010,2011 Jan Christoph Ebersbach
|
||||||
|
|
||||||
|
doc/orgguide.txt
|
||||||
|
documentation/emacs_orgguide.org
|
||||||
|
documentation/emacs_orgguide.texi
|
||||||
|
Copyright (C) 2010 Free Software Foundation
|
||||||
|
|
||||||
|
Permission is granted to copy, distribute and/or modify this document
|
||||||
|
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||||||
|
any later version published by the Free Software Foundation; with no
|
||||||
|
Invariant Sections, with the Front-Cover texts being “A GNU Manual,” and
|
||||||
|
with the Back-Cover Texts as in (a) below. A copy of the license is
|
||||||
|
included in the section entitled “GNU Free Documentation License.”
|
||||||
|
|
||||||
|
(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
|
||||||
|
modify this GNU manual. Buying copies from the FSF supports it in
|
||||||
|
developing GNU and promoting software freedom.”
|
||||||
|
|
||||||
|
This document is part of a collection distributed under the GNU Free
|
||||||
|
Documentation License. If you want to distribute this document
|
||||||
|
separately from the collection, you can do so by adding a copy of the
|
||||||
|
license to the document, as described in section 6 of the license.
|
91
pack/acp/start/vim-orgmode/Makefile
Normal file
91
pack/acp/start/vim-orgmode/Makefile
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
PLUGIN = orgmode
|
||||||
|
PREFIX = /usr/local
|
||||||
|
VIMDIR = $(PREFIX)/share/vim
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build:
|
||||||
|
|
||||||
|
# install plugin at destination
|
||||||
|
install: doc indent ftdetect ftplugin syntax
|
||||||
|
for i in doc indent ftdetect ftplugin syntax; do \
|
||||||
|
find $$i -type f -name \*.txt -o -type f -name \*.cnf -o -type f -name \*.py -o -type f -name \*.vim | while read f; do \
|
||||||
|
install -m 0755 -d $(DESTDIR)$(VIMDIR)/$$(dirname "$$f"); \
|
||||||
|
install -m 0644 $$f $(DESTDIR)$(VIMDIR)/$$f; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
clean: documentation
|
||||||
|
@find . -name \*.pyc -o -name \*.py,cover -exec rm {} \;
|
||||||
|
@rm -rf ${PLUGIN}.vmb ${PLUGIN}.vmb.gz tmp files
|
||||||
|
cd $< && $(MAKE) $@
|
||||||
|
|
||||||
|
# generate the vim ball package
|
||||||
|
${PLUGIN}.vmb: check build_vmb.vim clean
|
||||||
|
$(MAKE) DESTDIR=$(PWD)/tmp VIMDIR= install
|
||||||
|
find tmp -type f | sed -e 's/^tmp\///' > files
|
||||||
|
cp build_vmb.vim tmp
|
||||||
|
cd tmp && vim --cmd 'let g:plugin_name="${PLUGIN}"' -s build_vmb.vim
|
||||||
|
[ -e tmp/${PLUGIN}.vba ] && mv tmp/${PLUGIN}.vba tmp/$@ || true
|
||||||
|
mv tmp/$@ .
|
||||||
|
|
||||||
|
${PLUGIN}.vmb.gz: ${PLUGIN}.vmb
|
||||||
|
@rm -f ${PLUGIN}.vmb.gz
|
||||||
|
gzip $<
|
||||||
|
|
||||||
|
vmb: ${PLUGIN}.vmb
|
||||||
|
|
||||||
|
vmb.gz: ${PLUGIN}.vmb.gz
|
||||||
|
|
||||||
|
${PLUGIN}.vba: ${PLUGIN}.vmb
|
||||||
|
mv $< $@
|
||||||
|
|
||||||
|
${PLUGIN}.vba.gz: ${PLUGIN}.vba
|
||||||
|
@rm -f ${PLUGIN}.vba.gz
|
||||||
|
gzip $<
|
||||||
|
|
||||||
|
vba: ${PLUGIN}.vba
|
||||||
|
|
||||||
|
vba.gz: ${PLUGIN}.vba.gz
|
||||||
|
|
||||||
|
# run unit tests
|
||||||
|
test: check
|
||||||
|
|
||||||
|
check: tests/run_tests.py
|
||||||
|
cd tests && python2 run_tests.py
|
||||||
|
|
||||||
|
# generate documentation
|
||||||
|
docs: documentation
|
||||||
|
cd $< && $(MAKE)
|
||||||
|
|
||||||
|
# generate a test coverage report for all python files
|
||||||
|
coverage:
|
||||||
|
@echo ">>> Coverage depends on the package python-nose and python-coverage, make sure they are installed!"
|
||||||
|
cd tests && nosetests2 --with-coverage --cover-html .
|
||||||
|
|
||||||
|
# run a static code checker
|
||||||
|
lint:
|
||||||
|
@echo ">>> Lint depends on the package pylint make sure it's installed!"
|
||||||
|
pylint --rcfile .pylintrc --disable=C0301,C0103,C0111,C0322,C0323,C0324,W0703,W0612,W0603 orgmode
|
||||||
|
|
||||||
|
lintall:
|
||||||
|
@echo ">>> Lint depends on the package pylint make sure it's installed!"
|
||||||
|
pylint --rcfile .pylintrc orgmode
|
||||||
|
|
||||||
|
# install vim-orgmode in the .vim/bundle directory for test purposes
|
||||||
|
VIMPLUGINDIR = $(HOME)/.vim/bundle/orgmode
|
||||||
|
|
||||||
|
installvmb: ${PLUGIN}.vmb install_vmb.vim
|
||||||
|
rm -rvf ${VIMPLUGINDIR}
|
||||||
|
mkdir -p "${VIMPLUGINDIR}"
|
||||||
|
vim --cmd "let g:installdir='${VIMPLUGINDIR}'" -s install_vmb.vim $<
|
||||||
|
@echo "Plugin was installed in ${VIMPLUGINDIR}. Make sure you are using a plugin loader like pathegon, otherwise the ${PLUGIN} might not work properly."
|
||||||
|
|
||||||
|
installvba: ${PLUGIN}.vba install_vba.vim
|
||||||
|
rm -rvf ${VIMPLUGINDIR}
|
||||||
|
mkdir -p "${VIMPLUGINDIR}"
|
||||||
|
vim --cmd "let g:installdir='${VIMPLUGINDIR}'" -s install_vba.vim $<
|
||||||
|
@echo "Plugin was installed in ${VIMPLUGINDIR}. Make sure you are using a plugin loader like pathegon, otherwise the ${PLUGIN} might not work properly."
|
||||||
|
|
||||||
|
.PHONY: all build test check install clean vmb vmb.gz docs installvmb
|
43
pack/acp/start/vim-orgmode/README.org
Normal file
43
pack/acp/start/vim-orgmode/README.org
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
* Vim-OrgMode
|
||||||
|
|
||||||
|
#+ATTR_HTML: title="Join the chat at https://gitter.im/jceb/vim-orgmode"
|
||||||
|
[[https://gitter.im/jceb/vim-orgmode?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge][file:https://badges.gitter.im/jceb/vim-orgmode.svg]]
|
||||||
|
[[https://travis-ci.org/jceb/vim-orgmode][file:https://travis-ci.org/jceb/vim-orgmode.svg]]
|
||||||
|
[[https://codecov.io/gh/jceb/vim-orgmode][file:https://codecov.io/gh/jceb/vim-orgmode/branch/master/graph/badge.svg]]
|
||||||
|
|
||||||
|
Text outlining and task management for Vim based on [[http://orgmode.org/][Emacs' Org-Mode]].
|
||||||
|
|
||||||
|
The idea for this plugin was born by listening to the
|
||||||
|
[[http://twit.tv/floss136][Floss Weekly podcast]] introducing Emacs Org-Mode.
|
||||||
|
Org-Mode has a lot of strong features like folding, views (sparse tree) and
|
||||||
|
scheduling of tasks. These are completed by hyperlinks, tags, todo states,
|
||||||
|
priorities aso.
|
||||||
|
|
||||||
|
vim-orgmode aims at providing the same functionality for Vim.
|
||||||
|
|
||||||
|
[[https://github.com/jceb/vim-orgmode/blob/master/examples/mylife.org][file:examples/mylife.gif]]
|
||||||
|
|
||||||
|
** Features
|
||||||
|
Currently vim-orgmode does not support all orgmode features but is quite
|
||||||
|
usable. Short list of the already supported features:
|
||||||
|
|
||||||
|
- Syntax highlighting
|
||||||
|
- Cycle visibility of headings (folding)
|
||||||
|
- Navigate between headings
|
||||||
|
- Edit the structure of the document: add, move, promote, denote headings
|
||||||
|
and more
|
||||||
|
- Hyperlinks within vim-orgmode and outside (files, webpages, etc.)
|
||||||
|
- TODO list management
|
||||||
|
- Tags for headings
|
||||||
|
- Lists in alphanumeric and bullet item notation and checkbox support
|
||||||
|
- Basic date handling
|
||||||
|
- Export to other formats (via Emacs' Org-Mode)
|
||||||
|
|
||||||
|
* Installation and Usage
|
||||||
|
Installation and usage instructions are found in the file [[doc/orgguide.txt][doc/orgguide.txt]].
|
||||||
|
|
||||||
|
* License
|
||||||
|
Information about the license is found in file [[LICENSE]].
|
||||||
|
|
||||||
|
* Changelog
|
||||||
|
All changes are found in file [[https://github.com/jceb/vim-orgmode/blob/master/CHANGELOG.org][CHANGELOG.org]]
|
4
pack/acp/start/vim-orgmode/build_vmb.vim
Normal file
4
pack/acp/start/vim-orgmode/build_vmb.vim
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
:let g:vimball_home = "."
|
||||||
|
:e ../files
|
||||||
|
:execute '%MkVimball!' . g:plugin_name
|
||||||
|
:q!
|
869
pack/acp/start/vim-orgmode/debian/changelog
Normal file
869
pack/acp/start/vim-orgmode/debian/changelog
Normal file
|
@ -0,0 +1,869 @@
|
||||||
|
vim-orgmode (0.3.0-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* update documentation
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 09 Aug 2011 21:13:40 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.3.0-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* update documentation
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 09 Aug 2011 08:37:25 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.3.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix completion menu popup that disappeared because of the usage of
|
||||||
|
vim.command
|
||||||
|
* closes issue #48
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 09 Aug 2011 08:25:03 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-25) unstable; urgency=low
|
||||||
|
|
||||||
|
* playing around with ftdetect vs. setfiletype
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 08 Aug 2011 08:11:23 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-24) unstable; urgency=low
|
||||||
|
|
||||||
|
* improve implementation of todo state selection (issue #5)
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 07 Aug 2011 19:55:06 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-23) unstable; urgency=low
|
||||||
|
|
||||||
|
* more precise regex for dates - pull request by sotte
|
||||||
|
* closes issue #52
|
||||||
|
|
||||||
|
-- Roman Asendorf <roman.asendorf@gmail.com> Wed, 03 Aug 2011 22:40:48 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-22) unstable; urgency=low
|
||||||
|
|
||||||
|
* implement interactive todo state selection
|
||||||
|
* closes issue #5
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Wed, 03 Aug 2011 22:23:14 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-21) unstable; urgency=low
|
||||||
|
|
||||||
|
* added emacs as suggested package - pull request by sotte
|
||||||
|
* closes issue #54
|
||||||
|
|
||||||
|
-- Roman Asendorf <roman.asendorf@gmail.com> Wed, 03 Aug 2011 21:52:15 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-20) unstable; urgency=low
|
||||||
|
|
||||||
|
* simple export via emacs for pdf and html - pull request by sotte
|
||||||
|
* closes issue #54
|
||||||
|
|
||||||
|
-- Roman Asendorf <roman.asendorf@gmail.com> Wed, 03 Aug 2011 21:43:15 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-19) unstable; urgency=low
|
||||||
|
|
||||||
|
* add orgmode group to au commands in TagProperties plugin
|
||||||
|
* closes issue #53
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Wed, 03 Aug 2011 20:02:08 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-18) unstable; urgency=low
|
||||||
|
|
||||||
|
* allow demotion of first level headings
|
||||||
|
* closes issue #27
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 01 Aug 2011 21:59:32 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-17) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix encoding issues in Date plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Tue, 12 Jul 2011 17:59:41 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-16) unstable; urgency=low
|
||||||
|
|
||||||
|
* update installvba target to also work with older vim version
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Mon, 11 Jul 2011 08:23:18 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-15) unstable; urgency=low
|
||||||
|
|
||||||
|
* make switching to the next todo sequence more convenient
|
||||||
|
* fix issue in offset calculation when old and new state are None
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 09 Jul 2011 17:54:46 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-14) unstable; urgency=low
|
||||||
|
|
||||||
|
* make switching to the next todo sequence more consistent
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 09 Jul 2011 17:38:18 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-13) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix minor issues related to switching to the next todo sequence
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 09 Jul 2011 17:33:56 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-12) unstable; urgency=low
|
||||||
|
|
||||||
|
* add general support for multiple todo sequences
|
||||||
|
* closes issue #46
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 09 Jul 2011 16:39:49 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-11) unstable; urgency=low
|
||||||
|
|
||||||
|
* update documentation
|
||||||
|
* update clean target
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 09 Jul 2011 11:29:57 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-10) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix todo tests broken by version 0.2.1-8
|
||||||
|
* fix DONE result of VimBuffer.get_todo_states.parse_states
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 09 Jul 2011 09:49:07 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-9) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix folded text for headings containing backslashes or double quotes
|
||||||
|
* closes issue #26
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 08 Jul 2011 23:21:07 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-8) unstable; urgency=low
|
||||||
|
|
||||||
|
* add Document.get_todo_states() and Document.get_all_todo_states()
|
||||||
|
* don't confuse upper case words at the beginning of a heading with a todo
|
||||||
|
state
|
||||||
|
* closes issue #28
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 08 Jul 2011 22:30:29 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-7) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix error in setting tags
|
||||||
|
* closes issue #25
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Mon, 04 Jul 2011 12:56:27 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-6) unstable; urgency=low
|
||||||
|
|
||||||
|
* improve split of heading
|
||||||
|
* add variable g:org_improve_split_heading to enable/disable improve
|
||||||
|
the split of headings
|
||||||
|
* closes issue #24
|
||||||
|
* change Makefile to be more generic
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 04 Jul 2011 07:54:17 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-5) unstable; urgency=low
|
||||||
|
|
||||||
|
* implement shortcut for moving to the partent's next sibling
|
||||||
|
* closes issue #22
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 03 Jul 2011 13:21:04 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-4) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix duplication of children when inserting a new heading
|
||||||
|
* closes issue #20
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 03 Jul 2011 12:43:32 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-3) unstable; urgency=low
|
||||||
|
|
||||||
|
* add support for new vimball file extension .vmb
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 03 Jul 2011 12:27:07 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* always start insert mode when adding a new heading
|
||||||
|
* closes issue #21
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 03 Jul 2011 12:25:20 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* make target installvba create the VIMPLUGINDIR before attempting the
|
||||||
|
installation
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 26 Jun 2011 21:07:54 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.1-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* add documentation for customizing syntax highlighting
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 26 Jun 2011 19:08:59 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.0-6) unstable; urgency=low
|
||||||
|
|
||||||
|
* add dependency to clean target to orgmode.vba
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 26 Jun 2011 14:03:18 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.0-5) unstable; urgency=low
|
||||||
|
|
||||||
|
* add documentation for remapping shortcuts
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 26 Jun 2011 13:47:30 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.0-4) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix <Plug> names for Todo plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 26 Jun 2011 13:24:07 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.0-3) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix encoding of todo states set by the Todo plugin (thanks to Daniel Carl
|
||||||
|
for pointing out the issue)
|
||||||
|
* add target installvba to locally install orgmode.vba
|
||||||
|
* cleanup Makefile
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 26 Jun 2011 13:15:34 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.0-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* add hint for updateing vim-orgmode from a previous version
|
||||||
|
* move all documentation related to installation and usage to doc/org.txt
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 26 Jun 2011 12:46:55 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.0-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* minor changes to the build files
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 17:43:48 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.2.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* remove unused echo command in Makefile
|
||||||
|
* add vim help file doc/org.txt
|
||||||
|
* first release
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 17:35:31 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-89) unstable; urgency=low
|
||||||
|
|
||||||
|
* add separate target to generate the vba.gz archive
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 16:47:23 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-88) unstable; urgency=low
|
||||||
|
|
||||||
|
* improve error message in case ditaa is not available
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 16:42:36 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-87) unstable; urgency=low
|
||||||
|
|
||||||
|
* update README and diagram
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 16:38:31 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-86) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix issue in EditStructure._move_heading that caused the current heading
|
||||||
|
not to be removed from the list of heading
|
||||||
|
* improve error messages for non-allowed characters in tags or todo states
|
||||||
|
* allow \t and space in tags because of an automatic replacement by _ later
|
||||||
|
on
|
||||||
|
* fix issue when creating the debian package an not all path components
|
||||||
|
exist
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 16:36:39 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-85) unstable; urgency=low
|
||||||
|
|
||||||
|
* add support and tests for splitting a headings title in insert mode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 15:55:16 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-84) unstable; urgency=low
|
||||||
|
|
||||||
|
* correct test cases for Navigator plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 14:05:17 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-83) unstable; urgency=low
|
||||||
|
|
||||||
|
* remove LoggingWork from loaded plugins
|
||||||
|
* fix a problem when positioning the cursor on a newly created heading
|
||||||
|
* fix a problem when positioning the cursor on the first character of a
|
||||||
|
non-heading line
|
||||||
|
* fix a problem when indenting non-heading lines in insert mode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 13:13:41 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-82) unstable; urgency=low
|
||||||
|
|
||||||
|
* change global function insert_at_cursor to append text after cursor
|
||||||
|
* add support for insert mode to insert_at_cursor
|
||||||
|
* fix traceback in Date plugin caused by conversion to unicode
|
||||||
|
* change insert date mappings to ,si and ,sa
|
||||||
|
* add submenu Change Date to Date plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 25 Jun 2011 13:00:54 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-81) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix error in TagsProperties.set_tags when None type object is returned
|
||||||
|
* change TagsProperties.realign_tags to use VimBuffer.write_heading instead
|
||||||
|
of VimBuffer.write method
|
||||||
|
* add convenience function VimBuffer.find_current_heading
|
||||||
|
* remove trailing spaces when a heading contains a single uppercase word
|
||||||
|
(pseudo TODO state)
|
||||||
|
* change Heading.copy to create a completely detached heading even without a
|
||||||
|
connection to a document
|
||||||
|
* change Heading.start to reture Heading._orig_start when the heading has no
|
||||||
|
connection to a document
|
||||||
|
* add parameter connect_with_document to Document.find_heading
|
||||||
|
* convert plugins and global functions to use VimBuffer.find_current_heading
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 21 Jun 2011 23:26:25 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-80) unstable; urgency=low
|
||||||
|
|
||||||
|
* update README
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 21 Jun 2011 07:46:04 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-79) unstable; urgency=low
|
||||||
|
|
||||||
|
* implement VimBuffer.write_heading to just update a single heading
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 22:19:00 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-78) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix assignment to vim.current.buffer in test cases
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 15:21:39 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-77) unstable; urgency=low
|
||||||
|
|
||||||
|
* improve memory usage by removing unused document objects
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 14:33:10 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-76) unstable; urgency=low
|
||||||
|
|
||||||
|
* improve speed by implementing a better reuse of document objects
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 14:18:26 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-75) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix issue with tag recognition in headings that contain zero or just one
|
||||||
|
word
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 14:07:29 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-74) unstable; urgency=low
|
||||||
|
|
||||||
|
* change EditStructure mappings back to using the shift key
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 13:29:50 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-73) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix regression introduced in version 0.1.0-71
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 13:28:43 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-72) unstable; urgency=low
|
||||||
|
|
||||||
|
* change default value of g:org_tag_completion_ignorecase to &ignorecase
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 13:20:55 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-71) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert vim.eval return values to unicode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 19 Jun 2011 13:15:51 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-70) unstable; urgency=low
|
||||||
|
|
||||||
|
* update README
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 18 Jun 2011 19:21:04 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-69) unstable; urgency=low
|
||||||
|
|
||||||
|
* add support for tagbar plugin
|
||||||
|
* move ctags support to file ftplugin/org.cnf
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 18 Jun 2011 19:15:13 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-68) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix encoding error for plugins that directly access vim.current.buffer
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Thu, 16 Jun 2011 12:44:06 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-67) unstable; urgency=low
|
||||||
|
|
||||||
|
* change regex strings to raw strings
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 17 Jun 2011 08:09:23 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-66) unstable; urgency=low
|
||||||
|
|
||||||
|
* remove highlighting group Question from title colors
|
||||||
|
* fix utf-8 encoding for vim.command calls
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Thu, 16 Jun 2011 12:39:46 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-65) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix error when aktivating lazyredraw and hidden for the current buffer
|
||||||
|
* set commentstring to "# %s"
|
||||||
|
* fix error when switching buffers to get current changetick
|
||||||
|
* fix error when running get_document with bufnr 0 that opened to the first
|
||||||
|
document that was queried instead of return the current document
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Wed, 15 Jun 2011 12:42:03 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-64) unstable; urgency=low
|
||||||
|
|
||||||
|
* remove parameter mode from function change_visual_selection
|
||||||
|
* add more test cases for Navigator plugin, current this plugin is somehow
|
||||||
|
broken
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 14 Jun 2011 20:30:45 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-63) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert LoggingWork plugin to unicode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 14 Jun 2011 18:47:52 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-62) unstable; urgency=low
|
||||||
|
|
||||||
|
* move initialization of speeddating commands to __init__ method
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 14 Jun 2011 18:45:16 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-61) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert Date plugin to unicode
|
||||||
|
* correct a typo in mapping for May
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 14 Jun 2011 18:36:18 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-60) unstable; urgency=low
|
||||||
|
|
||||||
|
* add missing counter to test_edit_structure.py
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 14 Jun 2011 18:34:51 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-59) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert Todo plugin to unicode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 14 Jun 2011 18:32:01 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-58) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix indentation of docstring in VimBuffer
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 13 Jun 2011 21:51:16 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-57) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert TagsProperties to liborgmode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 13 Jun 2011 21:48:07 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-56) unstable; urgency=low
|
||||||
|
|
||||||
|
* add missing % when doing string formatting in EditStructure plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 13 Jun 2011 19:27:38 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-55) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix encoding error in keybinding.py when evaluation self.overwrite_exisiting
|
||||||
|
* convert Hyperlink plugin to unicode
|
||||||
|
* add hint to current plugin when a traceback occures during initialization
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 13 Jun 2011 19:23:13 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-54) unstable; urgency=low
|
||||||
|
|
||||||
|
* add copy method to Heading class to make a copy of the object
|
||||||
|
* track orig_start in Document.write method instead of the heading objects
|
||||||
|
* convert EditStructure plugin to liborgmode
|
||||||
|
* swap promote/demote meaning
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 13 Jun 2011 18:59:21 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-53) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix performance issue when identing/folding text
|
||||||
|
* rename method load to init_dom
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 28 May 2011 15:21:58 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-52) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix performance issue by introducing static computation of start value
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 28 May 2011 14:51:38 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-51) unstable; urgency=low
|
||||||
|
|
||||||
|
* add support for multiple color definitions for :foreground and :background
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Fri, 20 May 2011 08:29:59 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-50) unstable; urgency=low
|
||||||
|
|
||||||
|
* add support for org-todo-keyword-faces
|
||||||
|
* add support for nested org-todo-keyword lists
|
||||||
|
* add descriptions and examples for variables
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 15 May 2011 12:00:41 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-49) unstable; urgency=low
|
||||||
|
|
||||||
|
* general cleanup in syntax file
|
||||||
|
* add keyword default to all highlighting statements
|
||||||
|
* add syntax support for comments
|
||||||
|
* clear highlighting for org_shade_stars group if
|
||||||
|
g:org_heading_shade_leading_stars is not set
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 14 May 2011 23:33:50 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-48) unstable; urgency=low
|
||||||
|
|
||||||
|
* add syntax support for tables
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 14 May 2011 23:04:46 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-47) unstable; urgency=low
|
||||||
|
|
||||||
|
* add syntax support for DEADLINE and SCHEDULED
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 14 May 2011 21:27:07 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-46) unstable; urgency=low
|
||||||
|
|
||||||
|
* add syntax support for timestamps
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 14 May 2011 21:11:13 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-45) unstable; urgency=low
|
||||||
|
|
||||||
|
* add syntax support for properties
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sat, 14 May 2011 20:52:29 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-44) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert tests to unicode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 13 May 2011 23:39:38 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-43) unstable; urgency=low
|
||||||
|
|
||||||
|
* change comparison of None to "is" instead of "=="
|
||||||
|
* add function flatten_list to prevent sublists
|
||||||
|
* add convenience methods get_index_in_parent_list and get_parent_list to Heading class
|
||||||
|
* add __unicode__ and __str__ methods to Document
|
||||||
|
* started porting of EditStructure plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 13 May 2011 22:59:41 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-42) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix syntax error in syntax/org.vim
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 13 May 2011 19:30:44 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-41) unstable; urgency=low
|
||||||
|
|
||||||
|
* replace hbsitz's org syntax file
|
||||||
|
* change highlighting to integrate much better with colorschemes
|
||||||
|
* change license to AGPL 3
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Thu, 12 May 2011 18:46:13 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-40) unstable; urgency=low
|
||||||
|
|
||||||
|
* add tag_column and tabstop implementation to VimBuffer
|
||||||
|
* rename setting org_tags_column to org_tag_column
|
||||||
|
* rename setting org_tags_completion_ignorecase to
|
||||||
|
org_tag_completion_ignorecase
|
||||||
|
* fix unicode settings in test cases
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 10 May 2011 13:16:35 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-39) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix bug in echo function - use echo command
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 21:17:50 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-38) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert Navigator plugin to unicode and liborgmode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 21:17:17 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-37) unstable; urgency=low
|
||||||
|
|
||||||
|
* change echo function to use vim echo function
|
||||||
|
* add missing unicode parameter to string in ShowHide keybinding
|
||||||
|
* enable Misc plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 20:32:22 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-36) unstable; urgency=low
|
||||||
|
|
||||||
|
* convert Misc plugin to unicode and liborgmode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 20:14:04 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-35) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix a bug in ShowHide.toggle_folding when folding the first heading in
|
||||||
|
document when it doesn't have a child heading
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 19:55:52 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-34) unstable; urgency=low
|
||||||
|
|
||||||
|
* enable tests for ShowHide plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 18:40:11 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-33) unstable; urgency=low
|
||||||
|
|
||||||
|
* optimize update_changedtick to not run through all but just the wanted
|
||||||
|
buffer
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 18:33:14 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-32) unstable; urgency=low
|
||||||
|
|
||||||
|
* remove debug infomation from liborgmode.py
|
||||||
|
* add __str__ method for for Heading class
|
||||||
|
* port base functionality of orgmode to unicode
|
||||||
|
* echo a message instead of an error when no plugins are definied
|
||||||
|
* add heading parameter to VimBuffer methods
|
||||||
|
* add functionality to reuse VimBuffer objects and recognise user changes
|
||||||
|
* add BufNotInSync exception
|
||||||
|
* disable all but ShowHide plugin
|
||||||
|
* port ShowHide plugin to unicode and liborgmode
|
||||||
|
* port PluginExample to unicode and liborgmode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 18:20:59 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-31) unstable; urgency=low
|
||||||
|
|
||||||
|
* add vim swap files to gitignore list
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 14:29:41 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-30) unstable; urgency=low
|
||||||
|
|
||||||
|
* add support for unicode
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 14:27:37 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-29) unstable; urgency=low
|
||||||
|
|
||||||
|
* remove unsued import from liborgmode
|
||||||
|
* add heading parameter to VimBuffer.loag function
|
||||||
|
* update tests to use renamed liborgmode/document files
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 11:49:25 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-28) unstable; urgency=low
|
||||||
|
|
||||||
|
* rename ftplugin/orgmode/liborgmode.py to ftplugin/liborgmode.py
|
||||||
|
* rename ftplugin/orgmode/vimbuffer.py to ftplugin/orgmode/document.py
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 09 May 2011 11:46:39 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-27) unstable; urgency=low
|
||||||
|
|
||||||
|
* update README
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 06 May 2011 21:40:48 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-26) unstable; urgency=low
|
||||||
|
|
||||||
|
* add load method to documents for initializing the DOM
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 06 May 2011 21:21:39 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-25) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix heading initialization (Heading.parse_heading_from_data) when orig_start == 0
|
||||||
|
* fix comparing of deleted headings
|
||||||
|
* fix overwriting a single item in a heading
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 06 May 2011 21:12:49 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-24) unstable; urgency=low
|
||||||
|
|
||||||
|
* add support for tags and todo
|
||||||
|
* externalize heading create to a separate classmethod
|
||||||
|
* add all relevant parameters to the heading constructor
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 06 May 2011 20:20:37 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-23) unstable; urgency=low
|
||||||
|
|
||||||
|
* make Document.is_dirty function test all headings not just the first two
|
||||||
|
levels
|
||||||
|
* add more tests for replacing headings
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Thu, 05 May 2011 21:37:27 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-22) unstable; urgency=low
|
||||||
|
|
||||||
|
* distinguish between heading and body changes
|
||||||
|
* make writing the VimBuffer more efficient
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Thu, 05 May 2011 21:03:28 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-21) unstable; urgency=low
|
||||||
|
|
||||||
|
* use functionality of UserList in MultiPurposeList
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Thu, 05 May 2011 20:13:26 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-20) unstable; urgency=low
|
||||||
|
|
||||||
|
* update README
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Thu, 05 May 2011 10:51:12 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-19) unstable; urgency=low
|
||||||
|
|
||||||
|
* major refactoring of liborgmode
|
||||||
|
* tests and plugins are currently broken
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Thu, 05 May 2011 10:48:44 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-18) unstable; urgency=low
|
||||||
|
|
||||||
|
* install -D doesn't work on BSD based systems; migrate commands to install -d
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 02 May 2011 15:41:17 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-17) unstable; urgency=low
|
||||||
|
|
||||||
|
* merge date-plugin from sotte
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 02 May 2011 15:40:40 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-16) unstable; urgency=low
|
||||||
|
|
||||||
|
* rename heading.py to liborgmode.py
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 26 Apr 2011 21:55:17 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-15) unstable; urgency=low
|
||||||
|
|
||||||
|
* add variable g:org_syntax_highlight_leading_stars to customize
|
||||||
|
highlighting of leading stars
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 26 Apr 2011 21:30:31 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-14) unstable; urgency=low
|
||||||
|
|
||||||
|
* merge todo_refactoring from sotte
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 26 Apr 2011 21:16:19 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-13) unstable; urgency=low
|
||||||
|
|
||||||
|
* add documentation in form of a diagram describing the functionality of
|
||||||
|
vim-orgmode, liborgmode and orgcmd
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 26 Apr 2011 20:41:20 +0900
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-12) unstable; urgency=low
|
||||||
|
|
||||||
|
* update todos
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Mon, 28 Mar 2011 00:07:37 +0200
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-11) unstable; urgency=low
|
||||||
|
|
||||||
|
* move initialization to start method
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Thu, 24 Mar 2011 20:39:49 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-10) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix problem with the order of decorators (@classmethod must be first)
|
||||||
|
* remove silence from
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Thu, 24 Mar 2011 17:36:55 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-9) unstable; urgency=low
|
||||||
|
|
||||||
|
* rename update_tag_alignment
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Wed, 23 Mar 2011 19:40:44 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-8) unstable; urgency=low
|
||||||
|
|
||||||
|
* make edit tasks update tags alignment
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 22 Mar 2011 22:28:59 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-7) unstable; urgency=low
|
||||||
|
|
||||||
|
* clean up of unused imports
|
||||||
|
* change a bunch of methods into classmethods
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 22 Mar 2011 22:17:44 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-6) unstable; urgency=low
|
||||||
|
|
||||||
|
* add vim as build dependency
|
||||||
|
* update Installation and Building information in README
|
||||||
|
* update todos
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 22 Mar 2011 21:35:02 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-5) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix passing of function arguments
|
||||||
|
* fix empty links creation
|
||||||
|
* update todos for Hyperlinks plugin
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <ebersbach@univention.de> Mon, 21 Mar 2011 12:35:14 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-4) unstable; urgency=low
|
||||||
|
|
||||||
|
* implement Hyperlinks plugin (closes: #11)
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Sun, 20 Mar 2011 00:07:04 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-3) unstable; urgency=low
|
||||||
|
|
||||||
|
* fix syntax issue in PluginExample.py
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Fri, 11 Mar 2011 08:47:34 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* correct filename of PluginExample.py (closes: #3)
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Wed, 09 Mar 2011 22:02:49 +0100
|
||||||
|
|
||||||
|
vim-orgmode (0.1.0-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Initial release.
|
||||||
|
|
||||||
|
-- Jan Christoph Ebersbach <jceb@e-jc.de> Tue, 22 Feb 2011 22:14:01 +0100
|
1
pack/acp/start/vim-orgmode/debian/compat
Normal file
1
pack/acp/start/vim-orgmode/debian/compat
Normal file
|
@ -0,0 +1 @@
|
||||||
|
5
|
14
pack/acp/start/vim-orgmode/debian/control
Normal file
14
pack/acp/start/vim-orgmode/debian/control
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Source: vim-orgmode
|
||||||
|
Priority: extra
|
||||||
|
Section: editors
|
||||||
|
Maintainer: Jan Christoph Ebersbach <jceb@e-jc.de>
|
||||||
|
Build-Depends: debhelper (>= 7), vim
|
||||||
|
Standards-Version: 3.7.3
|
||||||
|
Homepage: http://www.e-jc.de/
|
||||||
|
|
||||||
|
Package: vim-orgmode
|
||||||
|
Architecture: all
|
||||||
|
Depends: python, vim-common, vim
|
||||||
|
Suggests: emacs
|
||||||
|
Description: Clone of Org-mode for Vim
|
||||||
|
Clone of Org-mode for Vim
|
28
pack/acp/start/vim-orgmode/debian/copyright
Normal file
28
pack/acp/start/vim-orgmode/debian/copyright
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
Copyright (C) 2010,2011 Jan Christoph Ebersbach
|
||||||
|
|
||||||
|
http://www.e-jc.de/
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License version 3 as
|
||||||
|
published by the Free Software Foundation.
|
||||||
|
|
||||||
|
Binary versions of this file provided by Univention to you as
|
||||||
|
well as other copyrighted, protected or trademarked materials like
|
||||||
|
Logos, graphics, fonts, specific documentations and configurations,
|
||||||
|
cryptographic keys etc. are subject to a license agreement between
|
||||||
|
you and Univention.
|
||||||
|
|
||||||
|
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
USA
|
||||||
|
|
||||||
|
Except file syntax/org.vim which was copied from Herbert Sitz and
|
||||||
|
changed later on by Jan Christoph Ebersbach.
|
1
pack/acp/start/vim-orgmode/debian/dirs
Normal file
1
pack/acp/start/vim-orgmode/debian/dirs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
usr/share/vim/addons
|
2
pack/acp/start/vim-orgmode/debian/docs
Normal file
2
pack/acp/start/vim-orgmode/debian/docs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
README.org
|
||||||
|
LICENSE
|
1
pack/acp/start/vim-orgmode/debian/examples
Normal file
1
pack/acp/start/vim-orgmode/debian/examples
Normal file
|
@ -0,0 +1 @@
|
||||||
|
examples/plugins/PluginExample.py
|
11
pack/acp/start/vim-orgmode/debian/rules
Executable file
11
pack/acp/start/vim-orgmode/debian/rules
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
# -*- makefile -*-
|
||||||
|
|
||||||
|
DESTDIR=$(CURDIR)/debian/vim-orgmode
|
||||||
|
ADDONSDIR=/usr/share/vim/addons
|
||||||
|
|
||||||
|
override_dh_auto_install:
|
||||||
|
dh_auto_install -- DESTDIR=$(DESTDIR) VIMDIR=$(ADDONSDIR)
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@
|
1553
pack/acp/start/vim-orgmode/doc/orgguide.txt
Normal file
1553
pack/acp/start/vim-orgmode/doc/orgguide.txt
Normal file
File diff suppressed because it is too large
Load diff
9
pack/acp/start/vim-orgmode/documentation/Makefile
Normal file
9
pack/acp/start/vim-orgmode/documentation/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
diagram: diagram.png
|
||||||
|
|
||||||
|
diagram.png: diagram.txt
|
||||||
|
if [ -n "$(shell which ditaa)" ]; then ditaa $^ $@; elif [ -f ditaa0_9.jar ]; then java -jar ditaa0_9.jar $^ $@; else echo "Unable to find ditaa, please install ditaa or download ditaa0_9.jar (http://ditaa.sf.net/)and place it in folder documentation"; exit 1 ; fi
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f diagram.png
|
||||||
|
|
||||||
|
.PHONY: diagram clean
|
75
pack/acp/start/vim-orgmode/documentation/diagram.txt
Normal file
75
pack/acp/start/vim-orgmode/documentation/diagram.txt
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/------------------------------\ +-----------------------------------+
|
||||||
|
| Legend | | vim-orgmode |
|
||||||
|
| cCCC | | cBLU |
|
||||||
|
| | | o support for plugins |
|
||||||
|
| | | o plugins implement orgmode |
|
||||||
|
+--------------+---------------+ | functionality in vim |
|
||||||
|
| vim-orgmode | liborgmode | | o mainly plugins implement |
|
||||||
|
| cBLU | cYEL | | keybindings for interactively |
|
||||||
|
| | | | changing org-mode files |
|
||||||
|
| | | | |
|
||||||
|
+--------------+---------------+ | |
|
||||||
|
| orgcmd | doesn't exist | +---+-------------------------------+
|
||||||
|
| cRED | yet | |1
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
\--------------+-=-------------/ |x
|
||||||
|
v
|
||||||
|
+-----------------------------------+
|
||||||
|
| Plugins |
|
||||||
|
| cBLU |
|
||||||
|
| o manipulate headings |
|
||||||
|
| o change tags, todo states, lists |
|
||||||
|
| o integrate with orgcmd |
|
||||||
|
| o reusable functionality doesn't |
|
||||||
|
| belong here but into liborgmode!|
|
||||||
|
| o timer, time tracking |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
+---+-------------------------------+ +------------+
|
||||||
|
| | VimBuffer |
|
||||||
|
| | {d} |
|
||||||
|
| /---------+ cBLU |
|
||||||
|
| | | |
|
||||||
|
v | +------------+
|
||||||
|
+-----------------------------------+ +---------------++
|
||||||
|
1 | Document | | Extend Document| +-=------------+
|
||||||
|
/-----+ cYEL |<-------+ cYEL | |+------------+|
|
||||||
|
| | o represents an org-mode document | | o abstraction | || file ||
|
||||||
|
| | o contains links to other | | of data/file | || {d} ||
|
||||||
|
| x | documents | | access +-------+| cYEL ||
|
||||||
|
\---->| o contains meta information | | o read | || ||
|
||||||
|
| o contains headings | | o write | |+------------+|
|
||||||
|
| | | | +--------------+
|
||||||
|
| | | |
|
||||||
|
| | +---------------++ +-=------------+
|
||||||
|
+----+------------------------------+ | |+------------+|
|
||||||
|
|1 ^ | || stdin/ ||
|
||||||
|
| | \--------+| stdout ||
|
||||||
|
| | || {d} ||
|
||||||
|
| \------------\ || cRED ||
|
||||||
|
|x | |+------------+|
|
||||||
|
v | +--------------+
|
||||||
|
+-----------------------------------+ +-+=--------------------------+
|
||||||
|
1 | Heading | |+---------------------------+|
|
||||||
|
/-----+ cYEL | || orgcmd ||
|
||||||
|
| | o represents a single heading | || cRED ||
|
||||||
|
| | o contains links to other headings| || o implement command line ||
|
||||||
|
| x | o parent heading | || tool for processing org ||
|
||||||
|
\---->| o siblings | || files ||
|
||||||
|
| o children | || o provide output filter ||
|
||||||
|
| | || o convert org-mode docs ||
|
||||||
|
| o title | || to other formats ||
|
||||||
|
| o level | |+---------------------------+|
|
||||||
|
| o body | +-----------------------------+
|
||||||
|
| o tags |
|
||||||
|
| o todo state |
|
||||||
|
| o closing date |
|
||||||
|
| o scheduled date |
|
||||||
|
| o priority |
|
||||||
|
| o item lists (class hierarchy) |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
+-----------------------------------+
|
||||||
|
|
3087
pack/acp/start/vim-orgmode/documentation/emacs_orgguide.org
Normal file
3087
pack/acp/start/vim-orgmode/documentation/emacs_orgguide.org
Normal file
File diff suppressed because it is too large
Load diff
2689
pack/acp/start/vim-orgmode/documentation/emacs_orgguide.texi
Normal file
2689
pack/acp/start/vim-orgmode/documentation/emacs_orgguide.texi
Normal file
File diff suppressed because it is too large
Load diff
BIN
pack/acp/start/vim-orgmode/examples/mylife.gif
Normal file
BIN
pack/acp/start/vim-orgmode/examples/mylife.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 99 KiB |
26
pack/acp/start/vim-orgmode/examples/mylife.org
Normal file
26
pack/acp/start/vim-orgmode/examples/mylife.org
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
* My Life in plain text
|
||||||
|
- [X] birth
|
||||||
|
- [-] life [50%]
|
||||||
|
- [X] use vim
|
||||||
|
- [ ] get everything else done
|
||||||
|
* Write minutes of last meeting <2014-08-08 Fri> :work:
|
||||||
|
** DONE John said
|
||||||
|
this
|
||||||
|
** TODO Mary said
|
||||||
|
that
|
||||||
|
** WAITING What did Mark say?
|
||||||
|
[[http://example.com/here/is/the/recording][1st recording]]
|
||||||
|
[[http://example.com/here/is/the/recording][2nd recording]]
|
||||||
|
* Some folding headline 1 :one:
|
||||||
|
** Folded
|
||||||
|
*** Even more folded
|
||||||
|
* Some folding headline 2
|
||||||
|
** Folded :two:
|
||||||
|
*** Even more folded
|
||||||
|
* Some folding headline 3
|
||||||
|
** Folded
|
||||||
|
*** Even more folded :three:
|
||||||
|
* Some folding headline 4
|
||||||
|
** Folded
|
||||||
|
*** Even more folded
|
||||||
|
completely unfolded
|
BIN
pack/acp/start/vim-orgmode/examples/mylife.png
Normal file
BIN
pack/acp/start/vim-orgmode/examples/mylife.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
53
pack/acp/start/vim-orgmode/examples/plugins/PluginExample.py
Normal file
53
pack/acp/start/vim-orgmode/examples/plugins/PluginExample.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from orgmode import echo, echom, echoe, ORGMODE, apply_count, repeat
|
||||||
|
from orgmode.menu import Submenu, Separator, ActionEntry
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, Command
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
|
||||||
|
class Example(object):
|
||||||
|
u"""
|
||||||
|
Example plugin.
|
||||||
|
|
||||||
|
TODO: Extend this doc!
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'Example')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def action(cls):
|
||||||
|
u"""
|
||||||
|
Some kind of action.
|
||||||
|
|
||||||
|
:returns: TODO
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of the plugin.
|
||||||
|
|
||||||
|
Key bindings and other initialization should be done here.
|
||||||
|
"""
|
||||||
|
# an Action menu entry which binds "keybinding" to action ":action"
|
||||||
|
self.commands.append(Command(u'OrgActionCommand',
|
||||||
|
u':py ORGMODE.plugins["Example"].action()'))
|
||||||
|
self.keybindings.append(Keybinding(u'keybinding',
|
||||||
|
Plug(u'OrgAction', self.commands[-1])))
|
||||||
|
self.menu + ActionEntry(u'&Action', self.keybindings[-1])
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
2
pack/acp/start/vim-orgmode/ftdetect/org.vim
Normal file
2
pack/acp/start/vim-orgmode/ftdetect/org.vim
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
autocmd BufNewFile,BufRead *.org setfiletype org
|
||||||
|
"autocmd BufNewFile,BufReadPost org:todo* setfiletype orgtodo
|
5
pack/acp/start/vim-orgmode/ftplugin/org.cnf
Normal file
5
pack/acp/start/vim-orgmode/ftplugin/org.cnf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
--langdef=org
|
||||||
|
--langmap=org:.org
|
||||||
|
--regex-org=/^(\*+)[[:space:]]+(.*)([[:space:]]+:[^\t ]*:)?$/\1 \2/s,sections/
|
||||||
|
--regex-org=/\[\[([^][]+)\]\]/\1/h,hyperlinks/
|
||||||
|
--regex-org=/\[\[[^][]+\]\[([^][]+)\]\]/\1/h,hyperlinks/
|
169
pack/acp/start/vim-orgmode/ftplugin/org.vim
Normal file
169
pack/acp/start/vim-orgmode/ftplugin/org.vim
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
" org.vim -- Text outlining and task management for Vim based on Emacs' Org-Mode
|
||||||
|
" @Author : Jan Christoph Ebersbach (jceb@e-jc.de)
|
||||||
|
" @License : AGPL3 (see http://www.gnu.org/licenses/agpl.txt)
|
||||||
|
" @Created : 2010-10-03
|
||||||
|
" @Last Modified: Tue 13. Sep 2011 20:52:57 +0200 CEST
|
||||||
|
" @Revision : 0.4
|
||||||
|
" vi: ft=vim:tw=80:sw=4:ts=4:fdm=marker
|
||||||
|
|
||||||
|
if v:version > 702
|
||||||
|
if has('python3')
|
||||||
|
let s:py_version = 'python3 '
|
||||||
|
let s:py_env = 'python3 << EOF'
|
||||||
|
elseif has('python')
|
||||||
|
let s:py_version = 'python '
|
||||||
|
let s:py_env = 'python << EOF'
|
||||||
|
else
|
||||||
|
echoerr "Unable to start orgmode. Orgmode depends on Vim >= 7.3 with Python support complied in."
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
echoerr "Unable to start orgmode. Orgmode depends on Vim >= 7.3 with Python support complied in."
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Init buffer for file {{{1
|
||||||
|
if ! exists('b:did_ftplugin')
|
||||||
|
" default emacs settings
|
||||||
|
setlocal comments=fb:*,b:#,fb:-
|
||||||
|
setlocal commentstring=#\ %s
|
||||||
|
setlocal conceallevel=2 concealcursor=nc
|
||||||
|
" original emacs settings are: setlocal tabstop=6 shiftwidth=6, but because
|
||||||
|
" of checkbox indentation the following settings are used:
|
||||||
|
setlocal tabstop=6 shiftwidth=6
|
||||||
|
if exists('g:org_tag_column')
|
||||||
|
exe 'setlocal textwidth='.g:org_tag_column
|
||||||
|
else
|
||||||
|
setlocal textwidth=77
|
||||||
|
endif
|
||||||
|
|
||||||
|
" expand tab for counting level of checkbox
|
||||||
|
setlocal expandtab
|
||||||
|
|
||||||
|
" enable % for angle brackets < >
|
||||||
|
setlocal matchpairs+=<:>
|
||||||
|
|
||||||
|
" register keybindings if they don't have been registered before
|
||||||
|
if exists("g:loaded_org")
|
||||||
|
exe s:py_version . 'ORGMODE.register_keybindings()'
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Load orgmode just once {{{1
|
||||||
|
if &cp || exists("g:loaded_org")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
let g:loaded_org = 1
|
||||||
|
|
||||||
|
" Default org plugins that will be loaded (in the given order) {{{2
|
||||||
|
if ! exists('g:org_plugins') && ! exists('b:org_plugins')
|
||||||
|
let g:org_plugins = ['ShowHide', '|', 'Navigator', 'EditStructure', 'EditCheckbox', '|', 'Hyperlinks', '|', 'Todo', 'TagsProperties', 'Date', 'Agenda', 'Misc', '|', 'Export']
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Default org plugin settings {{{2
|
||||||
|
" What does this do?
|
||||||
|
if ! exists('g:org_syntax_highlight_leading_stars') && ! exists('b:org_syntax_highlight_leading_stars')
|
||||||
|
let g:org_syntax_highlight_leading_stars = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
" setting to conceal aggresively
|
||||||
|
if ! exists('g:org_aggressive_conceal') && ! exists('b:org_aggressive_conceal')
|
||||||
|
let g:org_aggressive_conceal = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Defined in separate plugins
|
||||||
|
" Adding Behavior preference:
|
||||||
|
" 1: go into insert-mode when new heading/checkbox/plainlist added
|
||||||
|
" 0: retain original mode when new heading/checkbox/plainlist added
|
||||||
|
if ! exists('g:org_prefer_insert_mode') && ! exists('b:org_prefer_insert_mode')
|
||||||
|
let g:org_prefer_insert_mode = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Menu and document handling {{{1
|
||||||
|
function! <SID>OrgRegisterMenu()
|
||||||
|
exe s:py_version . 'ORGMODE.register_menu()'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! <SID>OrgUnregisterMenu()
|
||||||
|
exe s:py_version . 'ORGMODE.unregister_menu()'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! <SID>OrgDeleteUnusedDocument(bufnr)
|
||||||
|
exe s:py_env
|
||||||
|
b = int(vim.eval('a:bufnr'))
|
||||||
|
if b in ORGMODE._documents:
|
||||||
|
del ORGMODE._documents[b]
|
||||||
|
EOF
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" show and hide Org menu depending on the filetype
|
||||||
|
augroup orgmode
|
||||||
|
au BufEnter * :if &filetype == "org" | call <SID>OrgRegisterMenu() | endif
|
||||||
|
au BufLeave * :if &filetype == "org" | call <SID>OrgUnregisterMenu() | endif
|
||||||
|
au BufDelete * :call <SID>OrgDeleteUnusedDocument(expand('<abuf>'))
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
" Start orgmode {{{1
|
||||||
|
" Expand our path
|
||||||
|
exec s:py_env
|
||||||
|
import vim, os, sys
|
||||||
|
|
||||||
|
for p in vim.eval("&runtimepath").split(','):
|
||||||
|
dname = os.path.join(p, "ftplugin")
|
||||||
|
if os.path.exists(os.path.join(dname, "orgmode")):
|
||||||
|
if dname not in sys.path:
|
||||||
|
sys.path.append(dname)
|
||||||
|
break
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE, insert_at_cursor, get_user_input, date_to_str
|
||||||
|
ORGMODE.start()
|
||||||
|
|
||||||
|
from Date import Date
|
||||||
|
import datetime
|
||||||
|
EOF
|
||||||
|
|
||||||
|
" 3rd Party Plugin Integration {{{1
|
||||||
|
" * Repeat {{{2
|
||||||
|
try
|
||||||
|
call repeat#set()
|
||||||
|
catch
|
||||||
|
endtry
|
||||||
|
|
||||||
|
" * Tagbar {{{2
|
||||||
|
let g:tagbar_type_org = {
|
||||||
|
\ 'ctagstype' : 'org',
|
||||||
|
\ 'kinds' : [
|
||||||
|
\ 's:sections',
|
||||||
|
\ 'h:hyperlinks',
|
||||||
|
\ ],
|
||||||
|
\ 'sort' : 0,
|
||||||
|
\ 'deffile' : expand('<sfile>:p:h') . '/org.cnf'
|
||||||
|
\ }
|
||||||
|
|
||||||
|
" * Taglist {{{2
|
||||||
|
if exists('g:Tlist_Ctags_Cmd')
|
||||||
|
" Pass parameters to taglist
|
||||||
|
let g:tlist_org_settings = 'org;s:section;h:hyperlinks'
|
||||||
|
let g:Tlist_Ctags_Cmd .= ' --options=' . expand('<sfile>:p:h') . '/org.cnf '
|
||||||
|
endif
|
||||||
|
|
||||||
|
" * Calendar.vim {{{2
|
||||||
|
fun CalendarAction(day, month, year, week, dir)
|
||||||
|
let g:org_timestamp = printf("%04d-%02d-%02d Fri", a:year, a:month, a:day)
|
||||||
|
let datetime_date = printf("datetime.date(%d, %d, %d)", a:year, a:month, a:day)
|
||||||
|
exe s:py_version . "selected_date = " . datetime_date
|
||||||
|
" get_user_input
|
||||||
|
let msg = printf("Inserting %s | Modify date", g:org_timestamp)
|
||||||
|
exe s:py_version . "modifier = get_user_input('" . msg . "')"
|
||||||
|
" change date according to user input
|
||||||
|
exe s:py_version . "newdate = Date._modify_time(selected_date, modifier)"
|
||||||
|
exe s:py_version . "newdate = date_to_str(newdate)"
|
||||||
|
" close Calendar
|
||||||
|
exe "q"
|
||||||
|
" goto previous window
|
||||||
|
exe "wincmd p"
|
||||||
|
exe s:py_version . "timestamp = '" . g:org_timestamp_template . "' % newdate"
|
||||||
|
exe s:py_version . "insert_at_cursor(timestamp)"
|
||||||
|
" restore calendar_action
|
||||||
|
let g:calendar_action = g:org_calendar_action_backup
|
||||||
|
endf
|
1
pack/acp/start/vim-orgmode/ftplugin/orgmode/__init__.py
Normal file
1
pack/acp/start/vim-orgmode/ftplugin/orgmode/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
411
pack/acp/start/vim-orgmode/ftplugin/orgmode/_vim.py
Normal file
411
pack/acp/start/vim-orgmode/ftplugin/orgmode/_vim.py
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
VIM ORGMODE
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
TODO
|
||||||
|
"""
|
||||||
|
|
||||||
|
import imp
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import vim
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import orgmode.keybinding
|
||||||
|
import orgmode.menu
|
||||||
|
import orgmode.plugins
|
||||||
|
import orgmode.settings
|
||||||
|
from orgmode.exceptions import PluginError
|
||||||
|
from orgmode.vimbuffer import VimBuffer
|
||||||
|
from orgmode.liborgmode.agenda import AgendaManager
|
||||||
|
|
||||||
|
|
||||||
|
REPEAT_EXISTS = bool(int(vim.eval('exists("*repeat#set()")')))
|
||||||
|
TAGSPROPERTIES_EXISTS = False
|
||||||
|
|
||||||
|
cache_heading = None
|
||||||
|
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
|
||||||
|
def realign_tags(f):
|
||||||
|
u"""
|
||||||
|
Update tag alignment, dependency to TagsProperties plugin!
|
||||||
|
"""
|
||||||
|
def r(*args, **kwargs):
|
||||||
|
global TAGSPROPERTIES_EXISTS
|
||||||
|
res = f(*args, **kwargs)
|
||||||
|
|
||||||
|
if not TAGSPROPERTIES_EXISTS and u'TagsProperties' in ORGMODE.plugins:
|
||||||
|
TAGSPROPERTIES_EXISTS = True
|
||||||
|
|
||||||
|
if TAGSPROPERTIES_EXISTS:
|
||||||
|
ORGMODE.plugins[u'TagsProperties'].realign_tags()
|
||||||
|
|
||||||
|
return res
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def repeat(f):
|
||||||
|
u"""
|
||||||
|
Integrate with the repeat plugin if available
|
||||||
|
|
||||||
|
The decorated function must return the name of the <Plug> command to
|
||||||
|
execute by the repeat plugin.
|
||||||
|
"""
|
||||||
|
def r(*args, **kwargs):
|
||||||
|
res = f(*args, **kwargs)
|
||||||
|
if REPEAT_EXISTS and isinstance(res, basestring):
|
||||||
|
vim.command(u_encode(u'silent! call repeat#set("\\<Plug>%s")' % res))
|
||||||
|
return res
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def apply_count(f):
|
||||||
|
u"""
|
||||||
|
Decorator which executes function v:count or v:prevount (not implemented,
|
||||||
|
yet) times. The decorated function must return a value that evaluates to
|
||||||
|
True otherwise the function is not repeated.
|
||||||
|
"""
|
||||||
|
def r(*args, **kwargs):
|
||||||
|
count = 0
|
||||||
|
try:
|
||||||
|
count = int(vim.eval(u_encode(u'v:count')))
|
||||||
|
|
||||||
|
# visual count is not implemented yet
|
||||||
|
#if not count:
|
||||||
|
# count = int(vim.eval(u'v:prevcount'.encode(u'utf-8')))
|
||||||
|
except BaseException as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
res = f(*args, **kwargs)
|
||||||
|
count -= 1
|
||||||
|
while res and count > 0:
|
||||||
|
f(*args, **kwargs)
|
||||||
|
count -= 1
|
||||||
|
return res
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def echo(message):
|
||||||
|
u"""
|
||||||
|
Print a regular message that will not be visible to the user when
|
||||||
|
multiple lines are printed
|
||||||
|
"""
|
||||||
|
for m in message.split(u'\n'):
|
||||||
|
vim.command(u_encode(u':echo "%s"' % m))
|
||||||
|
|
||||||
|
|
||||||
|
def echom(message):
|
||||||
|
u"""
|
||||||
|
Print a regular message that will be visible to the user, even when
|
||||||
|
multiple lines are printed
|
||||||
|
"""
|
||||||
|
# probably some escaping is needed here
|
||||||
|
for m in message.split(u'\n'):
|
||||||
|
vim.command(u_encode(u':echomsg "%s"' % m))
|
||||||
|
|
||||||
|
|
||||||
|
def echoe(message):
|
||||||
|
u"""
|
||||||
|
Print an error message. This should only be used for serious errors!
|
||||||
|
"""
|
||||||
|
# probably some escaping is needed here
|
||||||
|
for m in message.split(u'\n'):
|
||||||
|
vim.command(u_encode(u':echoerr "%s"' % m))
|
||||||
|
|
||||||
|
|
||||||
|
def insert_at_cursor(text, move=True, start_insertmode=False):
|
||||||
|
u"""Insert text at the position of the cursor.
|
||||||
|
|
||||||
|
If move==True move the cursor with the inserted text.
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document(allow_dirty=True)
|
||||||
|
line, col = vim.current.window.cursor
|
||||||
|
_text = d._content[line - 1]
|
||||||
|
d._content[line - 1] = _text[:col + 1] + text + _text[col + 1:]
|
||||||
|
if move:
|
||||||
|
vim.current.window.cursor = (line, col + len(text))
|
||||||
|
if start_insertmode:
|
||||||
|
vim.command(u_encode(u'startinsert'))
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_input(message):
|
||||||
|
u"""Print the message and take input from the user.
|
||||||
|
Return the input or None if there is no input.
|
||||||
|
"""
|
||||||
|
vim.command(u_encode(u'call inputsave()'))
|
||||||
|
vim.command(u_encode(u"let user_input = input('" + message + u": ')"))
|
||||||
|
vim.command(u_encode(u'call inputrestore()'))
|
||||||
|
try:
|
||||||
|
return u_decode(vim.eval(u_encode(u'user_input')))
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_bufnumber(bufname):
|
||||||
|
"""
|
||||||
|
Return the number of the buffer for the given bufname if it exist;
|
||||||
|
else None.
|
||||||
|
"""
|
||||||
|
for b in vim.buffers:
|
||||||
|
if b.name == bufname:
|
||||||
|
return int(b.number)
|
||||||
|
|
||||||
|
|
||||||
|
def get_bufname(bufnr):
|
||||||
|
"""
|
||||||
|
Return the name of the buffer for the given bufnr if it exist; else None.
|
||||||
|
"""
|
||||||
|
for b in vim.buffers:
|
||||||
|
if b.number == bufnr:
|
||||||
|
return b.name
|
||||||
|
|
||||||
|
|
||||||
|
def indent_orgmode():
|
||||||
|
u""" Set the indent value for the current line in the variable
|
||||||
|
b:indent_level
|
||||||
|
|
||||||
|
Vim prerequisites:
|
||||||
|
:setlocal indentexpr=Method-which-calls-indent_orgmode
|
||||||
|
|
||||||
|
:returns: None
|
||||||
|
"""
|
||||||
|
line = int(vim.eval(u_encode(u'v:lnum')))
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
heading = d.current_heading(line - 1)
|
||||||
|
if heading and line != heading.start_vim:
|
||||||
|
heading.init_checkboxes()
|
||||||
|
checkbox = heading.current_checkbox()
|
||||||
|
level = heading.level + 1
|
||||||
|
if checkbox:
|
||||||
|
if line != checkbox.start_vim:
|
||||||
|
# indent body up to the beginning of the checkbox' text
|
||||||
|
# if checkbox isn't indented to the proper location, the body
|
||||||
|
# won't be indented either
|
||||||
|
level = checkbox.level + len(checkbox.type) + 1 + \
|
||||||
|
(4 if checkbox.status else 0)
|
||||||
|
vim.command(u_encode((u'let b:indent_level = %d' % level)))
|
||||||
|
|
||||||
|
|
||||||
|
def fold_text(allow_dirty=False):
|
||||||
|
u""" Set the fold text
|
||||||
|
:setlocal foldtext=Method-which-calls-foldtext
|
||||||
|
|
||||||
|
:allow_dirty: Perform a query without (re)building the DOM if True
|
||||||
|
:returns: None
|
||||||
|
"""
|
||||||
|
line = int(vim.eval(u_encode(u'v:foldstart')))
|
||||||
|
d = ORGMODE.get_document(allow_dirty=allow_dirty)
|
||||||
|
heading = None
|
||||||
|
if allow_dirty:
|
||||||
|
heading = d.find_current_heading(line - 1)
|
||||||
|
else:
|
||||||
|
heading = d.current_heading(line - 1)
|
||||||
|
if heading:
|
||||||
|
str_heading = unicode(heading)
|
||||||
|
|
||||||
|
# expand tabs
|
||||||
|
ts = int(vim.eval(u_encode(u'&ts')))
|
||||||
|
idx = str_heading.find(u'\t')
|
||||||
|
if idx != -1:
|
||||||
|
tabs, spaces = divmod(idx, ts)
|
||||||
|
str_heading = str_heading.replace(u'\t', u' ' * (ts - spaces), 1)
|
||||||
|
str_heading = str_heading.replace(u'\t', u' ' * ts)
|
||||||
|
|
||||||
|
# Workaround for vim.command seems to break the completion menu
|
||||||
|
vim.eval(u_encode(u'SetOrgFoldtext("%s...")' % (re.sub(r'\[\[([^[\]]*\]\[)?([^[\]]+)\]\]', r'\2',
|
||||||
|
str_heading).replace( u'\\', u'\\\\').replace(u'"', u'\\"'), )))
|
||||||
|
|
||||||
|
|
||||||
|
def fold_orgmode(allow_dirty=False):
|
||||||
|
u""" Set the fold expression/value for the current line in the variable
|
||||||
|
b:fold_expr
|
||||||
|
|
||||||
|
Vim prerequisites:
|
||||||
|
:setlocal foldmethod=expr
|
||||||
|
:setlocal foldexpr=Method-which-calls-fold_orgmode
|
||||||
|
|
||||||
|
:allow_dirty: Perform a query without (re)building the DOM if True
|
||||||
|
:returns: None
|
||||||
|
"""
|
||||||
|
line = int(vim.eval(u_encode(u'v:lnum')))
|
||||||
|
d = ORGMODE.get_document(allow_dirty=allow_dirty)
|
||||||
|
heading = None
|
||||||
|
if allow_dirty:
|
||||||
|
heading = d.find_current_heading(line - 1)
|
||||||
|
else:
|
||||||
|
heading = d.current_heading(line - 1)
|
||||||
|
|
||||||
|
# if cache_heading != heading:
|
||||||
|
# heading.init_checkboxes()
|
||||||
|
# checkbox = heading.current_checkbox()
|
||||||
|
|
||||||
|
# cache_heading = heading
|
||||||
|
if heading:
|
||||||
|
# if checkbox:
|
||||||
|
# vim.command((u'let b:fold_expr = ">%d"' % heading.level + checkbox.level).encode(u'utf-8'))
|
||||||
|
if 0:
|
||||||
|
pass
|
||||||
|
elif line == heading.start_vim:
|
||||||
|
vim.command(u_encode(u'let b:fold_expr = ">%d"' % heading.level))
|
||||||
|
#elif line == heading.end_vim:
|
||||||
|
# vim.command((u'let b:fold_expr = "<%d"' % heading.level).encode(u'utf-8'))
|
||||||
|
# end_of_last_child_vim is a performance junky and is actually not needed
|
||||||
|
#elif line == heading.end_of_last_child_vim:
|
||||||
|
# vim.command((u'let b:fold_expr = "<%d"' % heading.level).encode(u'utf-8'))
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'let b:fold_expr = %d' % heading.level))
|
||||||
|
|
||||||
|
|
||||||
|
def date_to_str(date):
|
||||||
|
if isinstance(date, datetime):
|
||||||
|
date = date.strftime(u_decode(u_encode(u'%Y-%m-%d %a %H:%M')))
|
||||||
|
else:
|
||||||
|
date = date.strftime(u_decode(u_encode(u'%Y-%m-%d %a')))
|
||||||
|
return date
|
||||||
|
|
||||||
|
class OrgMode(object):
|
||||||
|
u""" Vim Buffer """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
object.__init__(self)
|
||||||
|
self.debug = bool(int(orgmode.settings.get(u'org_debug', False)))
|
||||||
|
|
||||||
|
self.orgmenu = orgmode.menu.Submenu(u'&Org')
|
||||||
|
self._plugins = {}
|
||||||
|
# list of vim buffer objects
|
||||||
|
self._documents = {}
|
||||||
|
|
||||||
|
# agenda manager
|
||||||
|
self.agenda_manager = AgendaManager()
|
||||||
|
|
||||||
|
def get_document(self, bufnr=0, allow_dirty=False):
|
||||||
|
""" Retrieve instance of vim buffer document. This Document should be
|
||||||
|
used for manipulating the vim buffer.
|
||||||
|
|
||||||
|
:bufnr: Retrieve document with bufnr
|
||||||
|
:allow_dirty: Allow the retrieved document to be dirty
|
||||||
|
|
||||||
|
:returns: vim buffer instance
|
||||||
|
"""
|
||||||
|
if bufnr == 0:
|
||||||
|
bufnr = vim.current.buffer.number
|
||||||
|
|
||||||
|
if bufnr in self._documents:
|
||||||
|
if allow_dirty or self._documents[bufnr].is_insync:
|
||||||
|
return self._documents[bufnr]
|
||||||
|
self._documents[bufnr] = VimBuffer(bufnr).init_dom()
|
||||||
|
return self._documents[bufnr]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def plugins(self):
|
||||||
|
return self._plugins.copy()
|
||||||
|
|
||||||
|
@orgmode.keybinding.register_keybindings
|
||||||
|
@orgmode.keybinding.register_commands
|
||||||
|
@orgmode.menu.register_menu
|
||||||
|
def register_plugin(self, plugin):
|
||||||
|
if not isinstance(plugin, basestring):
|
||||||
|
raise ValueError(u'Parameter plugin is not of type string')
|
||||||
|
|
||||||
|
if plugin == u'|':
|
||||||
|
self.orgmenu + orgmode.menu.Separator()
|
||||||
|
self.orgmenu.children[-1].create()
|
||||||
|
return
|
||||||
|
|
||||||
|
if plugin in self._plugins:
|
||||||
|
raise PluginError(u'Plugin %s has already been loaded')
|
||||||
|
|
||||||
|
# a python module
|
||||||
|
module = None
|
||||||
|
|
||||||
|
# actual plugin class
|
||||||
|
_class = None
|
||||||
|
|
||||||
|
# locate module and initialize plugin class
|
||||||
|
try:
|
||||||
|
module = imp.find_module(plugin, orgmode.plugins.__path__)
|
||||||
|
except ImportError as e:
|
||||||
|
echom(u'Plugin not found: %s' % plugin)
|
||||||
|
if self.debug:
|
||||||
|
raise e
|
||||||
|
return
|
||||||
|
|
||||||
|
if not module:
|
||||||
|
echom(u'Plugin not found: %s' % plugin)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
module = imp.load_module(plugin, *module)
|
||||||
|
if not hasattr(module, plugin):
|
||||||
|
echoe(u'Unable to find plugin: %s' % plugin)
|
||||||
|
if self.debug:
|
||||||
|
raise PluginError(u'Unable to find class %s' % plugin)
|
||||||
|
return
|
||||||
|
_class = getattr(module, plugin)
|
||||||
|
self._plugins[plugin] = _class()
|
||||||
|
self._plugins[plugin].register()
|
||||||
|
if self.debug:
|
||||||
|
echo(u'Plugin registered: %s' % plugin)
|
||||||
|
return self._plugins[plugin]
|
||||||
|
except BaseException as e:
|
||||||
|
echoe(u'Unable to activate plugin: %s' % plugin)
|
||||||
|
echoe(u"%s" % e)
|
||||||
|
if self.debug:
|
||||||
|
import traceback
|
||||||
|
echoe(traceback.format_exc())
|
||||||
|
|
||||||
|
def register_keybindings(self):
|
||||||
|
@orgmode.keybinding.register_keybindings
|
||||||
|
def dummy(plugin):
|
||||||
|
return plugin
|
||||||
|
|
||||||
|
if sys.version_info < (3, ):
|
||||||
|
for p in self.plugins.itervalues():
|
||||||
|
dummy(p)
|
||||||
|
else:
|
||||||
|
for p in self.plugins.values():
|
||||||
|
dummy(p)
|
||||||
|
|
||||||
|
def register_menu(self):
|
||||||
|
self.orgmenu.create()
|
||||||
|
|
||||||
|
def unregister_menu(self):
|
||||||
|
vim.command(u_encode(u'silent! aunmenu Org'))
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
u""" Start orgmode and load all requested plugins
|
||||||
|
"""
|
||||||
|
plugins = orgmode.settings.get(u"org_plugins")
|
||||||
|
|
||||||
|
if not plugins:
|
||||||
|
echom(u'orgmode: No plugins registered.')
|
||||||
|
|
||||||
|
if isinstance(plugins, basestring):
|
||||||
|
try:
|
||||||
|
self.register_plugin(plugins)
|
||||||
|
except BaseException as e:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
elif isinstance(plugins, list) or \
|
||||||
|
isinstance(plugins, tuple):
|
||||||
|
for p in plugins:
|
||||||
|
try:
|
||||||
|
self.register_plugin(p)
|
||||||
|
except BaseException as e:
|
||||||
|
echoe('Error in %s plugin:' % p)
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
return plugins
|
||||||
|
|
||||||
|
|
||||||
|
ORGMODE = OrgMode()
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
230
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/Makefile
Normal file
230
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/Makefile
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
# Makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line.
|
||||||
|
SPHINXOPTS =
|
||||||
|
SPHINXBUILD = sphinx-build
|
||||||
|
PAPER =
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# User-friendly check for sphinx-build
|
||||||
|
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||||
|
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Internal variables.
|
||||||
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
# the i18n builder cannot share the environment and doctrees with the others
|
||||||
|
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help:
|
||||||
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " html to make standalone HTML files"
|
||||||
|
@echo " dirhtml to make HTML files named index.html in directories"
|
||||||
|
@echo " singlehtml to make a single large HTML file"
|
||||||
|
@echo " pickle to make pickle files"
|
||||||
|
@echo " json to make JSON files"
|
||||||
|
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||||
|
@echo " qthelp to make HTML files and a qthelp project"
|
||||||
|
@echo " applehelp to make an Apple Help Book"
|
||||||
|
@echo " devhelp to make HTML files and a Devhelp project"
|
||||||
|
@echo " epub to make an epub"
|
||||||
|
@echo " epub3 to make an epub3"
|
||||||
|
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||||
|
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||||
|
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||||
|
@echo " text to make text files"
|
||||||
|
@echo " man to make manual pages"
|
||||||
|
@echo " texinfo to make Texinfo files"
|
||||||
|
@echo " info to make Texinfo files and run them through makeinfo"
|
||||||
|
@echo " gettext to make PO message catalogs"
|
||||||
|
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||||
|
@echo " xml to make Docutils-native XML files"
|
||||||
|
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||||
|
@echo " linkcheck to check all external links for integrity"
|
||||||
|
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||||
|
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||||
|
@echo " dummy to check syntax errors of document sources"
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILDDIR)/*
|
||||||
|
|
||||||
|
.PHONY: html
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
|
|
||||||
|
.PHONY: dirhtml
|
||||||
|
dirhtml:
|
||||||
|
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||||
|
|
||||||
|
.PHONY: singlehtml
|
||||||
|
singlehtml:
|
||||||
|
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||||
|
|
||||||
|
.PHONY: pickle
|
||||||
|
pickle:
|
||||||
|
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the pickle files."
|
||||||
|
|
||||||
|
.PHONY: json
|
||||||
|
json:
|
||||||
|
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the JSON files."
|
||||||
|
|
||||||
|
.PHONY: htmlhelp
|
||||||
|
htmlhelp:
|
||||||
|
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||||
|
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||||
|
|
||||||
|
.PHONY: qthelp
|
||||||
|
qthelp:
|
||||||
|
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/orgmode.qhcp"
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/orgmode.qhc"
|
||||||
|
|
||||||
|
.PHONY: applehelp
|
||||||
|
applehelp:
|
||||||
|
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
||||||
|
@echo "N.B. You won't be able to view it unless you put it in" \
|
||||||
|
"~/Library/Documentation/Help or install it in your application" \
|
||||||
|
"bundle."
|
||||||
|
|
||||||
|
.PHONY: devhelp
|
||||||
|
devhelp:
|
||||||
|
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished."
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# mkdir -p $$HOME/.local/share/devhelp/orgmode"
|
||||||
|
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/orgmode"
|
||||||
|
@echo "# devhelp"
|
||||||
|
|
||||||
|
.PHONY: epub
|
||||||
|
epub:
|
||||||
|
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||||
|
|
||||||
|
.PHONY: epub3
|
||||||
|
epub3:
|
||||||
|
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
|
||||||
|
|
||||||
|
.PHONY: latex
|
||||||
|
latex:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||||
|
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||||
|
"(use \`make latexpdf' here to do that automatically)."
|
||||||
|
|
||||||
|
.PHONY: latexpdf
|
||||||
|
latexpdf:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
.PHONY: latexpdfja
|
||||||
|
latexpdfja:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||||
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
.PHONY: text
|
||||||
|
text:
|
||||||
|
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||||
|
|
||||||
|
.PHONY: man
|
||||||
|
man:
|
||||||
|
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||||
|
|
||||||
|
.PHONY: texinfo
|
||||||
|
texinfo:
|
||||||
|
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||||
|
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||||
|
"(use \`make info' here to do that automatically)."
|
||||||
|
|
||||||
|
.PHONY: info
|
||||||
|
info:
|
||||||
|
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||||
|
@echo "Running Texinfo files through makeinfo..."
|
||||||
|
make -C $(BUILDDIR)/texinfo info
|
||||||
|
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||||
|
|
||||||
|
.PHONY: gettext
|
||||||
|
gettext:
|
||||||
|
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||||
|
|
||||||
|
.PHONY: changes
|
||||||
|
changes:
|
||||||
|
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||||
|
@echo
|
||||||
|
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||||
|
|
||||||
|
.PHONY: linkcheck
|
||||||
|
linkcheck:
|
||||||
|
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||||
|
@echo
|
||||||
|
@echo "Link check complete; look for any errors in the above output " \
|
||||||
|
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||||
|
|
||||||
|
.PHONY: doctest
|
||||||
|
doctest:
|
||||||
|
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||||
|
@echo "Testing of doctests in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/doctest/output.txt."
|
||||||
|
|
||||||
|
.PHONY: coverage
|
||||||
|
coverage:
|
||||||
|
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||||
|
@echo "Testing of coverage in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/coverage/python.txt."
|
||||||
|
|
||||||
|
.PHONY: xml
|
||||||
|
xml:
|
||||||
|
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||||
|
|
||||||
|
.PHONY: pseudoxml
|
||||||
|
pseudoxml:
|
||||||
|
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||||
|
|
||||||
|
.PHONY: dummy
|
||||||
|
dummy:
|
||||||
|
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. Dummy builder generates no files."
|
387
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/conf.py
Normal file
387
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/conf.py
Normal file
|
@ -0,0 +1,387 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# orgmode documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Sat May 21 15:51:55 2016.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its
|
||||||
|
# containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import mock
|
||||||
|
|
||||||
|
# Mock vim
|
||||||
|
MOCK_MODULES = ['vim']
|
||||||
|
for m in MOCK_MODULES:
|
||||||
|
sys.modules[m] = mock.Mock()
|
||||||
|
|
||||||
|
import vim
|
||||||
|
vim.eval = mock.MagicMock(return_value=1)
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
sys.path.insert(0, os.path.abspath('../..'))
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.todo',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
'sphinx.ext.doctest',
|
||||||
|
'sphinx.ext.coverage',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
'sphinx.ext.napoleon',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Napoleon config
|
||||||
|
napoleon_google_docstring = True
|
||||||
|
napoleon_numpy_docstring = True
|
||||||
|
napoleon_include_private_with_doc = True
|
||||||
|
napoleon_include_special_with_doc = True
|
||||||
|
napoleon_use_admonition_for_examples = False
|
||||||
|
napoleon_use_admonition_for_notes = False
|
||||||
|
napoleon_use_admonition_for_references = False
|
||||||
|
napoleon_use_ivar = False
|
||||||
|
napoleon_use_param = True
|
||||||
|
napoleon_use_rtype = True
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
#templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix(es) of source filenames.
|
||||||
|
# You can specify multiple suffix as a list of string:
|
||||||
|
# source_suffix = ['.rst', '.md']
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = 'orgmode'
|
||||||
|
copyright = '2016, Author'
|
||||||
|
author = 'Author'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
version = ''
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = ''
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = 'en'
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This patterns also effect to html_static_path and html_extra_path
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
#keep_warnings = False
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
html_theme = 'alabaster'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
#html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents.
|
||||||
|
# "<project> v<release> documentation" by default.
|
||||||
|
html_title = 'orgmode v0.5'
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
#html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to use as a favicon of
|
||||||
|
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
#html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
# directly to the root of the documentation.
|
||||||
|
#html_extra_path = []
|
||||||
|
|
||||||
|
# If not None, a 'Last updated on:' timestamp is inserted at every page
|
||||||
|
# bottom, using the given strftime format.
|
||||||
|
# The empty string is equivalent to '%b %d, %Y'.
|
||||||
|
#html_last_updated_fmt = None
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Language to be used for generating the HTML full-text search index.
|
||||||
|
# Sphinx supports the following languages:
|
||||||
|
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
|
||||||
|
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh'
|
||||||
|
#html_search_language = 'en'
|
||||||
|
|
||||||
|
# A dictionary with options for the search language support, empty by default.
|
||||||
|
# 'ja' uses this config value.
|
||||||
|
# 'zh' user can custom change `jieba` dictionary path.
|
||||||
|
#html_search_options = {'type': 'default'}
|
||||||
|
|
||||||
|
# The name of a javascript file (relative to the configuration directory) that
|
||||||
|
# implements a search results scorer. If empty, the default will be used.
|
||||||
|
#html_search_scorer = 'scorer.js'
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'orgmodedoc'
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
#'papersize': 'letterpaper',
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#'pointsize': '10pt',
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#'preamble': '',
|
||||||
|
|
||||||
|
# Latex figure (float) alignment
|
||||||
|
#'figure_align': 'htbp',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title,
|
||||||
|
# author, documentclass [howto, manual, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
(master_doc, 'orgmode.tex', 'orgmode Documentation',
|
||||||
|
'Author', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
#latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
#latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#latex_show_urls = False
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
(master_doc, 'orgmode', 'orgmode Documentation',
|
||||||
|
[author], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
(master_doc, 'orgmode', 'orgmode Documentation',
|
||||||
|
author, 'orgmode', 'One line description of project.',
|
||||||
|
'Miscellaneous'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#texinfo_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#texinfo_domain_indices = True
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
#texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
|
#texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Epub output ----------------------------------------------
|
||||||
|
|
||||||
|
# Bibliographic Dublin Core info.
|
||||||
|
epub_title = project
|
||||||
|
epub_author = author
|
||||||
|
epub_publisher = author
|
||||||
|
epub_copyright = copyright
|
||||||
|
|
||||||
|
# The basename for the epub file. It defaults to the project name.
|
||||||
|
#epub_basename = project
|
||||||
|
|
||||||
|
# The HTML theme for the epub output. Since the default themes are not
|
||||||
|
# optimized for small screen space, using the same theme for HTML and epub
|
||||||
|
# output is usually not wise. This defaults to 'epub', a theme designed to save
|
||||||
|
# visual space.
|
||||||
|
#epub_theme = 'epub'
|
||||||
|
|
||||||
|
# The language of the text. It defaults to the language option
|
||||||
|
# or 'en' if the language is not set.
|
||||||
|
#epub_language = ''
|
||||||
|
|
||||||
|
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||||
|
#epub_scheme = ''
|
||||||
|
|
||||||
|
# The unique identifier of the text. This can be a ISBN number
|
||||||
|
# or the project homepage.
|
||||||
|
#epub_identifier = ''
|
||||||
|
|
||||||
|
# A unique identification for the text.
|
||||||
|
#epub_uid = ''
|
||||||
|
|
||||||
|
# A tuple containing the cover image and cover page html template filenames.
|
||||||
|
#epub_cover = ()
|
||||||
|
|
||||||
|
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
|
||||||
|
#epub_guide = ()
|
||||||
|
|
||||||
|
# HTML files that should be inserted before the pages created by sphinx.
|
||||||
|
# The format is a list of tuples containing the path and title.
|
||||||
|
#epub_pre_files = []
|
||||||
|
|
||||||
|
# HTML files that should be inserted after the pages created by sphinx.
|
||||||
|
# The format is a list of tuples containing the path and title.
|
||||||
|
#epub_post_files = []
|
||||||
|
|
||||||
|
# A list of files that should not be packed into the epub file.
|
||||||
|
epub_exclude_files = ['search.html']
|
||||||
|
|
||||||
|
# The depth of the table of contents in toc.ncx.
|
||||||
|
#epub_tocdepth = 3
|
||||||
|
|
||||||
|
# Allow duplicate toc entries.
|
||||||
|
#epub_tocdup = True
|
||||||
|
|
||||||
|
# Choose between 'default' and 'includehidden'.
|
||||||
|
#epub_tocscope = 'default'
|
||||||
|
|
||||||
|
# Fix unsupported image types using the Pillow.
|
||||||
|
#epub_fix_images = False
|
||||||
|
|
||||||
|
# Scale large images.
|
||||||
|
#epub_max_image_width = 0
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
#epub_show_urls = 'inline'
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#epub_use_index = True
|
22
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/index.rst
Normal file
22
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/index.rst
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
.. orgmode documentation master file, created by
|
||||||
|
sphinx-quickstart on Sat May 21 16:35:00 2016.
|
||||||
|
You can adapt this file completely to your liking, but it should at least
|
||||||
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
|
Welcome to orgmode's documentation!
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 4
|
||||||
|
|
||||||
|
orgmode
|
||||||
|
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
281
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/make.bat
Normal file
281
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/make.bat
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set BUILDDIR=_build
|
||||||
|
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||||
|
set I18NSPHINXOPTS=%SPHINXOPTS% .
|
||||||
|
if NOT "%PAPER%" == "" (
|
||||||
|
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||||
|
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
if "%1" == "help" (
|
||||||
|
:help
|
||||||
|
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||||
|
echo. html to make standalone HTML files
|
||||||
|
echo. dirhtml to make HTML files named index.html in directories
|
||||||
|
echo. singlehtml to make a single large HTML file
|
||||||
|
echo. pickle to make pickle files
|
||||||
|
echo. json to make JSON files
|
||||||
|
echo. htmlhelp to make HTML files and a HTML help project
|
||||||
|
echo. qthelp to make HTML files and a qthelp project
|
||||||
|
echo. devhelp to make HTML files and a Devhelp project
|
||||||
|
echo. epub to make an epub
|
||||||
|
echo. epub3 to make an epub3
|
||||||
|
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||||
|
echo. text to make text files
|
||||||
|
echo. man to make manual pages
|
||||||
|
echo. texinfo to make Texinfo files
|
||||||
|
echo. gettext to make PO message catalogs
|
||||||
|
echo. changes to make an overview over all changed/added/deprecated items
|
||||||
|
echo. xml to make Docutils-native XML files
|
||||||
|
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||||
|
echo. linkcheck to check all external links for integrity
|
||||||
|
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||||
|
echo. coverage to run coverage check of the documentation if enabled
|
||||||
|
echo. dummy to check syntax errors of document sources
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "clean" (
|
||||||
|
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||||
|
del /q /s %BUILDDIR%\*
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
REM Check if sphinx-build is available and fallback to Python version if any
|
||||||
|
%SPHINXBUILD% 1>NUL 2>NUL
|
||||||
|
if errorlevel 9009 goto sphinx_python
|
||||||
|
goto sphinx_ok
|
||||||
|
|
||||||
|
:sphinx_python
|
||||||
|
|
||||||
|
set SPHINXBUILD=python -m sphinx.__init__
|
||||||
|
%SPHINXBUILD% 2> nul
|
||||||
|
if errorlevel 9009 (
|
||||||
|
echo.
|
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||||
|
echo.may add the Sphinx directory to PATH.
|
||||||
|
echo.
|
||||||
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
|
echo.http://sphinx-doc.org/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
:sphinx_ok
|
||||||
|
|
||||||
|
|
||||||
|
if "%1" == "html" (
|
||||||
|
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "dirhtml" (
|
||||||
|
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "singlehtml" (
|
||||||
|
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "pickle" (
|
||||||
|
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can process the pickle files.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "json" (
|
||||||
|
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can process the JSON files.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "htmlhelp" (
|
||||||
|
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||||
|
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "qthelp" (
|
||||||
|
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||||
|
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||||
|
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\orgmode.qhcp
|
||||||
|
echo.To view the help file:
|
||||||
|
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\orgmode.ghc
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "devhelp" (
|
||||||
|
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "epub" (
|
||||||
|
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "epub3" (
|
||||||
|
%SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "latex" (
|
||||||
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "latexpdf" (
|
||||||
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
|
cd %BUILDDIR%/latex
|
||||||
|
make all-pdf
|
||||||
|
cd %~dp0
|
||||||
|
echo.
|
||||||
|
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "latexpdfja" (
|
||||||
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
|
cd %BUILDDIR%/latex
|
||||||
|
make all-pdf-ja
|
||||||
|
cd %~dp0
|
||||||
|
echo.
|
||||||
|
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "text" (
|
||||||
|
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "man" (
|
||||||
|
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "texinfo" (
|
||||||
|
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "gettext" (
|
||||||
|
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "changes" (
|
||||||
|
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.The overview file is in %BUILDDIR%/changes.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "linkcheck" (
|
||||||
|
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Link check complete; look for any errors in the above output ^
|
||||||
|
or in %BUILDDIR%/linkcheck/output.txt.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "doctest" (
|
||||||
|
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Testing of doctests in the sources finished, look at the ^
|
||||||
|
results in %BUILDDIR%/doctest/output.txt.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "coverage" (
|
||||||
|
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Testing of coverage in the sources finished, look at the ^
|
||||||
|
results in %BUILDDIR%/coverage/python.txt.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "xml" (
|
||||||
|
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "pseudoxml" (
|
||||||
|
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "dummy" (
|
||||||
|
%SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. Dummy builder generates no files.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
:end
|
|
@ -0,0 +1,78 @@
|
||||||
|
orgmode.liborgmode package
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Submodules
|
||||||
|
----------
|
||||||
|
|
||||||
|
orgmode.liborgmode.agenda module
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.agenda
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.liborgmode.agendafilter module
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.agendafilter
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.liborgmode.base module
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.base
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.liborgmode.checkboxes module
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.checkboxes
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.liborgmode.documents module
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.documents
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.liborgmode.dom_obj module
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.dom_obj
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.liborgmode.headings module
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.headings
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.liborgmode.orgdate module
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode.orgdate
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
Module contents
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.liborgmode
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
|
@ -0,0 +1,110 @@
|
||||||
|
orgmode.plugins package
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Submodules
|
||||||
|
----------
|
||||||
|
|
||||||
|
orgmode.plugins.Agenda module
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.Agenda
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.Date module
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.Date
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.EditCheckbox module
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.EditCheckbox
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.EditStructure module
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.EditStructure
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.Export module
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.Export
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.Hyperlinks module
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.Hyperlinks
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.LoggingWork module
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.LoggingWork
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.Misc module
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.Misc
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.Navigator module
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.Navigator
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.ShowHide module
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.ShowHide
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.TagsProperties module
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.TagsProperties
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.plugins.Todo module
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins.Todo
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
Module contents
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.plugins
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
|
@ -0,0 +1,46 @@
|
||||||
|
orgmode.py3compat package
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Submodules
|
||||||
|
----------
|
||||||
|
|
||||||
|
orgmode.py3compat.encode_compatibility module
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.py3compat.encode_compatibility
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.py3compat.py_py3_string module
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.py3compat.py_py3_string
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.py3compat.unicode_compatibility module
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.py3compat.unicode_compatibility
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.py3compat.xrange_compatibility module
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.py3compat.xrange_compatibility
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
Module contents
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.py3compat
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
71
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/orgmode.rst
Normal file
71
pack/acp/start/vim-orgmode/ftplugin/orgmode/docs/orgmode.rst
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
orgmode package
|
||||||
|
===============
|
||||||
|
|
||||||
|
Subpackages
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
orgmode.liborgmode
|
||||||
|
orgmode.plugins
|
||||||
|
orgmode.py3compat
|
||||||
|
|
||||||
|
Submodules
|
||||||
|
----------
|
||||||
|
|
||||||
|
orgmode._vim module
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode._vim
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.exceptions module
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.exceptions
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.keybinding module
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.keybinding
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.menu module
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.menu
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.settings module
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.settings
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
orgmode.vimbuffer module
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode.vimbuffer
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
Module contents
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: orgmode
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
23
pack/acp/start/vim-orgmode/ftplugin/orgmode/exceptions.py
Normal file
23
pack/acp/start/vim-orgmode/ftplugin/orgmode/exceptions.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
class PluginError(BaseException):
|
||||||
|
def __init__(self, message):
|
||||||
|
BaseException.__init__(self, message)
|
||||||
|
|
||||||
|
|
||||||
|
class BufferNotFound(BaseException):
|
||||||
|
def __init__(self, message):
|
||||||
|
BaseException.__init__(self, message)
|
||||||
|
|
||||||
|
|
||||||
|
class BufferNotInSync(BaseException):
|
||||||
|
def __init__(self, message):
|
||||||
|
BaseException.__init__(self, message)
|
||||||
|
|
||||||
|
|
||||||
|
class HeadingDomError(BaseException):
|
||||||
|
def __init__(self, message):
|
||||||
|
BaseException.__init__(self, message)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
217
pack/acp/start/vim-orgmode/ftplugin/orgmode/keybinding.py
Normal file
217
pack/acp/start/vim-orgmode/ftplugin/orgmode/keybinding.py
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
MODE_ALL = u'a'
|
||||||
|
MODE_NORMAL = u'n'
|
||||||
|
MODE_VISUAL = u'v'
|
||||||
|
MODE_INSERT = u'i'
|
||||||
|
MODE_OPERATOR = u'o'
|
||||||
|
|
||||||
|
OPTION_BUFFER_ONLY = u'<buffer>'
|
||||||
|
OPTION_SLIENT = u'<silent>'
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
def _register(f, name):
|
||||||
|
def r(*args, **kwargs):
|
||||||
|
p = f(*args, **kwargs)
|
||||||
|
if hasattr(p, name) and isinstance(getattr(p, name), list):
|
||||||
|
for i in getattr(p, name):
|
||||||
|
i.create()
|
||||||
|
return p
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def register_keybindings(f):
|
||||||
|
return _register(f, u'keybindings')
|
||||||
|
|
||||||
|
|
||||||
|
def register_commands(f):
|
||||||
|
return _register(f, u'commands')
|
||||||
|
|
||||||
|
|
||||||
|
class Command(object):
|
||||||
|
u""" A vim command """
|
||||||
|
|
||||||
|
def __init__(self, name, command, arguments=u'0', complete=None, overwrite_exisiting=False):
|
||||||
|
u"""
|
||||||
|
:name: The name of command, first character must be uppercase
|
||||||
|
:command: The actual command that is executed
|
||||||
|
:arguments: See :h :command-nargs, only the arguments need to be specified
|
||||||
|
:complete: See :h :command-completion, only the completion arguments need to be specified
|
||||||
|
"""
|
||||||
|
object.__init__(self)
|
||||||
|
|
||||||
|
self._name = name
|
||||||
|
self._command = command
|
||||||
|
self._arguments = arguments
|
||||||
|
self._complete = complete
|
||||||
|
self._overwrite_exisiting = overwrite_exisiting
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u':%s<CR>' % self.name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def command(self):
|
||||||
|
return self._command
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arguments(self):
|
||||||
|
return self._arguments
|
||||||
|
|
||||||
|
@property
|
||||||
|
def complete(self):
|
||||||
|
return self._complete
|
||||||
|
|
||||||
|
@property
|
||||||
|
def overwrite_exisiting(self):
|
||||||
|
return self._overwrite_exisiting
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
u""" Register/create the command
|
||||||
|
"""
|
||||||
|
vim.command(u_encode(':command%(overwrite)s -nargs=%(arguments)s %(complete)s %(name)s %(command)s' %
|
||||||
|
{u'overwrite': '!' if self.overwrite_exisiting else '',
|
||||||
|
u'arguments': u_encode(self.arguments),
|
||||||
|
u'complete': '-complete=%s' % u_encode(self.complete) if self.complete else '',
|
||||||
|
u'name': self.name,
|
||||||
|
u'command': self.command}
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
class Plug(object):
|
||||||
|
u""" Represents a <Plug> to an abitrary command """
|
||||||
|
|
||||||
|
def __init__(self, name, command, mode=MODE_NORMAL):
|
||||||
|
u"""
|
||||||
|
:name: the name of the <Plug> should be ScriptnameCommandname
|
||||||
|
:command: the actual command
|
||||||
|
"""
|
||||||
|
object.__init__(self)
|
||||||
|
|
||||||
|
if mode not in (MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR):
|
||||||
|
raise ValueError(u'Parameter mode not in MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR')
|
||||||
|
self._mode = mode
|
||||||
|
|
||||||
|
self.name = name
|
||||||
|
self.command = command
|
||||||
|
self.created = False
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u'<Plug>%s' % self.name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
if not self.created:
|
||||||
|
self.created = True
|
||||||
|
cmd = self._mode
|
||||||
|
if cmd == MODE_ALL:
|
||||||
|
cmd = u''
|
||||||
|
vim.command(u_encode(u':%snoremap %s %s' % (cmd, str(self), self.command)))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode(self):
|
||||||
|
return self._mode
|
||||||
|
|
||||||
|
|
||||||
|
class Keybinding(object):
|
||||||
|
u""" Representation of a single key binding """
|
||||||
|
|
||||||
|
def __init__(self, key, action, mode=None, options=None, remap=True, buffer_only=True, silent=True):
|
||||||
|
u"""
|
||||||
|
:key: the key(s) action is bound to
|
||||||
|
:action: the action triggered by key(s)
|
||||||
|
:mode: definition in which vim modes the key binding is valid. Should be one of MODE_*
|
||||||
|
:option: list of other options like <silent>, <buffer> ...
|
||||||
|
:repmap: allow or disallow nested mapping
|
||||||
|
:buffer_only: define the key binding only for the current buffer
|
||||||
|
"""
|
||||||
|
object.__init__(self)
|
||||||
|
self._key = key
|
||||||
|
self._action = action
|
||||||
|
|
||||||
|
# grab mode from plug if not set otherwise
|
||||||
|
if isinstance(self._action, Plug) and not mode:
|
||||||
|
mode = self._action.mode
|
||||||
|
|
||||||
|
if mode not in (MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR):
|
||||||
|
raise ValueError(u'Parameter mode not in MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR')
|
||||||
|
self._mode = mode
|
||||||
|
self._options = options
|
||||||
|
if self._options is None:
|
||||||
|
self._options = []
|
||||||
|
self._remap = remap
|
||||||
|
self._buffer_only = buffer_only
|
||||||
|
self._silent = silent
|
||||||
|
|
||||||
|
if self._buffer_only and OPTION_BUFFER_ONLY not in self._options:
|
||||||
|
self._options.append(OPTION_BUFFER_ONLY)
|
||||||
|
|
||||||
|
if self._silent and OPTION_SLIENT not in self._options:
|
||||||
|
self._options.append(OPTION_SLIENT)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self):
|
||||||
|
return self._key
|
||||||
|
|
||||||
|
@property
|
||||||
|
def action(self):
|
||||||
|
return str(self._action)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode(self):
|
||||||
|
return self._mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def options(self):
|
||||||
|
return self._options[:]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def remap(self):
|
||||||
|
return self._remap
|
||||||
|
|
||||||
|
@property
|
||||||
|
def buffer_only(self):
|
||||||
|
return self._buffer_only
|
||||||
|
|
||||||
|
@property
|
||||||
|
def silent(self):
|
||||||
|
return self._silent
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
from orgmode._vim import ORGMODE, echom
|
||||||
|
|
||||||
|
cmd = self._mode
|
||||||
|
if cmd == MODE_ALL:
|
||||||
|
cmd = u''
|
||||||
|
if not self._remap:
|
||||||
|
cmd += u'nore'
|
||||||
|
try:
|
||||||
|
create_mapping = True
|
||||||
|
if isinstance(self._action, Plug):
|
||||||
|
# create plug
|
||||||
|
self._action.create()
|
||||||
|
if int(vim.eval(u_encode(u'hasmapto("%s")' % (self._action, )))):
|
||||||
|
create_mapping = False
|
||||||
|
if isinstance(self._action, Command):
|
||||||
|
# create command
|
||||||
|
self._action.create()
|
||||||
|
|
||||||
|
if create_mapping:
|
||||||
|
vim.command(u_encode(u':%smap %s %s %s' % (cmd, u' '.join(self._options), self._key, self._action)))
|
||||||
|
except BaseException as e:
|
||||||
|
if ORGMODE.debug:
|
||||||
|
echom(u'Failed to register key binding %s %s' % (self._key, self._action))
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
|
@ -0,0 +1,63 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
u"""
|
||||||
|
Agenda
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The agenda is one of the main concepts of orgmode. It allows to
|
||||||
|
collect TODO items from multiple org documents in an agenda view.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* filtering
|
||||||
|
* sorting
|
||||||
|
"""
|
||||||
|
|
||||||
|
from orgmode.liborgmode.agendafilter import filter_items
|
||||||
|
from orgmode.liborgmode.agendafilter import is_within_week_and_active_todo
|
||||||
|
from orgmode.liborgmode.agendafilter import contains_active_todo
|
||||||
|
from orgmode.liborgmode.agendafilter import contains_active_date
|
||||||
|
|
||||||
|
|
||||||
|
class AgendaManager(object):
|
||||||
|
u"""Simple parsing of Documents to create an agenda."""
|
||||||
|
# TODO Move filters in this file, they do the same thing
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(AgendaManager, self).__init__()
|
||||||
|
|
||||||
|
def get_todo(self, documents):
|
||||||
|
u"""
|
||||||
|
Get the todo agenda for the given documents (list of document).
|
||||||
|
"""
|
||||||
|
filtered = []
|
||||||
|
for document in iter(documents):
|
||||||
|
# filter and return headings
|
||||||
|
filtered.extend(filter_items(document.all_headings(),
|
||||||
|
[contains_active_todo]))
|
||||||
|
return sorted(filtered)
|
||||||
|
|
||||||
|
def get_next_week_and_active_todo(self, documents):
|
||||||
|
u"""
|
||||||
|
Get the agenda for next week for the given documents (list of
|
||||||
|
document).
|
||||||
|
"""
|
||||||
|
filtered = []
|
||||||
|
for document in iter(documents):
|
||||||
|
# filter and return headings
|
||||||
|
filtered.extend(filter_items(document.all_headings(),
|
||||||
|
[is_within_week_and_active_todo]))
|
||||||
|
return sorted(filtered)
|
||||||
|
|
||||||
|
def get_timestamped_items(self, documents):
|
||||||
|
u"""
|
||||||
|
Get all time-stamped items in a time-sorted way for the given
|
||||||
|
documents (list of document).
|
||||||
|
"""
|
||||||
|
filtered = []
|
||||||
|
for document in iter(documents):
|
||||||
|
# filter and return headings
|
||||||
|
filtered.extend(filter_items(document.all_headings(),
|
||||||
|
[contains_active_date]))
|
||||||
|
return sorted(filtered)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,93 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
u"""
|
||||||
|
agendafilter
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
AgendaFilter contains all the filters that can be applied to create the
|
||||||
|
agenda.
|
||||||
|
|
||||||
|
|
||||||
|
All functions except filter_items() in the module are filters. Given a
|
||||||
|
heading they return if the heading meets the critera of the filter.
|
||||||
|
|
||||||
|
The function filter_items() can combine different filters and only returns
|
||||||
|
the filtered headings.
|
||||||
|
"""
|
||||||
|
from datetime import datetime
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
try:
|
||||||
|
from itertools import ifilter as filter
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def filter_items(headings, filters):
|
||||||
|
u""" Filter the given headings.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
headings (list): Contains headings
|
||||||
|
filters (list): Filters that will be applied. All functions in
|
||||||
|
this module (except this function) are filters.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
filter iterator: Headings which were not filtered.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> filtered = filter_items(headings, [contains_active_date,
|
||||||
|
contains_active_todo])
|
||||||
|
"""
|
||||||
|
filtered = headings
|
||||||
|
for f in filters:
|
||||||
|
filtered = filter(f, filtered)
|
||||||
|
return filtered
|
||||||
|
|
||||||
|
|
||||||
|
def is_within_week(heading):
|
||||||
|
u""" Test if headings date is withing a week
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the date in the deading is within a week in the future (or
|
||||||
|
older False otherwise.
|
||||||
|
"""
|
||||||
|
if contains_active_date(heading):
|
||||||
|
next_week = datetime.today() + timedelta(days=7)
|
||||||
|
if heading.active_date < next_week:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def is_within_week_and_active_todo(heading):
|
||||||
|
u"""
|
||||||
|
Returns:
|
||||||
|
bool: True if heading contains an active TODO and the date is within a
|
||||||
|
week.
|
||||||
|
"""
|
||||||
|
return is_within_week(heading) and contains_active_todo(heading)
|
||||||
|
|
||||||
|
|
||||||
|
def contains_active_todo(heading):
|
||||||
|
u"""
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if heading contains an active TODO.
|
||||||
|
"""
|
||||||
|
# TODO make this more efficient by checking some val and not calling the
|
||||||
|
# function
|
||||||
|
# TODO why is this import failing at top level? circular dependecy...
|
||||||
|
from orgmode._vim import ORGMODE
|
||||||
|
active = []
|
||||||
|
for act in ORGMODE.get_document().get_todo_states():
|
||||||
|
active.extend(act[0])
|
||||||
|
return heading.todo in active
|
||||||
|
|
||||||
|
|
||||||
|
def contains_active_date(heading):
|
||||||
|
u"""
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if heading contains an active date.
|
||||||
|
"""
|
||||||
|
return not(heading.active_date is None)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
190
pack/acp/start/vim-orgmode/ftplugin/orgmode/liborgmode/base.py
Normal file
190
pack/acp/start/vim-orgmode/ftplugin/orgmode/liborgmode/base.py
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
base
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Here are some really basic data structures that are used throughout
|
||||||
|
the liborgmode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from collections import UserList
|
||||||
|
except:
|
||||||
|
from UserList import UserList
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import sys
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
|
||||||
|
def flatten_list(lst):
|
||||||
|
""" Flattens a list
|
||||||
|
|
||||||
|
Args:
|
||||||
|
lst (iterable): An iterable that will is non-flat
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: Flat list
|
||||||
|
"""
|
||||||
|
# TODO write tests
|
||||||
|
def gen_lst(item):
|
||||||
|
if isinstance(item, basestring) or isinstance(item, bytes):
|
||||||
|
yield item
|
||||||
|
elif isinstance(item, collections.Iterable):
|
||||||
|
# yield from would be so nice... but c'est la vie
|
||||||
|
for val in item:
|
||||||
|
for final in gen_lst(val):
|
||||||
|
yield final
|
||||||
|
else:
|
||||||
|
yield item
|
||||||
|
return [i for i in gen_lst(lst)]
|
||||||
|
|
||||||
|
|
||||||
|
class Direction():
|
||||||
|
u"""
|
||||||
|
Direction is used to indicate the direction of certain actions.
|
||||||
|
|
||||||
|
Example: it defines the direction headings get parted in.
|
||||||
|
"""
|
||||||
|
FORWARD = 1
|
||||||
|
BACKWARD = 2
|
||||||
|
|
||||||
|
|
||||||
|
class MultiPurposeList(UserList):
|
||||||
|
u"""
|
||||||
|
A Multi Purpose List is a list that calls a user defined hook on
|
||||||
|
change. The implementation is very basic - the hook is called without any
|
||||||
|
parameters. Otherwise the Multi Purpose List can be used like any other
|
||||||
|
list.
|
||||||
|
|
||||||
|
The member element "data" can be used to fill the list without causing the
|
||||||
|
list to be marked dirty. This should only be used during initialization!
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, initlist=None, on_change=None):
|
||||||
|
UserList.__init__(self, initlist)
|
||||||
|
self._on_change = on_change
|
||||||
|
|
||||||
|
def _changed(self):
|
||||||
|
u""" Call hook """
|
||||||
|
if callable(self._on_change):
|
||||||
|
self._on_change()
|
||||||
|
|
||||||
|
def __setitem__(self, i, item):
|
||||||
|
if sys.version_info < (3, ) and isinstance(i, slice):
|
||||||
|
start, stop, _ = i.indices(len(self))
|
||||||
|
UserList.__setslice__(self, start, stop, item)
|
||||||
|
else:
|
||||||
|
UserList.__setitem__(self, i, item)
|
||||||
|
self._changed()
|
||||||
|
|
||||||
|
def __delitem__(self, i):
|
||||||
|
if sys.version_info < (3, ) and isinstance(i, slice):
|
||||||
|
start, stop, _ = i.indices(len(self))
|
||||||
|
UserList.__delslice__(self, start, stop)
|
||||||
|
else:
|
||||||
|
UserList.__delitem__(self, i)
|
||||||
|
self._changed()
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
if sys.version_info < (3, ):
|
||||||
|
if isinstance(i, slice):
|
||||||
|
# TODO Return just a list. Why?
|
||||||
|
return [self[i] for i in range(*i.indices(len(self)))]
|
||||||
|
# return UserList([self[i] for i in range(*i.indices(len(self)))])
|
||||||
|
return UserList.__getitem__(self, i)
|
||||||
|
|
||||||
|
# NOTE: These wrappers are necessary because of python 2
|
||||||
|
def __setslice__(self, i, j, other):
|
||||||
|
self.__setitem__(slice(i, j), other)
|
||||||
|
|
||||||
|
def __delslice__(self, i, j):
|
||||||
|
self.__delitem__(slice(i, j))
|
||||||
|
|
||||||
|
def __getslice__(self, i, j):
|
||||||
|
return self.__getitem__(slice(i, j))
|
||||||
|
|
||||||
|
def __iadd__(self, other):
|
||||||
|
res = UserList.__iadd__(self, other)
|
||||||
|
self._changed()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def __imul__(self, n):
|
||||||
|
res = UserList.__imul__(self, n)
|
||||||
|
self._changed()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def append(self, item):
|
||||||
|
UserList.append(self, item)
|
||||||
|
self._changed()
|
||||||
|
|
||||||
|
def insert(self, i, item):
|
||||||
|
UserList.insert(self, i, item)
|
||||||
|
self._changed()
|
||||||
|
|
||||||
|
def pop(self, i=-1):
|
||||||
|
item = self[i]
|
||||||
|
del self[i]
|
||||||
|
return item
|
||||||
|
|
||||||
|
def remove(self, item):
|
||||||
|
self.__delitem__(self.index(item))
|
||||||
|
|
||||||
|
def reverse(self):
|
||||||
|
UserList.reverse(self)
|
||||||
|
self._changed()
|
||||||
|
|
||||||
|
def sort(self, *args, **kwds):
|
||||||
|
UserList.sort(self, *args, **kwds)
|
||||||
|
self._changed()
|
||||||
|
|
||||||
|
def extend(self, other):
|
||||||
|
UserList.extend(self, other)
|
||||||
|
self._changed()
|
||||||
|
|
||||||
|
|
||||||
|
def get_domobj_range(content=[], position=0, direction=Direction.FORWARD, identify_fun=None):
|
||||||
|
u"""
|
||||||
|
Get the start and end line number of the dom obj lines from content.
|
||||||
|
|
||||||
|
:content: String to be recognized dom obj
|
||||||
|
:positon: Line number in content
|
||||||
|
:direction: Search direction
|
||||||
|
:identify_fun: A identify function to recognize dom obj(Heading, Checkbox) title string.
|
||||||
|
|
||||||
|
:return: Start and end line number for the recognized dom obj.
|
||||||
|
"""
|
||||||
|
len_cb = len(content)
|
||||||
|
|
||||||
|
if position < 0 or position > len_cb:
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
tmp_line = position
|
||||||
|
start = None
|
||||||
|
end = None
|
||||||
|
|
||||||
|
if direction == Direction.FORWARD:
|
||||||
|
while tmp_line < len_cb:
|
||||||
|
if identify_fun(content[tmp_line]) is not None:
|
||||||
|
if start is None:
|
||||||
|
start = tmp_line
|
||||||
|
elif end is None:
|
||||||
|
end = tmp_line - 1
|
||||||
|
if start is not None and end is not None:
|
||||||
|
break
|
||||||
|
tmp_line += 1
|
||||||
|
else:
|
||||||
|
while tmp_line >= 0 and tmp_line < len_cb:
|
||||||
|
if identify_fun(content[tmp_line]) is not None:
|
||||||
|
if start is None:
|
||||||
|
start = tmp_line
|
||||||
|
elif end is None:
|
||||||
|
end = tmp_line - 1
|
||||||
|
if start is not None and end is not None:
|
||||||
|
break
|
||||||
|
tmp_line -= 1 if start is None else -1
|
||||||
|
|
||||||
|
return (start, end)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,406 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
checkboxes
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
TODO: explain this :)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
try:
|
||||||
|
from collections import UserList
|
||||||
|
except:
|
||||||
|
from UserList import UserList
|
||||||
|
|
||||||
|
import vim
|
||||||
|
from orgmode.liborgmode.base import MultiPurposeList, flatten_list
|
||||||
|
from orgmode.liborgmode.orgdate import OrgTimeRange
|
||||||
|
from orgmode.liborgmode.orgdate import get_orgdate
|
||||||
|
from orgmode.liborgmode.dom_obj import DomObj, DomObjList, REGEX_SUBTASK, REGEX_SUBTASK_PERCENT, REGEX_HEADING, REGEX_CHECKBOX
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
|
||||||
|
class Checkbox(DomObj):
|
||||||
|
u""" Structural checkbox object """
|
||||||
|
STATUS_ON = u'[X]'
|
||||||
|
STATUS_OFF = u'[ ]'
|
||||||
|
# intermediate status
|
||||||
|
STATUS_INT = u'[-]'
|
||||||
|
|
||||||
|
def __init__(self, level=1, type=u'-', title=u'', status=u'[ ]', body=None):
|
||||||
|
u"""
|
||||||
|
:level: Indent level of the checkbox
|
||||||
|
:type: Type of the checkbox list (-, +, *)
|
||||||
|
:title: Title of the checkbox
|
||||||
|
:status: Status of the checkbox ([ ], [X], [-])
|
||||||
|
:body: Body of the checkbox
|
||||||
|
"""
|
||||||
|
DomObj.__init__(self, level=level, title=title, body=body)
|
||||||
|
|
||||||
|
# heading
|
||||||
|
self._heading = None
|
||||||
|
|
||||||
|
self._children = CheckboxList(obj=self)
|
||||||
|
self._dirty_checkbox = False
|
||||||
|
# list type
|
||||||
|
self._type = u'-'
|
||||||
|
if type:
|
||||||
|
self.type = type
|
||||||
|
# status
|
||||||
|
self._status = Checkbox.STATUS_OFF
|
||||||
|
if status:
|
||||||
|
self.status = status
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u' ' * self.level + self.type + u' ' + \
|
||||||
|
(self.status + u' ' if self.status else u'') + self.title
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
# 1 is for the heading's title
|
||||||
|
return 1 + len(self.body)
|
||||||
|
|
||||||
|
def copy(self, including_children=True, parent=None):
|
||||||
|
u"""
|
||||||
|
Create a copy of the current checkbox. The checkbox will be completely
|
||||||
|
detached and not even belong to a document anymore.
|
||||||
|
|
||||||
|
:including_children: If True a copy of all children is create as
|
||||||
|
well. If False the returned checkbox doesn't
|
||||||
|
have any children.
|
||||||
|
:parent: Don't use this parameter. It's set
|
||||||
|
automatically.
|
||||||
|
"""
|
||||||
|
checkbox = self.__class__(
|
||||||
|
level=self.level, title=self.title,
|
||||||
|
body=self.body[:])
|
||||||
|
if parent:
|
||||||
|
parent.children.append(checkbox)
|
||||||
|
if including_children and self.children:
|
||||||
|
for item in self.children:
|
||||||
|
item.copy(
|
||||||
|
including_children=including_children,
|
||||||
|
parent=checkbox)
|
||||||
|
checkbox._orig_start = self._orig_start
|
||||||
|
checkbox._orig_len = self._orig_len
|
||||||
|
|
||||||
|
checkbox._dirty_heading = self.is_dirty_checkbox
|
||||||
|
|
||||||
|
return checkbox
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse_checkbox_from_data(cls, data, heading=None, orig_start=None):
|
||||||
|
u""" Construct a new checkbox from the provided data
|
||||||
|
|
||||||
|
:data: List of lines
|
||||||
|
:heading: The heading object this checkbox belongs to
|
||||||
|
:orig_start: The original start of the heading in case it was read
|
||||||
|
from a document. If orig_start is provided, the
|
||||||
|
resulting heading will not be marked dirty.
|
||||||
|
|
||||||
|
:returns: The newly created checkbox
|
||||||
|
"""
|
||||||
|
def parse_title(heading_line):
|
||||||
|
# checkbox is not heading
|
||||||
|
if REGEX_HEADING.match(heading_line) is not None:
|
||||||
|
return None
|
||||||
|
m = REGEX_CHECKBOX.match(heading_line)
|
||||||
|
if m:
|
||||||
|
r = m.groupdict()
|
||||||
|
return (len(r[u'level']), r[u'type'], r[u'status'], r[u'title'])
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
raise ValueError(u'Unable to create checkbox, no data provided.')
|
||||||
|
|
||||||
|
# create new checkbox
|
||||||
|
nc = cls()
|
||||||
|
nc.level, nc.type, nc.status, nc.title = parse_title(data[0])
|
||||||
|
nc.body = data[1:]
|
||||||
|
if orig_start is not None:
|
||||||
|
nc._dirty_heading = False
|
||||||
|
nc._dirty_body = False
|
||||||
|
nc._orig_start = orig_start
|
||||||
|
nc._orig_len = len(nc)
|
||||||
|
if heading:
|
||||||
|
nc._heading = heading
|
||||||
|
|
||||||
|
return nc
|
||||||
|
|
||||||
|
def update_subtasks(self, total=0, on=0):
|
||||||
|
if total != 0:
|
||||||
|
percent = (on * 100) / total
|
||||||
|
else:
|
||||||
|
percent = 0
|
||||||
|
|
||||||
|
count = "%d/%d" % (on, total)
|
||||||
|
self.title = REGEX_SUBTASK.sub("[%s]" % (count), self.title)
|
||||||
|
self.title = REGEX_SUBTASK_PERCENT.sub("[%d%%]" % (percent), self.title)
|
||||||
|
d = self._heading.document.write_checkbox(self, including_children=False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def identify_checkbox(cls, line):
|
||||||
|
u""" Test if a certain line is a checkbox or not.
|
||||||
|
|
||||||
|
:line: the line to check
|
||||||
|
|
||||||
|
:returns: indent_level
|
||||||
|
"""
|
||||||
|
# checkbox is not heading
|
||||||
|
if REGEX_HEADING.match(line) is not None:
|
||||||
|
return None
|
||||||
|
m = REGEX_CHECKBOX.match(line)
|
||||||
|
if m:
|
||||||
|
r = m.groupdict()
|
||||||
|
return len(r[u'level'])
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty(self):
|
||||||
|
u""" Return True if the heading's body is marked dirty """
|
||||||
|
return self._dirty_checkbox or self._dirty_body
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty_checkbox(self):
|
||||||
|
u""" Return True if the heading is marked dirty """
|
||||||
|
return self._dirty_checkbox
|
||||||
|
|
||||||
|
def get_index_in_parent_list(self):
|
||||||
|
""" Retrieve the index value of current checkbox in the parents list of
|
||||||
|
checkboxes. This works also for top level checkboxes.
|
||||||
|
|
||||||
|
:returns: Index value or None if heading doesn't have a
|
||||||
|
parent/document or is not in the list of checkboxes
|
||||||
|
"""
|
||||||
|
if self.parent:
|
||||||
|
return super(Checkbox, self).get_index_in_parent_list()
|
||||||
|
elif self.document:
|
||||||
|
l = self.get_parent_list()
|
||||||
|
if l:
|
||||||
|
return l.index(self)
|
||||||
|
|
||||||
|
def get_parent_list(self):
|
||||||
|
""" Retrieve the parents' list of headings. This works also for top
|
||||||
|
level headings.
|
||||||
|
|
||||||
|
:returns: List of headings or None if heading doesn't have a
|
||||||
|
parent/document or is not in the list of headings
|
||||||
|
"""
|
||||||
|
if self.parent:
|
||||||
|
return super(Checkbox, self).get_parent_list()
|
||||||
|
elif self.document:
|
||||||
|
if self in self.document.checkboxes:
|
||||||
|
return self.document.checkboxes
|
||||||
|
|
||||||
|
def set_dirty(self):
|
||||||
|
u""" Mark the heading and body dirty so that it will be rewritten when
|
||||||
|
saving the document """
|
||||||
|
self._dirty_checkbox = True
|
||||||
|
self._dirty_body = True
|
||||||
|
if self._document:
|
||||||
|
self._document.set_dirty_document()
|
||||||
|
|
||||||
|
def set_dirty_checkbox(self):
|
||||||
|
u""" Mark the checkbox dirty so that it will be rewritten when saving the
|
||||||
|
document """
|
||||||
|
self._dirty_checkbox = True
|
||||||
|
if self._document:
|
||||||
|
self._document.set_dirty_document()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def previous_checkbox(self):
|
||||||
|
u""" Serialized access to the previous checkbox """
|
||||||
|
return super(Checkbox, self).previous_item
|
||||||
|
|
||||||
|
@property
|
||||||
|
def next_checkbox(self):
|
||||||
|
u""" Serialized access to the next checkbox """
|
||||||
|
return super(Checkbox, self).next_item
|
||||||
|
|
||||||
|
@property
|
||||||
|
def first_checkbox(self):
|
||||||
|
u""" Access to the first child heading or None if no children exist """
|
||||||
|
if self.children:
|
||||||
|
return self.children[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start(self):
|
||||||
|
u""" Access to the starting line of the checkbox """
|
||||||
|
return super(Checkbox, self).start
|
||||||
|
|
||||||
|
def toggle(self):
|
||||||
|
u""" Toggle status of this checkbox """
|
||||||
|
if self.status == Checkbox.STATUS_OFF or self.status is None:
|
||||||
|
self.status = Checkbox.STATUS_ON
|
||||||
|
else:
|
||||||
|
self.status = Checkbox.STATUS_OFF
|
||||||
|
self.set_dirty()
|
||||||
|
|
||||||
|
def all_siblings(self):
|
||||||
|
if not self.parent:
|
||||||
|
p = self._heading
|
||||||
|
else:
|
||||||
|
p = self.parent
|
||||||
|
if not p.children:
|
||||||
|
return
|
||||||
|
|
||||||
|
c = p.first_checkbox
|
||||||
|
while c:
|
||||||
|
yield c
|
||||||
|
c = c.next_sibling
|
||||||
|
return
|
||||||
|
|
||||||
|
def all_children(self):
|
||||||
|
if not self.children:
|
||||||
|
return
|
||||||
|
|
||||||
|
c = self.first_checkbox
|
||||||
|
while c:
|
||||||
|
yield c
|
||||||
|
for d in c.all_children():
|
||||||
|
yield d
|
||||||
|
c = c.next_sibling
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def all_children_status(self):
|
||||||
|
u""" Return checkboxes status for currnet checkbox's all children
|
||||||
|
|
||||||
|
:return: (total, on)
|
||||||
|
total: total # of checkboxes
|
||||||
|
on: # of checkboxes which are on
|
||||||
|
"""
|
||||||
|
total, on = 0, 0
|
||||||
|
for c in self.all_children():
|
||||||
|
if c.status is not None:
|
||||||
|
total += 1
|
||||||
|
|
||||||
|
if c.status == Checkbox.STATUS_ON:
|
||||||
|
on += 1
|
||||||
|
|
||||||
|
return (total, on)
|
||||||
|
|
||||||
|
def all_siblings_status(self):
|
||||||
|
u""" Return checkboxes status for currnet checkbox's all siblings
|
||||||
|
|
||||||
|
:return: (total, on)
|
||||||
|
total: total # of checkboxes
|
||||||
|
on: # of checkboxes which are on
|
||||||
|
"""
|
||||||
|
total, on = 0, 0
|
||||||
|
for c in self.all_siblings():
|
||||||
|
if c.status is not None:
|
||||||
|
total += 1
|
||||||
|
|
||||||
|
if c.status == Checkbox.STATUS_ON:
|
||||||
|
on += 1
|
||||||
|
|
||||||
|
return (total, on)
|
||||||
|
|
||||||
|
def are_children_all(self, status):
|
||||||
|
u""" Check all children checkboxes status """
|
||||||
|
clen = len(self.children)
|
||||||
|
for i in range(clen):
|
||||||
|
if self.children[i].status != status:
|
||||||
|
return False
|
||||||
|
# recursively check children's status
|
||||||
|
if not self.children[i].are_children_all(status):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_child_one(self, status):
|
||||||
|
u""" Return true, if there is one child with given status """
|
||||||
|
clen = len(self.children)
|
||||||
|
for i in range(clen):
|
||||||
|
if self.children[i].status == status:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def are_siblings_all(self, status):
|
||||||
|
u""" Check all sibling checkboxes status """
|
||||||
|
for c in self.all_siblings():
|
||||||
|
if c.status != status:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@DomObj.level.setter
|
||||||
|
def level(self, value):
|
||||||
|
u""" Set the checkbox level and mark the checkbox and the document
|
||||||
|
dirty """
|
||||||
|
self._level = int(value)
|
||||||
|
self.set_dirty_checkbox()
|
||||||
|
|
||||||
|
@DomObj.title.setter
|
||||||
|
def title(self, value):
|
||||||
|
u""" Set the title and mark the document and the checkbox dirty """
|
||||||
|
if type(value) not in (unicode, str):
|
||||||
|
raise ValueError(u'Title must be a string.')
|
||||||
|
v = value
|
||||||
|
if type(v) == str:
|
||||||
|
v = u_decode(v)
|
||||||
|
self._title = v.strip()
|
||||||
|
self.set_dirty_checkbox()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
u""" status of current checkbox """
|
||||||
|
return self._status
|
||||||
|
|
||||||
|
@status.setter
|
||||||
|
def status(self, value):
|
||||||
|
self._status = value
|
||||||
|
self.set_dirty()
|
||||||
|
|
||||||
|
@status.deleter
|
||||||
|
def status(self):
|
||||||
|
self._status = u''
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
u""" type of current checkbox list type """
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
@type.setter
|
||||||
|
def type(self, value):
|
||||||
|
self._type = value
|
||||||
|
|
||||||
|
@type.deleter
|
||||||
|
def type(self):
|
||||||
|
self._type = u''
|
||||||
|
|
||||||
|
|
||||||
|
class CheckboxList(DomObjList):
|
||||||
|
u"""
|
||||||
|
Checkbox List
|
||||||
|
"""
|
||||||
|
def __init__(self, initlist=None, obj=None):
|
||||||
|
"""
|
||||||
|
:initlist: Initial data
|
||||||
|
:obj: Link to a concrete Checkbox or Document object
|
||||||
|
"""
|
||||||
|
# it's not necessary to register a on_change hook because the heading
|
||||||
|
# list will itself take care of marking headings dirty or adding
|
||||||
|
# headings to the deleted headings list
|
||||||
|
DomObjList.__init__(self, initlist, obj)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_checkbox(cls, obj):
|
||||||
|
return CheckboxList.is_domobj(obj)
|
||||||
|
|
||||||
|
def _get_heading(self):
|
||||||
|
if self.__class__.is_checkbox(self._obj):
|
||||||
|
return self._obj._document
|
||||||
|
return self._obj
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,315 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
documents
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
TODO: explain this :)
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from collections import UserList
|
||||||
|
except:
|
||||||
|
from UserList import UserList
|
||||||
|
|
||||||
|
from orgmode.liborgmode.base import MultiPurposeList, flatten_list, Direction, get_domobj_range
|
||||||
|
from orgmode.liborgmode.headings import Heading, HeadingList
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
class Document(object):
|
||||||
|
u"""
|
||||||
|
Representation of a whole org-mode document.
|
||||||
|
|
||||||
|
A Document consists basically of headings (see Headings) and some metadata.
|
||||||
|
|
||||||
|
TODO: explain the 'dirty' mechanism
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u"""
|
||||||
|
Don't call this constructor directly but use one of the concrete
|
||||||
|
implementations.
|
||||||
|
|
||||||
|
TODO: what are the concrete implementatiions?
|
||||||
|
"""
|
||||||
|
object.__init__(self)
|
||||||
|
|
||||||
|
# is a list - only the Document methods should work on this list!
|
||||||
|
self._content = None
|
||||||
|
self._dirty_meta_information = False
|
||||||
|
self._dirty_document = False
|
||||||
|
self._meta_information = MultiPurposeList(
|
||||||
|
on_change=self.set_dirty_meta_information)
|
||||||
|
self._orig_meta_information_len = None
|
||||||
|
self._headings = HeadingList(obj=self)
|
||||||
|
self._deleted_headings = []
|
||||||
|
|
||||||
|
# settings needed to align tags properly
|
||||||
|
self._tabstop = 8
|
||||||
|
self._tag_column = 77
|
||||||
|
|
||||||
|
# TODO this doesn't differentiate between ACTIVE and FINISHED todo's
|
||||||
|
self.todo_states = [u'TODO', u'DONE']
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
if self.meta_information is None:
|
||||||
|
return u'\n'.join(self.all_headings())
|
||||||
|
return u'\n'.join(self.meta_information) + u'\n' + u'\n'.join([u'\n'.join([unicode(i)] + i.body) for i in self.all_headings()])
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def get_all_todo_states(self):
|
||||||
|
u""" Convenience function that returns all todo and done states and
|
||||||
|
sequences in one big list.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: [all todo/done states]
|
||||||
|
"""
|
||||||
|
# TODO This is not necessary remove
|
||||||
|
return flatten_list(self.get_todo_states())
|
||||||
|
|
||||||
|
def get_todo_states(self):
|
||||||
|
u""" Returns a list containing a tuple of two lists of allowed todo
|
||||||
|
states split by todo and done states. Multiple todo-done state
|
||||||
|
sequences can be defined.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: [([todo states], [done states]), ..]
|
||||||
|
"""
|
||||||
|
# TODO this should be made into property so todo states can be set like
|
||||||
|
# this too.. or there was also some todo property around... oh well..
|
||||||
|
# TODO there is the same method in vimbuffer
|
||||||
|
return self.todo_states
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tabstop(self):
|
||||||
|
u""" Tabstop for this document """
|
||||||
|
return self._tabstop
|
||||||
|
|
||||||
|
@tabstop.setter
|
||||||
|
def tabstop(self, value):
|
||||||
|
self._tabstop = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tag_column(self):
|
||||||
|
u""" The column all tags are right-aligned to """
|
||||||
|
return self._tag_column
|
||||||
|
|
||||||
|
@tag_column.setter
|
||||||
|
def tag_column(self, value):
|
||||||
|
self._tag_column = value
|
||||||
|
|
||||||
|
def init_dom(self, heading=Heading):
|
||||||
|
u""" Initialize all headings in document - build DOM. This method
|
||||||
|
should be call prior to accessing the document.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
self
|
||||||
|
"""
|
||||||
|
def init_heading(_h):
|
||||||
|
u"""
|
||||||
|
:returns the initialized heading
|
||||||
|
"""
|
||||||
|
start = _h.end + 1
|
||||||
|
prev_heading = None
|
||||||
|
while True:
|
||||||
|
new_heading = self.find_heading(start, heading=heading)
|
||||||
|
|
||||||
|
# * Heading 1 <- heading
|
||||||
|
# * Heading 1 <- sibling
|
||||||
|
# or
|
||||||
|
# * Heading 2 <- heading
|
||||||
|
# * Heading 1 <- parent's sibling
|
||||||
|
if not new_heading or \
|
||||||
|
new_heading.level <= _h.level:
|
||||||
|
break
|
||||||
|
|
||||||
|
# * Heading 1 <- heading
|
||||||
|
# * Heading 2 <- first child
|
||||||
|
# * Heading 2 <- another child
|
||||||
|
new_heading._parent = _h
|
||||||
|
if prev_heading:
|
||||||
|
prev_heading._next_sibling = new_heading
|
||||||
|
new_heading._previous_sibling = prev_heading
|
||||||
|
_h.children.data.append(new_heading)
|
||||||
|
# the start and end computation is only
|
||||||
|
# possible when the new heading was properly
|
||||||
|
# added to the document structure
|
||||||
|
init_heading(new_heading)
|
||||||
|
if new_heading.children:
|
||||||
|
# skip children
|
||||||
|
start = new_heading.end_of_last_child + 1
|
||||||
|
else:
|
||||||
|
start = new_heading.end + 1
|
||||||
|
prev_heading = new_heading
|
||||||
|
|
||||||
|
return _h
|
||||||
|
|
||||||
|
h = self.find_heading(heading=heading)
|
||||||
|
# initialize meta information
|
||||||
|
if h:
|
||||||
|
self._meta_information.data.extend(self._content[:h._orig_start])
|
||||||
|
else:
|
||||||
|
self._meta_information.data.extend(self._content[:])
|
||||||
|
self._orig_meta_information_len = len(self.meta_information)
|
||||||
|
|
||||||
|
# initialize dom tree
|
||||||
|
prev_h = None
|
||||||
|
while h:
|
||||||
|
if prev_h:
|
||||||
|
prev_h._next_sibling = h
|
||||||
|
h._previous_sibling = prev_h
|
||||||
|
self.headings.data.append(h)
|
||||||
|
init_heading(h)
|
||||||
|
prev_h = h
|
||||||
|
h = self.find_heading(h.end_of_last_child + 1, heading=heading)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def meta_information(self):
|
||||||
|
u""" Meta information is text that precedes all headings in an org-mode
|
||||||
|
document. It might contain additional information about the document,
|
||||||
|
e.g. author
|
||||||
|
"""
|
||||||
|
return self._meta_information
|
||||||
|
|
||||||
|
@meta_information.setter
|
||||||
|
def meta_information(self, value):
|
||||||
|
if self._orig_meta_information_len is None:
|
||||||
|
self._orig_meta_information_len = len(self.meta_information)
|
||||||
|
if type(value) in (list, tuple) or isinstance(value, UserList):
|
||||||
|
self._meta_information[:] = flatten_list(value)
|
||||||
|
elif type(value) in (str, ):
|
||||||
|
self._meta_information[:] = u_decode(value).split(u'\n')
|
||||||
|
elif type(value) in (unicode, ):
|
||||||
|
self._meta_information[:] = value.split(u'\n')
|
||||||
|
self.set_dirty_meta_information()
|
||||||
|
|
||||||
|
@meta_information.deleter
|
||||||
|
def meta_information(self):
|
||||||
|
self.meta_information = u''
|
||||||
|
|
||||||
|
@property
|
||||||
|
def headings(self):
|
||||||
|
u""" List of top level headings """
|
||||||
|
return self._headings
|
||||||
|
|
||||||
|
@headings.setter
|
||||||
|
def headings(self, value):
|
||||||
|
self._headings[:] = value
|
||||||
|
|
||||||
|
@headings.deleter
|
||||||
|
def headings(self):
|
||||||
|
del self.headings[:]
|
||||||
|
|
||||||
|
def write(self):
|
||||||
|
u""" Write the document
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if something was written, otherwise False
|
||||||
|
"""
|
||||||
|
raise NotImplementedError(u'Abstract method, please use concrete impelementation!')
|
||||||
|
|
||||||
|
def set_dirty_meta_information(self):
|
||||||
|
u""" Mark the meta information dirty.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Causes meta information to be rewritten when saving the document
|
||||||
|
"""
|
||||||
|
self._dirty_meta_information = True
|
||||||
|
|
||||||
|
def set_dirty_document(self):
|
||||||
|
u""" Mark the whole document dirty.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
When changing a heading this method must be executed in order to
|
||||||
|
changed computation of start and end positions from a static to a
|
||||||
|
dynamic computation
|
||||||
|
"""
|
||||||
|
self._dirty_document = True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty(self):
|
||||||
|
u""" Return information about unsaved changes for the document and all
|
||||||
|
related headings.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if document contains unsaved changes.
|
||||||
|
"""
|
||||||
|
if self.is_dirty_meta_information:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self.is_dirty_document:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self._deleted_headings:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty_meta_information(self):
|
||||||
|
u""" Return True if the meta information is marked dirty """
|
||||||
|
return self._dirty_meta_information
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty_document(self):
|
||||||
|
u""" Return True if the document is marked dirty """
|
||||||
|
return self._dirty_document
|
||||||
|
|
||||||
|
def all_headings(self):
|
||||||
|
u""" Iterate over all headings of the current document in serialized
|
||||||
|
order
|
||||||
|
|
||||||
|
:returns: Returns an iterator object which returns all headings of
|
||||||
|
the current file in serialized order
|
||||||
|
"""
|
||||||
|
if not self.headings:
|
||||||
|
return
|
||||||
|
|
||||||
|
h = self.headings[0]
|
||||||
|
while h:
|
||||||
|
yield h
|
||||||
|
h = h.next_heading
|
||||||
|
return
|
||||||
|
|
||||||
|
def find_heading(
|
||||||
|
self, position=0, direction=Direction.FORWARD, heading=Heading,
|
||||||
|
connect_with_document=True):
|
||||||
|
u""" Find heading in the given direction
|
||||||
|
|
||||||
|
Args:
|
||||||
|
position (int): starting line, counting from 0 (in vim you start
|
||||||
|
counting from 1, don't forget)
|
||||||
|
direction: downwards == Direction.FORWARD,
|
||||||
|
upwards == Direction.BACKWARD
|
||||||
|
heading: Heading class from which new heading objects will be
|
||||||
|
instanciated
|
||||||
|
connect_with_document: if True, the newly created heading will be
|
||||||
|
connected with the document, otherwise not
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
heading or None: New heading
|
||||||
|
"""
|
||||||
|
start, end = get_domobj_range(
|
||||||
|
content=self._content, position=position, direction=direction,
|
||||||
|
identify_fun=heading.identify_heading)
|
||||||
|
|
||||||
|
if start is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if end is None:
|
||||||
|
end = len(self._content) - 1
|
||||||
|
|
||||||
|
document = self if connect_with_document else None
|
||||||
|
|
||||||
|
return heading.parse_heading_from_data(
|
||||||
|
self._content[start:end + 1], self.get_all_todo_states(),
|
||||||
|
document=document, orig_start=start)
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,505 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
dom object
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
TODO: explain this :)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
from orgmode.liborgmode.base import MultiPurposeList, flatten_list
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
from collections import UserList
|
||||||
|
except:
|
||||||
|
from UserList import UserList
|
||||||
|
|
||||||
|
# breaking down tasks regex
|
||||||
|
REGEX_SUBTASK = re.compile(r'\[(\d*)/(\d*)\]')
|
||||||
|
REGEX_SUBTASK_PERCENT = re.compile(r'\[(\d*)%\]')
|
||||||
|
|
||||||
|
# heading regex
|
||||||
|
REGEX_HEADING = re.compile(
|
||||||
|
r'^(?P<level>\*+)(\s+(?P<title>.*?))?\s*(\s(?P<tags>:[\w_:@]+:))?$',
|
||||||
|
flags=re.U)
|
||||||
|
REGEX_TAG = re.compile(
|
||||||
|
r'^\s*((?P<title>[^\s]*?)\s+)?(?P<tags>:[\w_:@]+:)$',
|
||||||
|
flags=re.U)
|
||||||
|
REGEX_TODO = re.compile(r'^[^\s]*$')
|
||||||
|
|
||||||
|
# checkbox regex:
|
||||||
|
# - [ ] checkbox item
|
||||||
|
# - [X] checkbox item
|
||||||
|
# - [ ]
|
||||||
|
# - no status checkbox
|
||||||
|
UnOrderListType = [u'-', u'+', u'*']
|
||||||
|
OrderListType = [u'.', u')']
|
||||||
|
REGEX_CHECKBOX = re.compile(
|
||||||
|
r'^(?P<level>\s*)(?P<type>[%s]|([a-zA-Z]|[\d]+)[%s])(\s+(?P<status>\[.\]))?\s*(?P<title>.*)$'
|
||||||
|
% (''.join(UnOrderListType), ''.join(OrderListType)), flags=re.U)
|
||||||
|
|
||||||
|
|
||||||
|
class DomObj(object):
|
||||||
|
u"""
|
||||||
|
A DomObj is DOM structure element, like Heading and Checkbox.
|
||||||
|
Its purpose is to abstract the same parts of Heading and Checkbox objects,
|
||||||
|
and make code reusable.
|
||||||
|
|
||||||
|
All methods and properties are extracted from Heading object.
|
||||||
|
Heading and Checkbox objects inherit from DomObj, and override some specific
|
||||||
|
methods in their own objects.
|
||||||
|
|
||||||
|
Normally, we don't intend to use DomObj directly. However, we can add some more
|
||||||
|
DOM structure element based on this class to make code more concise.
|
||||||
|
"""
|
||||||
|
# TODO should this and DomObj_list be abstract methods? If so use ABC to
|
||||||
|
# force abstract methods
|
||||||
|
|
||||||
|
def __init__(self, level=1, title=u'', body=None):
|
||||||
|
u"""
|
||||||
|
:level: Level of the dom object
|
||||||
|
:title: Title of the dom object
|
||||||
|
:body: Body of the dom object
|
||||||
|
"""
|
||||||
|
object.__init__(self)
|
||||||
|
|
||||||
|
self._document = None
|
||||||
|
self._parent = None
|
||||||
|
self._previous_sibling = None
|
||||||
|
self._next_sibling = None
|
||||||
|
self._children = MultiPurposeList()
|
||||||
|
self._orig_start = None
|
||||||
|
self._orig_len = 0
|
||||||
|
|
||||||
|
self._level = level
|
||||||
|
# title
|
||||||
|
self._title = u''
|
||||||
|
if title:
|
||||||
|
self.title = title
|
||||||
|
|
||||||
|
# body
|
||||||
|
self._dirty_body = False
|
||||||
|
self._body = MultiPurposeList(on_change=self.set_dirty_body)
|
||||||
|
if body:
|
||||||
|
self.body = body
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u'<dom obj level=%s, title=%s>' % (level, title)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
# 1 is for the heading's title
|
||||||
|
return 1 + len(self.body)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty(self):
|
||||||
|
u""" Return True if the dom obj body is marked dirty """
|
||||||
|
return self._dirty_body
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty_body(self):
|
||||||
|
u""" Return True if the dom obj body is marked dirty """
|
||||||
|
return self._dirty_body
|
||||||
|
|
||||||
|
def get_index_in_parent_list(self):
|
||||||
|
""" Retrieve the index value of current dom obj in the parents list of
|
||||||
|
dom objs. This works also for top level dom objs.
|
||||||
|
|
||||||
|
:returns: Index value or None if dom obj doesn't have a
|
||||||
|
parent/document or is not in the list of dom objs
|
||||||
|
"""
|
||||||
|
l = self.get_parent_list()
|
||||||
|
if l:
|
||||||
|
return l.index(self)
|
||||||
|
|
||||||
|
def get_parent_list(self):
|
||||||
|
""" Retrieve the parents list of dom objs. This works also for top
|
||||||
|
level dom objs.
|
||||||
|
|
||||||
|
:returns: List of dom objs or None if dom objs doesn't have a
|
||||||
|
parent/document or is not in the list of dom objs
|
||||||
|
"""
|
||||||
|
if self.parent:
|
||||||
|
if self in self.parent.children:
|
||||||
|
return self.parent.children
|
||||||
|
|
||||||
|
def set_dirty(self):
|
||||||
|
u""" Mark the dom objs and body dirty so that it will be rewritten when
|
||||||
|
saving the document """
|
||||||
|
if self._document:
|
||||||
|
self._document.set_dirty_document()
|
||||||
|
|
||||||
|
def set_dirty_body(self):
|
||||||
|
u""" Mark the dom objs' body dirty so that it will be rewritten when
|
||||||
|
saving the document """
|
||||||
|
self._dirty_body = True
|
||||||
|
if self._document:
|
||||||
|
self._document.set_dirty_document()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def document(self):
|
||||||
|
u""" Read only access to the document. If you want to change the
|
||||||
|
document, just assign the dom obj to another document """
|
||||||
|
return self._document
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parent(self):
|
||||||
|
u""" Access to the parent dom obj """
|
||||||
|
return self._parent
|
||||||
|
|
||||||
|
@property
|
||||||
|
def number_of_parents(self):
|
||||||
|
u""" Access to the number of parent dom objs before reaching the root
|
||||||
|
document """
|
||||||
|
def count_parents(h):
|
||||||
|
if h.parent:
|
||||||
|
return 1 + count_parents(h.parent)
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
return count_parents(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def previous_sibling(self):
|
||||||
|
u""" Access to the previous dom obj that's a sibling of the current one
|
||||||
|
"""
|
||||||
|
return self._previous_sibling
|
||||||
|
|
||||||
|
@property
|
||||||
|
def next_sibling(self):
|
||||||
|
u""" Access to the next dom obj that's a sibling of the current one """
|
||||||
|
return self._next_sibling
|
||||||
|
|
||||||
|
@property
|
||||||
|
def previous_item(self):
|
||||||
|
u""" Serialized access to the previous dom obj """
|
||||||
|
if self.previous_sibling:
|
||||||
|
h = self.previous_sibling
|
||||||
|
while h.children:
|
||||||
|
h = h.children[-1]
|
||||||
|
return h
|
||||||
|
elif self.parent:
|
||||||
|
return self.parent
|
||||||
|
|
||||||
|
@property
|
||||||
|
def next_item(self):
|
||||||
|
u""" Serialized access to the next dom obj """
|
||||||
|
if self.children:
|
||||||
|
return self.children[0]
|
||||||
|
elif self.next_sibling:
|
||||||
|
return self.next_sibling
|
||||||
|
else:
|
||||||
|
h = self.parent
|
||||||
|
while h:
|
||||||
|
if h.next_sibling:
|
||||||
|
return h.next_sibling
|
||||||
|
else:
|
||||||
|
h = h.parent
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start(self):
|
||||||
|
u""" Access to the starting line of the dom obj """
|
||||||
|
if self.document is None or not self.document.is_dirty:
|
||||||
|
return self._orig_start
|
||||||
|
|
||||||
|
def item_len_generator(h):
|
||||||
|
while h:
|
||||||
|
yield len(h)
|
||||||
|
h = h.previous_item
|
||||||
|
return sum(item for item in item_len_generator(self.previous_item))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start_vim(self):
|
||||||
|
if self.start is not None:
|
||||||
|
return self.start + 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end(self):
|
||||||
|
u""" Access to the ending line of the dom obj """
|
||||||
|
if self.start is not None:
|
||||||
|
return self.start + len(self.body)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_vim(self):
|
||||||
|
if self.end is not None:
|
||||||
|
return self.end + 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_of_last_child(self):
|
||||||
|
u""" Access to end of the last child """
|
||||||
|
if self.children:
|
||||||
|
child = self.children[-1]
|
||||||
|
while child.children:
|
||||||
|
child = child.children[-1]
|
||||||
|
return child.end
|
||||||
|
return self.end
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_of_last_child_vim(self):
|
||||||
|
return self.end_of_last_child + 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def children(self):
|
||||||
|
u""" MultiPurposeList[dom_objects??]: subheadings of the current DomObj
|
||||||
|
|
||||||
|
Setter method takes list, tuple or userlist with DOMObjects
|
||||||
|
"""
|
||||||
|
return self._children
|
||||||
|
|
||||||
|
@children.setter
|
||||||
|
def children(self, value):
|
||||||
|
v = value
|
||||||
|
if type(v) in (list, tuple) or isinstance(v, UserList):
|
||||||
|
v = flatten_list(v)
|
||||||
|
self._children[:] = v
|
||||||
|
|
||||||
|
@children.deleter
|
||||||
|
def children(self):
|
||||||
|
del self.children[:]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def first_child(self):
|
||||||
|
u""" Access to the first child dom obj or None if no children exist """
|
||||||
|
if self.children:
|
||||||
|
return self.children[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def last_child(self):
|
||||||
|
u""" Access to the last child dom obj or None if no children exist """
|
||||||
|
if self.children:
|
||||||
|
return self.children[-1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def level(self):
|
||||||
|
u""" int: Access the the dom obj level
|
||||||
|
|
||||||
|
Setter sets the DOM object and the document as dirty if invoked.
|
||||||
|
"""
|
||||||
|
return self._level
|
||||||
|
|
||||||
|
@level.setter
|
||||||
|
def level(self, value):
|
||||||
|
# TODO Shouldn't there be and error when values is not int?
|
||||||
|
self._level = int(value)
|
||||||
|
self.set_dirty()
|
||||||
|
|
||||||
|
@level.deleter
|
||||||
|
def level(self):
|
||||||
|
self.level = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def title(self):
|
||||||
|
u""" str: Get the title of current dom object
|
||||||
|
|
||||||
|
Setter sets the DOM object and the document as dirty if invoked.
|
||||||
|
"""
|
||||||
|
return self._title.strip()
|
||||||
|
|
||||||
|
@title.setter
|
||||||
|
def title(self, value):
|
||||||
|
if type(value) not in (unicode, str):
|
||||||
|
raise ValueError(u'Title must be a string.')
|
||||||
|
v = value
|
||||||
|
if type(v) == str:
|
||||||
|
v = u_decode(v)
|
||||||
|
self._title = v.strip()
|
||||||
|
self.set_dirty()
|
||||||
|
|
||||||
|
@title.deleter
|
||||||
|
def title(self):
|
||||||
|
self._title = u''
|
||||||
|
|
||||||
|
@property
|
||||||
|
def body(self):
|
||||||
|
u""" MultiPurposeList[]: Holds the content belonging to the heading """
|
||||||
|
return self._body
|
||||||
|
|
||||||
|
@body.setter
|
||||||
|
def body(self, value):
|
||||||
|
if type(value) in (list, tuple) or isinstance(value, UserList):
|
||||||
|
self._body[:] = flatten_list(value)
|
||||||
|
elif type(value) in (str, ):
|
||||||
|
self._body[:] = u_decode(value).split(u'\n')
|
||||||
|
elif type(value) in (unicode, ):
|
||||||
|
self._body[:] = value.split(u'\n')
|
||||||
|
else:
|
||||||
|
self.body = list(unicode(value))
|
||||||
|
|
||||||
|
@body.deleter
|
||||||
|
def body(self):
|
||||||
|
# TODO write this as del self._body[:] because there is no reason to
|
||||||
|
# call so much code for deleting a list
|
||||||
|
self.body = []
|
||||||
|
|
||||||
|
|
||||||
|
class DomObjList(MultiPurposeList):
|
||||||
|
u"""
|
||||||
|
A Dom Obj List
|
||||||
|
"""
|
||||||
|
def __init__(self, initlist=None, obj=None):
|
||||||
|
"""
|
||||||
|
:initlist: Initial data
|
||||||
|
:obj: Link to a concrete Heading or Document object
|
||||||
|
"""
|
||||||
|
# it's not necessary to register a on_change hook because the heading
|
||||||
|
# list will itself take care of marking headings dirty or adding
|
||||||
|
# headings to the deleted headings list
|
||||||
|
MultiPurposeList.__init__(self)
|
||||||
|
|
||||||
|
self._obj = obj
|
||||||
|
|
||||||
|
# initialization must be done here, because
|
||||||
|
# self._document is not initialized when the
|
||||||
|
# constructor of MultiPurposeList is called
|
||||||
|
if initlist:
|
||||||
|
self.extend(initlist)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_domobj(cls, obj):
|
||||||
|
# TODO no reason for it to be class method. Does it even need to exist
|
||||||
|
# because it is quite clear what isinstance does and in derived methods
|
||||||
|
# isinstance(Heading, DomObj) would return True anyway.
|
||||||
|
return isinstance(obj, DomObj)
|
||||||
|
|
||||||
|
# TODO this should be made into a property
|
||||||
|
def _get_document(self):
|
||||||
|
if self.__class__.is_domobj(self._obj):
|
||||||
|
return self._obj._document
|
||||||
|
return self._obj
|
||||||
|
|
||||||
|
def __setitem__(self, i, item):
|
||||||
|
if isinstance(i, slice):
|
||||||
|
o = item
|
||||||
|
if self.__class__.is_domobj(o):
|
||||||
|
o = (o, )
|
||||||
|
o = flatten_list(o)
|
||||||
|
for item in o:
|
||||||
|
if not self.__class__.is_domobj(item):
|
||||||
|
raise ValueError(u'List contains items that are not a Dom obj!')
|
||||||
|
|
||||||
|
# self._add_to_deleted_domobjs(self[i:j])
|
||||||
|
# self._associate_domobj(o, \
|
||||||
|
# self[i - 1] if i - 1 >= 0 and i < len(self) else None, \
|
||||||
|
# self[j] if j >= 0 and j < len(self) else None)
|
||||||
|
MultiPurposeList.__setitem__(self, i, o)
|
||||||
|
else:
|
||||||
|
if not self.__class__.is_domobj(item):
|
||||||
|
raise ValueError(u'Item is not a Dom obj!')
|
||||||
|
if item in self:
|
||||||
|
raise ValueError(u'Dom obj is already part of this list!')
|
||||||
|
# self._add_to_deleted_domobjs(self[i])
|
||||||
|
|
||||||
|
# self._associate_domobj(item, \
|
||||||
|
# self[i - 1] if i - 1 >= 0 else None, \
|
||||||
|
# self[i + 1] if i + 1 < len(self) else None)
|
||||||
|
MultiPurposeList.__setitem__(self, i, item)
|
||||||
|
|
||||||
|
def __delitem__(self, i, taint=True):
|
||||||
|
if isinstance(i, slice):
|
||||||
|
items = self[i]
|
||||||
|
if items:
|
||||||
|
first = items[0]
|
||||||
|
last = items[-1]
|
||||||
|
if first.previous_sibling:
|
||||||
|
first.previous_sibling._next_sibling = last.next_sibling
|
||||||
|
if last.next_sibling:
|
||||||
|
last.next_sibling._previous_sibling = first.previous_sibling
|
||||||
|
# if taint:
|
||||||
|
# self._add_to_deleted_domobjs(items)
|
||||||
|
else:
|
||||||
|
item = self[i]
|
||||||
|
if item.previous_sibling:
|
||||||
|
item.previous_sibling._next_sibling = item.next_sibling
|
||||||
|
if item.next_sibling:
|
||||||
|
item.next_sibling._previous_sibling = item.previous_sibling
|
||||||
|
|
||||||
|
# if taint:
|
||||||
|
# self._add_to_deleted_domobjs(item)
|
||||||
|
MultiPurposeList.__delitem__(self, i)
|
||||||
|
|
||||||
|
def __setslice__(self, i, j, other):
|
||||||
|
self.__setitem__(slice(i, j), other)
|
||||||
|
|
||||||
|
def __delslice__(self, i, j, taint=True):
|
||||||
|
self.__delitem__(slice(i, j), taint=taint)
|
||||||
|
|
||||||
|
def __iadd__(self, other):
|
||||||
|
o = other
|
||||||
|
if self.__class__.is_domobj(o):
|
||||||
|
o = (o, )
|
||||||
|
for item in flatten_list(o):
|
||||||
|
if not self.__class__.is_domobj(item):
|
||||||
|
raise ValueError(u'List contains items that are not a Dom obj!')
|
||||||
|
# self._associate_domobj(o, self[-1] if len(self) > 0 else None, None)
|
||||||
|
return MultiPurposeList.__iadd__(self, o)
|
||||||
|
|
||||||
|
def __imul__(self, n):
|
||||||
|
# TODO das müsste eigentlich ein klonen von objekten zur Folge haben
|
||||||
|
return MultiPurposeList.__imul__(self, n)
|
||||||
|
|
||||||
|
def append(self, item, taint=True):
|
||||||
|
if not self.__class__.is_domobj(item):
|
||||||
|
raise ValueError(u'Item is not a heading!')
|
||||||
|
if item in self:
|
||||||
|
raise ValueError(u'Heading is already part of this list!')
|
||||||
|
# self._associate_domobj(
|
||||||
|
# item, self[-1] if len(self) > 0 else None,
|
||||||
|
# None, taint=taint)
|
||||||
|
MultiPurposeList.append(self, item)
|
||||||
|
|
||||||
|
def insert(self, i, item, taint=True):
|
||||||
|
# self._associate_domobj(
|
||||||
|
# item,
|
||||||
|
# self[i - 1] if i - 1 >= 0 and i - 1 < len(self) else None,
|
||||||
|
# self[i] if i >= 0 and i < len(self) else None, taint=taint)
|
||||||
|
MultiPurposeList.insert(self, i, item)
|
||||||
|
|
||||||
|
def pop(self, i=-1):
|
||||||
|
item = self[i]
|
||||||
|
# self._add_to_deleted_domobjs(item)
|
||||||
|
del self[i]
|
||||||
|
return item
|
||||||
|
|
||||||
|
def remove_slice(self, i, j, taint=True):
|
||||||
|
self.__delitem__(slice(i, j), taint=taint)
|
||||||
|
|
||||||
|
def remove(self, item, taint=True):
|
||||||
|
self.__delitem__(self.index(item), taint=taint)
|
||||||
|
|
||||||
|
def reverse(self):
|
||||||
|
MultiPurposeList.reverse(self)
|
||||||
|
prev_h = None
|
||||||
|
for h in self:
|
||||||
|
h._previous_sibling = prev_h
|
||||||
|
h._next_sibling = None
|
||||||
|
prev_h._next_sibling = h
|
||||||
|
h.set_dirty()
|
||||||
|
prev_h = h
|
||||||
|
|
||||||
|
def sort(self, *args, **kwds):
|
||||||
|
MultiPurposeList.sort(*args, **kwds)
|
||||||
|
prev_h = None
|
||||||
|
for h in self:
|
||||||
|
h._previous_sibling = prev_h
|
||||||
|
h._next_sibling = None
|
||||||
|
prev_h._next_sibling = h
|
||||||
|
h.set_dirty()
|
||||||
|
prev_h = h
|
||||||
|
|
||||||
|
def extend(self, other):
|
||||||
|
o = other
|
||||||
|
if self.__class__.is_domobj(o):
|
||||||
|
o = (o, )
|
||||||
|
for item in o:
|
||||||
|
if not self.__class__.is_domobj(item):
|
||||||
|
raise ValueError(u'List contains items that are not a heading!')
|
||||||
|
# self._associate_domobj(o, self[-1] if len(self) > 0 else None, None)
|
||||||
|
MultiPurposeList.extend(self, o)
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,889 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
headings
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
TODO: explain this :)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
import vim
|
||||||
|
from orgmode.liborgmode.base import MultiPurposeList, flatten_list, Direction, get_domobj_range
|
||||||
|
from orgmode.liborgmode.orgdate import OrgTimeRange
|
||||||
|
from orgmode.liborgmode.orgdate import get_orgdate
|
||||||
|
from orgmode.liborgmode.checkboxes import Checkbox, CheckboxList
|
||||||
|
from orgmode.liborgmode.dom_obj import DomObj, DomObjList, REGEX_SUBTASK, REGEX_SUBTASK_PERCENT, REGEX_HEADING, REGEX_TAG, REGEX_TODO
|
||||||
|
|
||||||
|
from orgmode.py3compat.xrange_compatibility import *
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
from collections import UserList
|
||||||
|
except:
|
||||||
|
from UserList import UserList
|
||||||
|
from itertools import ifilter as filter
|
||||||
|
|
||||||
|
class Heading(DomObj):
|
||||||
|
u""" Structural heading object """
|
||||||
|
|
||||||
|
def __init__(self, level=1, title=u'', tags=None, todo=None, body=None, active_date=None):
|
||||||
|
u"""
|
||||||
|
:level: Level of the heading
|
||||||
|
:title: Title of the heading
|
||||||
|
:tags: Tags of the heading
|
||||||
|
:todo: Todo state of the heading
|
||||||
|
:body: Body of the heading
|
||||||
|
:active_date: active date that is used in the agenda
|
||||||
|
"""
|
||||||
|
DomObj.__init__(self, level=level, title=title, body=body)
|
||||||
|
|
||||||
|
self._children = HeadingList(obj=self)
|
||||||
|
self._dirty_heading = False
|
||||||
|
|
||||||
|
# todo
|
||||||
|
self._todo = None
|
||||||
|
if todo:
|
||||||
|
self.todo = todo
|
||||||
|
|
||||||
|
# tags
|
||||||
|
self._tags = MultiPurposeList(on_change=self.set_dirty_heading)
|
||||||
|
if tags:
|
||||||
|
self.tags = tags
|
||||||
|
|
||||||
|
# active date
|
||||||
|
self._active_date = active_date
|
||||||
|
if active_date:
|
||||||
|
self.active_date = active_date
|
||||||
|
|
||||||
|
# checkboxes
|
||||||
|
self._checkboxes = CheckboxList(obj=self)
|
||||||
|
self._cached_checkbox = None
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
res = u'*' * self.level
|
||||||
|
if self.todo:
|
||||||
|
res = u' '.join((res, self.todo))
|
||||||
|
if self.title:
|
||||||
|
res = u' '.join((res, self.title))
|
||||||
|
|
||||||
|
# compute position of tags
|
||||||
|
if self.tags:
|
||||||
|
tabs = 0
|
||||||
|
spaces = 2
|
||||||
|
tags = u':%s:' % (u':'.join(self.tags), )
|
||||||
|
|
||||||
|
# FIXME this is broken because of missing associations for headings
|
||||||
|
ts = 6
|
||||||
|
tag_column = 77
|
||||||
|
if self.document:
|
||||||
|
ts = self.document.tabstop
|
||||||
|
tag_column = self.document.tag_column
|
||||||
|
|
||||||
|
len_heading = len(res)
|
||||||
|
len_tags = len(tags)
|
||||||
|
if len_heading + spaces + len_tags < tag_column:
|
||||||
|
spaces_to_next_tabstop = ts - divmod(len_heading, ts)[1]
|
||||||
|
|
||||||
|
if len_heading + spaces_to_next_tabstop + len_tags < tag_column:
|
||||||
|
tabs, spaces = divmod(
|
||||||
|
tag_column - (len_heading + spaces_to_next_tabstop + len_tags),
|
||||||
|
ts)
|
||||||
|
|
||||||
|
if spaces_to_next_tabstop:
|
||||||
|
tabs += 1
|
||||||
|
else:
|
||||||
|
spaces = tag_column - (len_heading + len_tags)
|
||||||
|
|
||||||
|
res += u'\t' * tabs + u' ' * spaces + tags
|
||||||
|
|
||||||
|
# append a trailing space when there are just * and no text
|
||||||
|
if len(res) == self.level:
|
||||||
|
res += u' '
|
||||||
|
return res
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
# 1 is for the heading's title
|
||||||
|
return 1 + len(self.body)
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
"""
|
||||||
|
Headings can be sorted by date.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if self.active_date < other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date == other.active_date:
|
||||||
|
return False
|
||||||
|
elif self.active_date > other.active_date:
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
if self.active_date and not other.active_date:
|
||||||
|
return True
|
||||||
|
elif not self.active_date and other.active_date:
|
||||||
|
return False
|
||||||
|
elif not self.active_date and not other.active_date:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __le__(self, other):
|
||||||
|
"""
|
||||||
|
Headings can be sorted by date.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if self.active_date < other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date == other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date > other.active_date:
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
if self.active_date and not other.active_date:
|
||||||
|
return True
|
||||||
|
elif not self.active_date and other.active_date:
|
||||||
|
return False
|
||||||
|
elif not self.active_date and not other.active:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __ge__(self, other):
|
||||||
|
"""
|
||||||
|
Headings can be sorted by date.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if self.active_date > other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date == other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date < other.active_date:
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
if not self.active_date and other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date and not other.active_date:
|
||||||
|
return False
|
||||||
|
elif not self.active_date and not other.active:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __gt__(self, other):
|
||||||
|
"""
|
||||||
|
Headings can be sorted by date.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if self.active_date > other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date == other.active_date:
|
||||||
|
return False
|
||||||
|
elif self.active_date < other.active_date:
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
if not self.active_date and other.active_date:
|
||||||
|
return True
|
||||||
|
elif self.active_date and not other.active_date:
|
||||||
|
return False
|
||||||
|
elif not self.active_date and not other.active:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def copy(self, including_children=True, parent=None):
|
||||||
|
u"""
|
||||||
|
Create a copy of the current heading. The heading will be completely
|
||||||
|
detached and not even belong to a document anymore.
|
||||||
|
|
||||||
|
:including_children: If True a copy of all children is create as
|
||||||
|
well. If False the returned heading doesn't
|
||||||
|
have any children.
|
||||||
|
:parent: Don't use this parameter. It's set
|
||||||
|
automatically.
|
||||||
|
"""
|
||||||
|
heading = self.__class__(
|
||||||
|
level=self.level, title=self.title,
|
||||||
|
tags=self.tags, todo=self.todo, body=self.body[:])
|
||||||
|
if parent:
|
||||||
|
parent.children.append(heading)
|
||||||
|
if including_children and self.children:
|
||||||
|
for item in self.children:
|
||||||
|
item.copy(
|
||||||
|
including_children=including_children,
|
||||||
|
parent=heading)
|
||||||
|
heading._orig_start = self._orig_start
|
||||||
|
heading._orig_len = self._orig_len
|
||||||
|
|
||||||
|
heading._dirty_heading = self.is_dirty_heading
|
||||||
|
|
||||||
|
return heading
|
||||||
|
|
||||||
|
def all_checkboxes(self):
|
||||||
|
u""" Iterate over all checkboxes of the current heading in serialized
|
||||||
|
order
|
||||||
|
|
||||||
|
:returns: Returns an iterator object which returns all checkboxes of
|
||||||
|
the current heading in serialized order
|
||||||
|
"""
|
||||||
|
if not self.checkboxes:
|
||||||
|
return
|
||||||
|
|
||||||
|
c = self.first_checkbox
|
||||||
|
while c:
|
||||||
|
yield c
|
||||||
|
c = c.next_checkbox
|
||||||
|
return
|
||||||
|
|
||||||
|
def all_toplevel_checkboxes(self):
|
||||||
|
u""" return all top level checkboxes for current heading """
|
||||||
|
if not self.checkboxes:
|
||||||
|
return
|
||||||
|
|
||||||
|
c = self.first_checkbox
|
||||||
|
while c:
|
||||||
|
yield c
|
||||||
|
c = c.next_sibling
|
||||||
|
return
|
||||||
|
|
||||||
|
def find_checkbox(self, position=0, direction=Direction.FORWARD,
|
||||||
|
checkbox=Checkbox, connect_with_heading=True):
|
||||||
|
u""" Find checkbox in the given direction
|
||||||
|
|
||||||
|
:postition: starting line, counting from 0 (in vim you start
|
||||||
|
counting from 1, don't forget)
|
||||||
|
:direction: downwards == Direction.FORWARD,
|
||||||
|
upwards == Direction.BACKWARD
|
||||||
|
:checkbox: Checkbox class from which new checkbox objects will be
|
||||||
|
instanciated
|
||||||
|
:connect_with_heading: if True, the newly created checkbox will be
|
||||||
|
connected with the heading, otherwise not
|
||||||
|
|
||||||
|
:returns: New checkbox object or None
|
||||||
|
"""
|
||||||
|
doc = self.document
|
||||||
|
(start, end) = get_domobj_range(content=doc._content, position=position, direction=direction, identify_fun=checkbox.identify_checkbox)
|
||||||
|
# if out of current headinig range, reutrn None
|
||||||
|
heading_end = self.start + len(self) - 1
|
||||||
|
if start is not None and start > heading_end:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if end is not None and end > heading_end:
|
||||||
|
end = heading_end
|
||||||
|
|
||||||
|
if start is not None and end is None:
|
||||||
|
end = heading_end
|
||||||
|
if start is not None and end is not None:
|
||||||
|
return checkbox.parse_checkbox_from_data(
|
||||||
|
doc._content[start:end + 1],
|
||||||
|
heading=self if connect_with_heading else None, orig_start=start)
|
||||||
|
|
||||||
|
def init_checkboxes(self, checkbox=Checkbox):
|
||||||
|
u""" Initialize all checkboxes in current heading - build DOM.
|
||||||
|
|
||||||
|
:returns: self
|
||||||
|
"""
|
||||||
|
def init_checkbox(_c):
|
||||||
|
u"""
|
||||||
|
:returns the initialized checkbox
|
||||||
|
"""
|
||||||
|
start = _c.end + 1
|
||||||
|
prev_checkbox = None
|
||||||
|
while True:
|
||||||
|
new_checkbox = self.find_checkbox(start, checkbox=checkbox)
|
||||||
|
|
||||||
|
# * Checkbox 1 <- checkbox
|
||||||
|
# * Checkbox 1 <- sibling
|
||||||
|
# or
|
||||||
|
# * Checkbox 2 <- checkbox
|
||||||
|
# * Checkbox 1 <- parent's sibling
|
||||||
|
if not new_checkbox or \
|
||||||
|
new_checkbox.level <= _c.level:
|
||||||
|
break
|
||||||
|
|
||||||
|
# * Checkbox 1 <- heading
|
||||||
|
# * Checkbox 2 <- first child
|
||||||
|
# * Checkbox 2 <- another child
|
||||||
|
new_checkbox._parent = _c
|
||||||
|
if prev_checkbox:
|
||||||
|
prev_checkbox._next_sibling = new_checkbox
|
||||||
|
new_checkbox._previous_sibling = prev_checkbox
|
||||||
|
_c.children.data.append(new_checkbox)
|
||||||
|
# the start and end computation is only
|
||||||
|
# possible when the new checkbox was properly
|
||||||
|
# added to the document structure
|
||||||
|
init_checkbox(new_checkbox)
|
||||||
|
if new_checkbox.children:
|
||||||
|
# skip children
|
||||||
|
start = new_checkbox.end_of_last_child + 1
|
||||||
|
else:
|
||||||
|
start = new_checkbox.end + 1
|
||||||
|
prev_checkbox = new_checkbox
|
||||||
|
|
||||||
|
return _c
|
||||||
|
|
||||||
|
c = self.find_checkbox(checkbox=checkbox, position=self.start)
|
||||||
|
|
||||||
|
# initialize dom tree
|
||||||
|
prev_c = None
|
||||||
|
while c:
|
||||||
|
if prev_c and prev_c.level == c.level:
|
||||||
|
prev_c._next_sibling = c
|
||||||
|
c._previous_sibling = prev_c
|
||||||
|
self.checkboxes.data.append(c)
|
||||||
|
init_checkbox(c)
|
||||||
|
prev_c = c
|
||||||
|
c = self.find_checkbox(c.end_of_last_child + 1, checkbox=checkbox)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def current_checkbox(self, position=None):
|
||||||
|
u""" Find the current checkbox (search backward) and return the related object
|
||||||
|
:returns: Checkbox object or None
|
||||||
|
"""
|
||||||
|
if position is None:
|
||||||
|
position = vim.current.window.cursor[0] - 1
|
||||||
|
|
||||||
|
if not self.checkboxes:
|
||||||
|
return
|
||||||
|
|
||||||
|
def binaryFindInHeading():
|
||||||
|
hi = len(self.checkboxes)
|
||||||
|
lo = 0
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo + hi) // 2
|
||||||
|
c = self.checkboxes[mid]
|
||||||
|
if c.end_of_last_child < position:
|
||||||
|
lo = mid + 1
|
||||||
|
elif c.start > position:
|
||||||
|
hi = mid
|
||||||
|
else:
|
||||||
|
return binaryFindCheckbox(c)
|
||||||
|
|
||||||
|
def binaryFindCheckbox(checkbox):
|
||||||
|
if not checkbox.children or checkbox.end >= position:
|
||||||
|
return checkbox
|
||||||
|
|
||||||
|
hi = len(checkbox.children)
|
||||||
|
lo = 0
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo + hi) // 2
|
||||||
|
c = checkbox.children[mid]
|
||||||
|
if c.end_of_last_child < position:
|
||||||
|
lo = mid + 1
|
||||||
|
elif c.start > position:
|
||||||
|
hi = mid
|
||||||
|
else:
|
||||||
|
return binaryFindCheckbox(c)
|
||||||
|
|
||||||
|
# look at the cache to find the heading
|
||||||
|
c_tmp = self._cached_checkbox
|
||||||
|
if c_tmp is not None:
|
||||||
|
if c_tmp.end_of_last_child > position and \
|
||||||
|
c_tmp.start < position:
|
||||||
|
if c_tmp.end < position:
|
||||||
|
self._cached_checkbox = binaryFindCheckbox(c_tmp)
|
||||||
|
return self._cached_checkbox
|
||||||
|
|
||||||
|
self._cached_checkbox = binaryFindInHeading()
|
||||||
|
return self._cached_checkbox
|
||||||
|
|
||||||
|
@property
|
||||||
|
def first_checkbox(self):
|
||||||
|
u""" Access to the first child checkbox or None if no children exist """
|
||||||
|
if self.checkboxes:
|
||||||
|
return self.checkboxes[0]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse_heading_from_data(
|
||||||
|
cls, data, allowed_todo_states, document=None,
|
||||||
|
orig_start=None):
|
||||||
|
u""" Construct a new heading from the provided data
|
||||||
|
|
||||||
|
:data: List of lines
|
||||||
|
:allowed_todo_states: TODO???
|
||||||
|
:document: The document object this heading belongs to
|
||||||
|
:orig_start: The original start of the heading in case it was read
|
||||||
|
from a document. If orig_start is provided, the
|
||||||
|
resulting heading will not be marked dirty.
|
||||||
|
|
||||||
|
:returns: The newly created heading
|
||||||
|
"""
|
||||||
|
test_not_empty = lambda x: x != u''
|
||||||
|
|
||||||
|
def parse_title(heading_line):
|
||||||
|
# WARNING this regular expression fails if there is just one or no
|
||||||
|
# word in the heading but a tag!
|
||||||
|
m = REGEX_HEADING.match(heading_line)
|
||||||
|
if m:
|
||||||
|
r = m.groupdict()
|
||||||
|
level = len(r[u'level'])
|
||||||
|
todo = None
|
||||||
|
title = u''
|
||||||
|
tags = filter(test_not_empty, r[u'tags'].split(u':')) if r[u'tags'] else []
|
||||||
|
tags = list(tags)
|
||||||
|
|
||||||
|
# if there is just one or no word in the heading, redo the parsing
|
||||||
|
mt = REGEX_TAG.match(r[u'title'])
|
||||||
|
if not tags and mt:
|
||||||
|
r = mt.groupdict()
|
||||||
|
tags = filter(test_not_empty, r[u'tags'].split(u':')) if r[u'tags'] else []
|
||||||
|
tags = list(tags)
|
||||||
|
if r[u'title'] is not None:
|
||||||
|
_todo_title = [i.strip() for i in r[u'title'].split(None, 1)]
|
||||||
|
if _todo_title and _todo_title[0] in allowed_todo_states:
|
||||||
|
todo = _todo_title[0]
|
||||||
|
if len(_todo_title) > 1:
|
||||||
|
title = _todo_title[1]
|
||||||
|
else:
|
||||||
|
title = r[u'title'].strip()
|
||||||
|
|
||||||
|
return (level, todo, title, tags)
|
||||||
|
raise ValueError(u'Data doesn\'t start with a heading definition.')
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
raise ValueError(u'Unable to create heading, no data provided.')
|
||||||
|
|
||||||
|
# create new heaing
|
||||||
|
new_heading = cls()
|
||||||
|
new_heading.level, new_heading.todo, new_heading.title, new_heading.tags = parse_title(data[0])
|
||||||
|
new_heading.body = data[1:]
|
||||||
|
if orig_start is not None:
|
||||||
|
new_heading._dirty_heading = False
|
||||||
|
new_heading._dirty_body = False
|
||||||
|
new_heading._orig_start = orig_start
|
||||||
|
new_heading._orig_len = len(new_heading)
|
||||||
|
if document:
|
||||||
|
new_heading._document = document
|
||||||
|
|
||||||
|
# try to find active dates
|
||||||
|
tmp_orgdate = get_orgdate(data)
|
||||||
|
if tmp_orgdate and tmp_orgdate.active \
|
||||||
|
and not isinstance(tmp_orgdate, OrgTimeRange):
|
||||||
|
new_heading.active_date = tmp_orgdate
|
||||||
|
else:
|
||||||
|
new_heading.active_date = None
|
||||||
|
|
||||||
|
return new_heading
|
||||||
|
|
||||||
|
def update_subtasks(self, total=0, on=0):
|
||||||
|
u""" Update subtask information for current heading
|
||||||
|
:total: total # of top level checkboxes
|
||||||
|
:on: # of top level checkboxes which are on
|
||||||
|
"""
|
||||||
|
if total != 0:
|
||||||
|
percent = (on * 100) / total
|
||||||
|
else:
|
||||||
|
percent = 0
|
||||||
|
|
||||||
|
count = "%d/%d" % (on, total)
|
||||||
|
self.title = REGEX_SUBTASK.sub("[%s]" % (count), self.title)
|
||||||
|
self.title = REGEX_SUBTASK_PERCENT.sub("[%d%%]" % (percent), self.title)
|
||||||
|
self.document.write_heading(self, including_children=False)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def identify_heading(line):
|
||||||
|
u""" Test if a certain line is a heading or not.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
line (str): the line to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int or None: level of heading or None if line is not heading
|
||||||
|
"""
|
||||||
|
# TODO would it make sense to return 0 for heading level?
|
||||||
|
# TODO add tests e.g. '*** abc', '**', '', '* ', '*\t', '*'
|
||||||
|
for i, item in enumerate(line):
|
||||||
|
if item == '*':
|
||||||
|
continue
|
||||||
|
elif i and item in ('\t', ' '):
|
||||||
|
return i
|
||||||
|
break
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty(self):
|
||||||
|
u""" Return True if the heading's body is marked dirty """
|
||||||
|
return self._dirty_heading or self._dirty_body
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_dirty_heading(self):
|
||||||
|
u""" Return True if the heading is marked dirty """
|
||||||
|
return self._dirty_heading
|
||||||
|
|
||||||
|
def get_index_in_parent_list(self):
|
||||||
|
""" Retrieve the index value of current heading in the parents list of
|
||||||
|
headings. This works also for top level headings.
|
||||||
|
|
||||||
|
:returns: Index value or None if heading doesn't have a
|
||||||
|
parent/document or is not in the list of headings
|
||||||
|
"""
|
||||||
|
if self.parent:
|
||||||
|
return super(Heading, self).get_index_in_parent_list()
|
||||||
|
elif self.document:
|
||||||
|
l = self.get_parent_list()
|
||||||
|
if l:
|
||||||
|
return l.index(self)
|
||||||
|
|
||||||
|
def get_parent_list(self):
|
||||||
|
""" Retrieve the parents' list of headings. This works also for top
|
||||||
|
level headings.
|
||||||
|
|
||||||
|
:returns: List of headings or None if heading doesn't have a
|
||||||
|
parent/document or is not in the list of headings
|
||||||
|
"""
|
||||||
|
if self.parent:
|
||||||
|
return super(Heading, self).get_parent_list()
|
||||||
|
elif self.document:
|
||||||
|
if self in self.document.headings:
|
||||||
|
return self.document.headings
|
||||||
|
|
||||||
|
def set_dirty(self):
|
||||||
|
u""" Mark the heading and body dirty so that it will be rewritten when
|
||||||
|
saving the document """
|
||||||
|
self._dirty_heading = True
|
||||||
|
self._dirty_body = True
|
||||||
|
if self._document:
|
||||||
|
self._document.set_dirty_document()
|
||||||
|
|
||||||
|
def set_dirty_heading(self):
|
||||||
|
u""" Mark the heading dirty so that it will be rewritten when saving the
|
||||||
|
document """
|
||||||
|
self._dirty_heading = True
|
||||||
|
if self._document:
|
||||||
|
self._document.set_dirty_document()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def previous_heading(self):
|
||||||
|
u""" Serialized access to the previous heading """
|
||||||
|
return super(Heading, self).previous_item
|
||||||
|
|
||||||
|
@property
|
||||||
|
def next_heading(self):
|
||||||
|
u""" Serialized access to the next heading """
|
||||||
|
return super(Heading, self).next_item
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start(self):
|
||||||
|
u""" Access to the starting line of the heading """
|
||||||
|
if self.document is None or not self.document.is_dirty:
|
||||||
|
return self._orig_start
|
||||||
|
|
||||||
|
meta_len = len(self.document.meta_information) if \
|
||||||
|
self.document.meta_information else 0
|
||||||
|
return super(Heading, self).start + meta_len
|
||||||
|
|
||||||
|
@DomObj.level.setter
|
||||||
|
def level(self, value):
|
||||||
|
u""" Set the heading level and mark the heading and the document dirty """
|
||||||
|
self._level = int(value)
|
||||||
|
self.set_dirty_heading()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def todo(self):
|
||||||
|
u""" Todo state of current heading. When todo state is set"""
|
||||||
|
# extract todo state from heading
|
||||||
|
return self._todo
|
||||||
|
|
||||||
|
@todo.setter
|
||||||
|
def todo(self, value):
|
||||||
|
# update todo state
|
||||||
|
if type(value) not in (unicode, str, type(None)):
|
||||||
|
raise ValueError(u'Todo state must be a string or None.')
|
||||||
|
if value and not REGEX_TODO.match(value):
|
||||||
|
raise ValueError(u'Found non allowed character in todo state! %s' % value)
|
||||||
|
if not value:
|
||||||
|
self._todo = None
|
||||||
|
else:
|
||||||
|
v = value
|
||||||
|
if type(v) == str:
|
||||||
|
v = u_decode(v)
|
||||||
|
self._todo = v
|
||||||
|
self.set_dirty_heading()
|
||||||
|
|
||||||
|
@todo.deleter
|
||||||
|
def todo(self):
|
||||||
|
self.todo = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def active_date(self):
|
||||||
|
u"""
|
||||||
|
active date of the hearing.
|
||||||
|
|
||||||
|
active dates are used in the agenda view. they can be part of the
|
||||||
|
heading and/or the body.
|
||||||
|
"""
|
||||||
|
return self._active_date
|
||||||
|
|
||||||
|
@active_date.setter
|
||||||
|
def active_date(self, value):
|
||||||
|
self._active_date = value
|
||||||
|
|
||||||
|
@active_date.deleter
|
||||||
|
def active_date(self):
|
||||||
|
self._active_date = None
|
||||||
|
|
||||||
|
@DomObj.title.setter
|
||||||
|
def title(self, value):
|
||||||
|
u""" Set the title and mark the document and the heading dirty """
|
||||||
|
# TODO these setter should be rewriten to also reuse code from DOM OBJ
|
||||||
|
if type(value) not in (unicode, str):
|
||||||
|
raise ValueError(u'Title must be a string.')
|
||||||
|
v = value
|
||||||
|
if type(v) == str:
|
||||||
|
v = u_decode(v)
|
||||||
|
self._title = v.strip()
|
||||||
|
self.set_dirty_heading()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tags(self):
|
||||||
|
u""" Tags of the current heading """
|
||||||
|
return self._tags
|
||||||
|
|
||||||
|
@tags.setter
|
||||||
|
def tags(self, value):
|
||||||
|
v = value
|
||||||
|
if type(v) in (unicode, str):
|
||||||
|
v = list(unicode(v))
|
||||||
|
if type(v) not in (list, tuple) and not isinstance(v, UserList):
|
||||||
|
v = list(unicode(v))
|
||||||
|
v = flatten_list(v)
|
||||||
|
v_decoded = []
|
||||||
|
for i in v:
|
||||||
|
if type(i) not in (unicode, str):
|
||||||
|
raise ValueError(u'Found non string value in tags! %s' % unicode(i))
|
||||||
|
if u':' in i:
|
||||||
|
raise ValueError(u'Found non allowed character in tag! %s' % i)
|
||||||
|
i_tmp = i.strip().replace(' ', '_').replace('\t', '_')
|
||||||
|
if type(i) == str:
|
||||||
|
i_tmp = u_decode(i)
|
||||||
|
v_decoded.append(i_tmp)
|
||||||
|
|
||||||
|
self._tags[:] = v_decoded
|
||||||
|
|
||||||
|
@tags.deleter
|
||||||
|
def tags(self):
|
||||||
|
self.tags = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def checkboxes(self):
|
||||||
|
u""" All checkboxes in current heading """
|
||||||
|
return self._checkboxes
|
||||||
|
|
||||||
|
@checkboxes.setter
|
||||||
|
def checkboxes(self, value):
|
||||||
|
self._checkboxes[:] = value
|
||||||
|
|
||||||
|
@checkboxes.deleter
|
||||||
|
def checkboxes(self):
|
||||||
|
del self.checkboxes[:]
|
||||||
|
|
||||||
|
|
||||||
|
class HeadingList(DomObjList):
|
||||||
|
u"""
|
||||||
|
A Heading List just contains headings. It's used for documents to store top
|
||||||
|
level headings and for headings to store subheadings.
|
||||||
|
|
||||||
|
A Heading List must be linked to a Document or Heading!
|
||||||
|
|
||||||
|
See documenatation of MultiPurposeList for more information.
|
||||||
|
"""
|
||||||
|
def __init__(self, initlist=None, obj=None):
|
||||||
|
"""
|
||||||
|
:initlist: Initial data
|
||||||
|
:obj: Link to a concrete Heading or Document object
|
||||||
|
"""
|
||||||
|
# it's not necessary to register a on_change hook because the heading
|
||||||
|
# list will itself take care of marking headings dirty or adding
|
||||||
|
# headings to the deleted headings list
|
||||||
|
DomObjList.__init__(self, initlist, obj)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_heading(cls, obj):
|
||||||
|
# TODO no need to make this or is_domobj a class methods
|
||||||
|
return HeadingList.is_domobj(obj)
|
||||||
|
|
||||||
|
def _get_document(self):
|
||||||
|
if self.__class__.is_heading(self._obj):
|
||||||
|
return self._obj._document
|
||||||
|
return self._obj
|
||||||
|
|
||||||
|
def _add_to_deleted_headings(self, item):
|
||||||
|
u"""
|
||||||
|
Serialize headings so that all subheadings are also marked for deletion
|
||||||
|
"""
|
||||||
|
if not self._get_document():
|
||||||
|
# HeadingList has not yet been associated
|
||||||
|
return
|
||||||
|
|
||||||
|
if type(item) in (list, tuple) or isinstance(item, UserList):
|
||||||
|
for i in flatten_list(item):
|
||||||
|
self._add_to_deleted_headings(i)
|
||||||
|
else:
|
||||||
|
self._get_document()._deleted_headings.append(
|
||||||
|
item.copy(including_children=False))
|
||||||
|
self._add_to_deleted_headings(item.children)
|
||||||
|
self._get_document().set_dirty_document()
|
||||||
|
|
||||||
|
def _associate_heading(
|
||||||
|
self, heading, previous_sibling, next_sibling,
|
||||||
|
children=False, taint=True):
|
||||||
|
"""
|
||||||
|
:heading: The heading or list to associate with the current heading
|
||||||
|
:previous_sibling: The previous sibling of the current heading. If
|
||||||
|
heading is a list the first heading will be
|
||||||
|
connected with the previous sibling and the last
|
||||||
|
heading with the next sibling. The items in between
|
||||||
|
will be linked with one another.
|
||||||
|
:next_sibling: The next sibling of the current heading. If
|
||||||
|
heading is a list the first heading will be
|
||||||
|
connected with the previous sibling and the last
|
||||||
|
heading with the next sibling. The items in between
|
||||||
|
will be linked with one another.
|
||||||
|
:children: Marks whether children are processed in the current
|
||||||
|
iteration or not (should not be use, it's set
|
||||||
|
automatically)
|
||||||
|
:taint: If not True, the heading is not marked dirty at the end
|
||||||
|
of the association process and its orig_start and
|
||||||
|
orig_len values are not updated.
|
||||||
|
"""
|
||||||
|
# TODO this method should be externalized and moved to the Heading class
|
||||||
|
# TODO should this method work with slice?
|
||||||
|
if type(heading) in (list, tuple) or isinstance(heading, UserList):
|
||||||
|
prev = previous_sibling
|
||||||
|
current = None
|
||||||
|
for _next in flatten_list(heading):
|
||||||
|
if current:
|
||||||
|
self._associate_heading(
|
||||||
|
current, prev, _next,
|
||||||
|
children=children, taint=taint)
|
||||||
|
prev = current
|
||||||
|
current = _next
|
||||||
|
if current:
|
||||||
|
self._associate_heading(
|
||||||
|
current, prev, next_sibling,
|
||||||
|
children=children, taint=taint)
|
||||||
|
else:
|
||||||
|
if taint:
|
||||||
|
heading._orig_start = None
|
||||||
|
heading._orig_len = None
|
||||||
|
d = self._get_document()
|
||||||
|
if heading._document != d:
|
||||||
|
heading._document = d
|
||||||
|
if not children:
|
||||||
|
# connect heading with previous and next headings
|
||||||
|
heading._previous_sibling = previous_sibling
|
||||||
|
if previous_sibling:
|
||||||
|
previous_sibling._next_sibling = heading
|
||||||
|
heading._next_sibling = next_sibling
|
||||||
|
if next_sibling:
|
||||||
|
next_sibling._previous_sibling = heading
|
||||||
|
|
||||||
|
if d == self._obj:
|
||||||
|
# self._obj is a Document
|
||||||
|
heading._parent = None
|
||||||
|
elif heading._parent != self._obj:
|
||||||
|
# self._obj is a Heading
|
||||||
|
heading._parent = self._obj
|
||||||
|
if taint:
|
||||||
|
heading.set_dirty()
|
||||||
|
|
||||||
|
self._associate_heading(
|
||||||
|
heading.children, None, None,
|
||||||
|
children=True, taint=taint)
|
||||||
|
|
||||||
|
def __setitem__(self, i, item):
|
||||||
|
if isinstance(i, slice):
|
||||||
|
start, stop, step = i.indices(len(self))
|
||||||
|
items = item
|
||||||
|
if self.__class__.is_heading(items):
|
||||||
|
items = (items, )
|
||||||
|
items = flatten_list(items)
|
||||||
|
for head in items:
|
||||||
|
if not self.__class__.is_heading(head):
|
||||||
|
raise ValueError(u'List contains items that are not a heading!')
|
||||||
|
|
||||||
|
self._add_to_deleted_headings(self[i])
|
||||||
|
self._associate_heading(
|
||||||
|
items,
|
||||||
|
self[start - 1] if start - 1 >= 0 else None,
|
||||||
|
self[stop] if stop < len(self) else None)
|
||||||
|
MultiPurposeList.__setitem__(self, i, items)
|
||||||
|
else:
|
||||||
|
if not self.__class__.is_heading(item):
|
||||||
|
raise ValueError(u'Item is not a heading!')
|
||||||
|
if item in self:
|
||||||
|
raise ValueError(u'Heading is already part of this list!')
|
||||||
|
self._add_to_deleted_headings(self[i])
|
||||||
|
self._associate_heading(
|
||||||
|
item,
|
||||||
|
self[i - 1] if i - 1 >= 0 else None,
|
||||||
|
self[i + 1] if i + 1 < len(self) else None)
|
||||||
|
MultiPurposeList.__setitem__(self, i, item)
|
||||||
|
|
||||||
|
def __delitem__(self, i, taint=True):
|
||||||
|
# TODO refactor this item, it works the same in dom_obj except taint?
|
||||||
|
if isinstance(i, slice):
|
||||||
|
items = self[i]
|
||||||
|
if items:
|
||||||
|
first = items[0]
|
||||||
|
last = items[-1]
|
||||||
|
if first.previous_sibling:
|
||||||
|
first.previous_sibling._next_sibling = last.next_sibling
|
||||||
|
if last.next_sibling:
|
||||||
|
last.next_sibling._previous_sibling = first.previous_sibling
|
||||||
|
if taint:
|
||||||
|
self._add_to_deleted_headings(items)
|
||||||
|
MultiPurposeList.__delitem__(self, i)
|
||||||
|
else:
|
||||||
|
item = self[i]
|
||||||
|
if item.previous_sibling:
|
||||||
|
item.previous_sibling._next_sibling = item.next_sibling
|
||||||
|
if item.next_sibling:
|
||||||
|
item.next_sibling._previous_sibling = item.previous_sibling
|
||||||
|
|
||||||
|
if taint:
|
||||||
|
self._add_to_deleted_headings(item)
|
||||||
|
MultiPurposeList.__delitem__(self, i)
|
||||||
|
|
||||||
|
def __iadd__(self, other):
|
||||||
|
o = other
|
||||||
|
if self.__class__.is_heading(o):
|
||||||
|
o = (o, )
|
||||||
|
for item in flatten_list(o):
|
||||||
|
if not self.__class__.is_heading(item):
|
||||||
|
raise ValueError(u'List contains items that are not a heading!')
|
||||||
|
self._associate_heading(o, self[-1] if len(self) > 0 else None, None)
|
||||||
|
return MultiPurposeList.__iadd__(self, o)
|
||||||
|
|
||||||
|
def append(self, item, taint=True):
|
||||||
|
if not self.__class__.is_heading(item):
|
||||||
|
raise ValueError(u'Item is not a heading!')
|
||||||
|
if item in self:
|
||||||
|
raise ValueError(u'Heading is already part of this list!')
|
||||||
|
self._associate_heading(
|
||||||
|
item, self[-1] if len(self) > 0 else None,
|
||||||
|
None, taint=taint)
|
||||||
|
MultiPurposeList.append(self, item)
|
||||||
|
|
||||||
|
def insert(self, i, item, taint=True):
|
||||||
|
self._associate_heading(
|
||||||
|
item,
|
||||||
|
self[i - 1] if i - 1 >= 0 and i - 1 < len(self) else None,
|
||||||
|
self[i] if i >= 0 and i < len(self) else None, taint=taint)
|
||||||
|
MultiPurposeList.insert(self, i, item)
|
||||||
|
|
||||||
|
def pop(self, i=-1):
|
||||||
|
item = self[i]
|
||||||
|
self._add_to_deleted_headings(item)
|
||||||
|
del self[i]
|
||||||
|
return item
|
||||||
|
|
||||||
|
def extend(self, other):
|
||||||
|
o = other
|
||||||
|
if self.__class__.is_heading(o):
|
||||||
|
o = (o, )
|
||||||
|
for item in o:
|
||||||
|
if not self.__class__.is_heading(item):
|
||||||
|
raise ValueError(u'List contains items that are not a heading!')
|
||||||
|
self._associate_heading(o, self[-1] if len(self) > 0 else None, None)
|
||||||
|
MultiPurposeList.extend(self, o)
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,296 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
u"""
|
||||||
|
OrgDate
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This module contains all date/time/timerange representations that exist in
|
||||||
|
orgmode.
|
||||||
|
|
||||||
|
There exist three different kinds:
|
||||||
|
|
||||||
|
* OrgDate: is similar to a date object in python and it looks like
|
||||||
|
'2011-09-07 Wed'.
|
||||||
|
|
||||||
|
* OrgDateTime: is similar to a datetime object in python and looks like
|
||||||
|
'2011-09-07 Wed 10:30'
|
||||||
|
|
||||||
|
* OrgTimeRange: indicates a range of time. It has a start and and end date:
|
||||||
|
* <2011-09-07 Wed>--<2011-09-08 Fri>
|
||||||
|
* <2011-09-07 Wed 10:00-13:00>
|
||||||
|
|
||||||
|
All OrgTime oblects can be active or inactive.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
# <2011-09-12 Mon>
|
||||||
|
_DATE_REGEX = re.compile(r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w>", re.UNICODE)
|
||||||
|
# [2011-09-12 Mon]
|
||||||
|
_DATE_PASSIVE_REGEX = re.compile(r"\[(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w\]", re.UNICODE)
|
||||||
|
|
||||||
|
# <2011-09-12 Mon 10:20>
|
||||||
|
_DATETIME_REGEX = re.compile(
|
||||||
|
r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d{1,2}):(\d\d)>", re.UNICODE)
|
||||||
|
# [2011-09-12 Mon 10:20]
|
||||||
|
_DATETIME_PASSIVE_REGEX = re.compile(
|
||||||
|
r"\[(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d{1,2}):(\d\d)\]", re.UNICODE)
|
||||||
|
|
||||||
|
# <2011-09-12 Mon>--<2011-09-13 Tue>
|
||||||
|
_DATERANGE_REGEX = re.compile(
|
||||||
|
# <2011-09-12 Mon>--
|
||||||
|
r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w>--"
|
||||||
|
# <2011-09-13 Tue>
|
||||||
|
"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w>", re.UNICODE)
|
||||||
|
# <2011-09-12 Mon 10:00>--<2011-09-12 Mon 11:00>
|
||||||
|
_DATETIMERANGE_REGEX = re.compile(
|
||||||
|
# <2011-09-12 Mon 10:00>--
|
||||||
|
r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d\d):(\d\d)>--"
|
||||||
|
# <2011-09-12 Mon 11:00>
|
||||||
|
"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d\d):(\d\d)>", re.UNICODE)
|
||||||
|
# <2011-09-12 Mon 10:00--12:00>
|
||||||
|
_DATETIMERANGE_SAME_DAY_REGEX = re.compile(
|
||||||
|
r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d\d):(\d\d)-(\d\d):(\d\d)>", re.UNICODE)
|
||||||
|
|
||||||
|
|
||||||
|
def get_orgdate(data):
|
||||||
|
u"""
|
||||||
|
Parse the given data (can be a string or list). Return an OrgDate if data
|
||||||
|
contains a string representation of an OrgDate; otherwise return None.
|
||||||
|
|
||||||
|
data can be a string or a list containing strings.
|
||||||
|
"""
|
||||||
|
# TODO maybe it should be checked just for iterable? Does it affect here if
|
||||||
|
# in base __getitem__(slice(i,j)) doesn't return a list but userlist...
|
||||||
|
if isinstance(data, list):
|
||||||
|
return _findfirst(_text2orgdate, data)
|
||||||
|
else:
|
||||||
|
return _text2orgdate(data)
|
||||||
|
# if no dates found
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _findfirst(f, seq):
|
||||||
|
u"""
|
||||||
|
Return first item in sequence seq where f(item) == True.
|
||||||
|
|
||||||
|
TODO: this is a general help function and it should be moved somewhere
|
||||||
|
else; preferably into the standard lib :)
|
||||||
|
"""
|
||||||
|
for found in (f(item) for item in seq if f(item)):
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def _text2orgdate(string):
|
||||||
|
u"""
|
||||||
|
Transform the given string into an OrgDate.
|
||||||
|
Return an OrgDate if data contains a string representation of an OrgDate;
|
||||||
|
otherwise return None.
|
||||||
|
"""
|
||||||
|
# handle active datetime with same day
|
||||||
|
result = _DATETIMERANGE_SAME_DAY_REGEX.search(string)
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
(syear, smonth, sday, shour, smin, ehour, emin) = \
|
||||||
|
[int(m) for m in result.groups()]
|
||||||
|
start = datetime.datetime(syear, smonth, sday, shour, smin)
|
||||||
|
end = datetime.datetime(syear, smonth, sday, ehour, emin)
|
||||||
|
return OrgTimeRange(True, start, end)
|
||||||
|
except BaseException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# handle active datetime
|
||||||
|
result = _DATETIMERANGE_REGEX.search(string)
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
tmp = [int(m) for m in result.groups()]
|
||||||
|
(syear, smonth, sday, shour, smin, eyear, emonth, eday, ehour, emin) = tmp
|
||||||
|
start = datetime.datetime(syear, smonth, sday, shour, smin)
|
||||||
|
end = datetime.datetime(eyear, emonth, eday, ehour, emin)
|
||||||
|
return OrgTimeRange(True, start, end)
|
||||||
|
except BaseException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# handle active datetime
|
||||||
|
result = _DATERANGE_REGEX.search(string)
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
tmp = [int(m) for m in result.groups()]
|
||||||
|
syear, smonth, sday, eyear, emonth, ehour = tmp
|
||||||
|
start = datetime.date(syear, smonth, sday)
|
||||||
|
end = datetime.date(eyear, emonth, ehour)
|
||||||
|
return OrgTimeRange(True, start, end)
|
||||||
|
except BaseException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# handle active datetime
|
||||||
|
result = _DATETIME_REGEX.search(string)
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
year, month, day, hour, minutes = [int(m) for m in result.groups()]
|
||||||
|
return OrgDateTime(True, year, month, day, hour, minutes)
|
||||||
|
except BaseException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# handle passive datetime
|
||||||
|
result = _DATETIME_PASSIVE_REGEX.search(string)
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
year, month, day, hour, minutes = [int(m) for m in result.groups()]
|
||||||
|
return OrgDateTime(False, year, month, day, hour, minutes)
|
||||||
|
except BaseException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# handle passive dates
|
||||||
|
result = _DATE_PASSIVE_REGEX.search(string)
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
year, month, day = [int(m) for m in result.groups()]
|
||||||
|
return OrgDate(False, year, month, day)
|
||||||
|
except BaseException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# handle active dates
|
||||||
|
result = _DATE_REGEX.search(string)
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
year, month, day = [int(m) for m in result.groups()]
|
||||||
|
return OrgDate(True, year, month, day)
|
||||||
|
except BaseException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class OrgDate(datetime.date):
|
||||||
|
u"""
|
||||||
|
OrgDate represents a normal date like '2011-08-29 Mon'.
|
||||||
|
|
||||||
|
OrgDates can be active or inactive.
|
||||||
|
|
||||||
|
NOTE: date is immutable. Thats why there needs to be __new__().
|
||||||
|
See: http://docs.python.org/reference/datamodel.html#object.__new__
|
||||||
|
"""
|
||||||
|
def __init__(self, active, year, month, day):
|
||||||
|
self.active = active
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __new__(cls, active, year, month, day):
|
||||||
|
return datetime.date.__new__(cls, year, month, day)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
u"""
|
||||||
|
Return a string representation.
|
||||||
|
"""
|
||||||
|
if self.active:
|
||||||
|
return self.strftime(u'<%Y-%m-%d %a>')
|
||||||
|
else:
|
||||||
|
return self.strftime(u'[%Y-%m-%d %a]')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def strftime(self, fmt):
|
||||||
|
return u_decode(datetime.date.strftime(self, u_encode(fmt)))
|
||||||
|
|
||||||
|
|
||||||
|
class OrgDateTime(datetime.datetime):
|
||||||
|
u"""
|
||||||
|
OrgDateTime represents a normal date like '2011-08-29 Mon'.
|
||||||
|
|
||||||
|
OrgDateTime can be active or inactive.
|
||||||
|
|
||||||
|
NOTE: date is immutable. Thats why there needs to be __new__().
|
||||||
|
See: http://docs.python.org/reference/datamodel.html#object.__new__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, active, year, month, day, hour, mins):
|
||||||
|
self.active = active
|
||||||
|
|
||||||
|
def __new__(cls, active, year, month, day, hour, minute):
|
||||||
|
return datetime.datetime.__new__(cls, year, month, day, hour, minute)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
u"""
|
||||||
|
Return a string representation.
|
||||||
|
"""
|
||||||
|
if self.active:
|
||||||
|
return self.strftime(u'<%Y-%m-%d %a %H:%M>')
|
||||||
|
else:
|
||||||
|
return self.strftime(u'[%Y-%m-%d %a %H:%M]')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def strftime(self, fmt):
|
||||||
|
return u_decode(datetime.datetime.strftime(self, u_encode(fmt)))
|
||||||
|
|
||||||
|
|
||||||
|
class OrgTimeRange(object):
|
||||||
|
u"""
|
||||||
|
OrgTimeRange objects have a start and an end. Start and ent can be date
|
||||||
|
or datetime. Start and end have to be the same type.
|
||||||
|
|
||||||
|
OrgTimeRange objects look like this:
|
||||||
|
* <2011-09-07 Wed>--<2011-09-08 Fri>
|
||||||
|
* <2011-09-07 Wed 20:00>--<2011-09-08 Fri 10:00>
|
||||||
|
* <2011-09-07 Wed 10:00-13:00>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, active, start, end):
|
||||||
|
u"""
|
||||||
|
stat and end must be datetime.date or datetime.datetime (both of the
|
||||||
|
same type).
|
||||||
|
"""
|
||||||
|
super(OrgTimeRange, self).__init__()
|
||||||
|
self.start = start
|
||||||
|
self.end = end
|
||||||
|
self.active = active
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
u"""
|
||||||
|
Return a string representation.
|
||||||
|
"""
|
||||||
|
# active
|
||||||
|
if self.active:
|
||||||
|
# datetime
|
||||||
|
if isinstance(self.start, datetime.datetime):
|
||||||
|
# if start and end are on same the day
|
||||||
|
if self.start.year == self.end.year and\
|
||||||
|
self.start.month == self.end.month and\
|
||||||
|
self.start.day == self.end.day:
|
||||||
|
return u"<%s-%s>" % (
|
||||||
|
self.start.strftime(u'%Y-%m-%d %a %H:%M'),
|
||||||
|
self.end.strftime(u'%H:%M'))
|
||||||
|
else:
|
||||||
|
return u"<%s>--<%s>" % (
|
||||||
|
self.start.strftime(u'%Y-%m-%d %a %H:%M'),
|
||||||
|
self.end.strftime(u'%Y-%m-%d %a %H:%M'))
|
||||||
|
# date
|
||||||
|
if isinstance(self.start, datetime.date):
|
||||||
|
return u"<%s>--<%s>" % (
|
||||||
|
self.start.strftime(u'%Y-%m-%d %a'),
|
||||||
|
self.end.strftime(u'%Y-%m-%d %a'))
|
||||||
|
# inactive
|
||||||
|
else:
|
||||||
|
if isinstance(self.start, datetime.datetime):
|
||||||
|
# if start and end are on same the day
|
||||||
|
if self.start.year == self.end.year and\
|
||||||
|
self.start.month == self.end.month and\
|
||||||
|
self.start.day == self.end.day:
|
||||||
|
return u"[%s-%s]" % (
|
||||||
|
self.start.strftime(u'%Y-%m-%d %a %H:%M'),
|
||||||
|
self.end.strftime(u'%H:%M'))
|
||||||
|
else:
|
||||||
|
return u"[%s]--[%s]" % (
|
||||||
|
self.start.strftime(u'%Y-%m-%d %a %H:%M'),
|
||||||
|
self.end.strftime(u'%Y-%m-%d %a %H:%M'))
|
||||||
|
if isinstance(self.start, datetime.date):
|
||||||
|
return u"[%s]--[%s]" % (
|
||||||
|
self.start.strftime(u'%Y-%m-%d %a'),
|
||||||
|
self.end.strftime(u'%Y-%m-%d %a'))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
173
pack/acp/start/vim-orgmode/ftplugin/orgmode/menu.py
Normal file
173
pack/acp/start/vim-orgmode/ftplugin/orgmode/menu.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode.keybinding import Command, Plug, Keybinding
|
||||||
|
from orgmode.keybinding import MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
def register_menu(f):
|
||||||
|
def r(*args, **kwargs):
|
||||||
|
p = f(*args, **kwargs)
|
||||||
|
def create(entry):
|
||||||
|
if isinstance(entry, Submenu) or isinstance(entry, Separator) \
|
||||||
|
or isinstance(entry, ActionEntry):
|
||||||
|
entry.create()
|
||||||
|
|
||||||
|
if hasattr(p, u'menu'):
|
||||||
|
if isinstance(p.menu, list) or isinstance(p.menu, tuple):
|
||||||
|
for e in p.menu:
|
||||||
|
create(e)
|
||||||
|
else:
|
||||||
|
create(p.menu)
|
||||||
|
return p
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def add_cmd_mapping_menu(plugin, name, function, key_mapping, menu_desrc):
|
||||||
|
u"""A helper function to create a vim command and keybinding and add these
|
||||||
|
to the menu for a given plugin.
|
||||||
|
|
||||||
|
:plugin: the plugin to operate on.
|
||||||
|
:name: the name of the vim command (and the name of the Plug)
|
||||||
|
:function: the actual python function which is called when executing the
|
||||||
|
vim command.
|
||||||
|
:key_mapping: the keymapping to execute the command.
|
||||||
|
:menu_desrc: the text which appears in the menu.
|
||||||
|
"""
|
||||||
|
cmd = Command(name, function)
|
||||||
|
keybinding = Keybinding(key_mapping, Plug(name, cmd))
|
||||||
|
|
||||||
|
plugin.commands.append(cmd)
|
||||||
|
plugin.keybindings.append(keybinding)
|
||||||
|
plugin.menu + ActionEntry(menu_desrc, keybinding)
|
||||||
|
|
||||||
|
|
||||||
|
class Submenu(object):
|
||||||
|
u""" Submenu entry """
|
||||||
|
|
||||||
|
def __init__(self, name, parent=None):
|
||||||
|
object.__init__(self)
|
||||||
|
self.name = name
|
||||||
|
self.parent = parent
|
||||||
|
self._children = []
|
||||||
|
|
||||||
|
def __add__(self, entry):
|
||||||
|
if entry not in self._children:
|
||||||
|
self._children.append(entry)
|
||||||
|
entry.parent = self
|
||||||
|
return entry
|
||||||
|
|
||||||
|
def __sub__(self, entry):
|
||||||
|
if entry in self._children:
|
||||||
|
idx = self._children.index(entry)
|
||||||
|
del self._children[idx]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def children(self):
|
||||||
|
return self._children[:]
|
||||||
|
|
||||||
|
def get_menu(self):
|
||||||
|
n = self.name.replace(u' ', u'\\ ')
|
||||||
|
if self.parent:
|
||||||
|
return u'%s.%s' % (self.parent.get_menu(), n)
|
||||||
|
return n
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
for c in self.children:
|
||||||
|
c.create()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
res = self.name
|
||||||
|
for c in self.children:
|
||||||
|
res += str(c)
|
||||||
|
return res
|
||||||
|
|
||||||
|
class Separator(object):
|
||||||
|
u""" Menu entry for a Separator """
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
object.__init__(self)
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u'-----'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u_encode(self.__unicode__())
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
if self.parent:
|
||||||
|
menu = self.parent.get_menu()
|
||||||
|
vim.command(u_encode(u'menu %s.-%s- :' % (menu, id(self))))
|
||||||
|
|
||||||
|
class ActionEntry(object):
|
||||||
|
u""" ActionEntry entry """
|
||||||
|
|
||||||
|
def __init__(self, lname, action, rname=None, mode=MODE_NORMAL, parent=None):
|
||||||
|
u"""
|
||||||
|
:lname: menu title on the left hand side of the menu entry
|
||||||
|
:action: could be a vim command sequence or an actual Keybinding
|
||||||
|
:rname: menu title that appears on the right hand side of the menu
|
||||||
|
entry. If action is a Keybinding this value ignored and is
|
||||||
|
taken from the Keybinding
|
||||||
|
:mode: defines when the menu entry/action is executable
|
||||||
|
:parent: the parent instance of this object. The only valid parent is Submenu
|
||||||
|
"""
|
||||||
|
object.__init__(self)
|
||||||
|
self._lname = lname
|
||||||
|
self._action = action
|
||||||
|
self._rname = rname
|
||||||
|
if mode not in (MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT):
|
||||||
|
raise ValueError(u'Parameter mode not in MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT')
|
||||||
|
self._mode = mode
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return u'%s\t%s' % (self.lname, self.rname)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lname(self):
|
||||||
|
return self._lname.replace(u' ', u'\\ ')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def action(self):
|
||||||
|
if isinstance(self._action, Keybinding):
|
||||||
|
return self._action.action
|
||||||
|
return self._action
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rname(self):
|
||||||
|
if isinstance(self._action, Keybinding):
|
||||||
|
return self._action.key.replace(u'<Tab>', u'Tab')
|
||||||
|
return self._rname
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode(self):
|
||||||
|
if isinstance(self._action, Keybinding):
|
||||||
|
return self._action.mode
|
||||||
|
return self._mode
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
menucmd = u':%smenu ' % self.mode
|
||||||
|
menu = u''
|
||||||
|
cmd = u''
|
||||||
|
|
||||||
|
if self.parent:
|
||||||
|
menu = self.parent.get_menu()
|
||||||
|
menu += u'.%s' % self.lname
|
||||||
|
|
||||||
|
if self.rname:
|
||||||
|
cmd = u'%s %s<Tab>%s %s' % (menucmd, menu, self.rname, self.action)
|
||||||
|
else:
|
||||||
|
cmd = u'%s %s %s' % (menucmd, menu, self.action)
|
||||||
|
|
||||||
|
vim.command(u_encode(cmd))
|
||||||
|
|
||||||
|
# keybindings should be stored in the plugin.keybindings property and be registered by the appropriate keybinding registrar
|
||||||
|
#if isinstance(self._action, Keybinding):
|
||||||
|
# self._action.create()
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
314
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Agenda.py
Normal file
314
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Agenda.py
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE, get_bufnumber, get_bufname, echoe
|
||||||
|
from orgmode import settings
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, Command
|
||||||
|
from orgmode.menu import Submenu, ActionEntry, add_cmd_mapping_menu
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class Agenda(object):
|
||||||
|
u"""
|
||||||
|
The Agenda Plugin uses liborgmode.agenda to display the agenda views.
|
||||||
|
|
||||||
|
The main task is to format the agenda from liborgmode.agenda.
|
||||||
|
Also all the mappings: jump from agenda to todo, etc are realized here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'Agenda')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _switch_to(cls, bufname, vim_commands=None):
|
||||||
|
u"""
|
||||||
|
Swicht to the buffer with bufname.
|
||||||
|
|
||||||
|
A list of vim.commands (if given) gets executed as well.
|
||||||
|
|
||||||
|
TODO: this should be extracted and imporved to create an easy to use
|
||||||
|
way to create buffers/jump to buffers. Otherwise there are going to be
|
||||||
|
quite a few ways to open buffers in vimorgmode.
|
||||||
|
"""
|
||||||
|
cmds = [
|
||||||
|
u'botright split org:%s' % bufname,
|
||||||
|
u'setlocal buftype=nofile',
|
||||||
|
u'setlocal modifiable',
|
||||||
|
u'setlocal nonumber',
|
||||||
|
# call opendoc() on enter the original todo item
|
||||||
|
u'nnoremap <silent> <buffer> <CR> :exec "%s ORGMODE.plugins[u\'Agenda\'].opendoc()"<CR>' % VIM_PY_CALL,
|
||||||
|
u'nnoremap <silent> <buffer> <TAB> :exec "%s ORGMODE.plugins[u\'Agenda\'].opendoc(switch=True)"<CR>' % VIM_PY_CALL,
|
||||||
|
u'nnoremap <silent> <buffer> <S-CR> :exec "%s ORGMODE.plugins[u\'Agenda\'].opendoc(split=True)"<CR>' % VIM_PY_CALL,
|
||||||
|
# statusline
|
||||||
|
u'setlocal statusline=Org\\ %s' % bufname]
|
||||||
|
if vim_commands:
|
||||||
|
cmds.extend(vim_commands)
|
||||||
|
for cmd in cmds:
|
||||||
|
vim.command(u_encode(cmd))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_agendadocuments(self):
|
||||||
|
u"""
|
||||||
|
Return the org documents of the agenda files; return None if no
|
||||||
|
agenda documents are defined.
|
||||||
|
|
||||||
|
TODO: maybe turn this into an decorator?
|
||||||
|
"""
|
||||||
|
# load org files of agenda
|
||||||
|
agenda_files = settings.get(u'org_agenda_files', u',')
|
||||||
|
if not agenda_files or agenda_files == ',':
|
||||||
|
echoe(
|
||||||
|
u"No org_agenda_files defined. Use :let "
|
||||||
|
u"g:org_agenda_files=['~/org/index.org'] to add "
|
||||||
|
u"files to the agenda view.")
|
||||||
|
return
|
||||||
|
return self._load_agendafiles(agenda_files)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _load_agendafiles(self, agenda_files):
|
||||||
|
# glob for files in agenda_files
|
||||||
|
resolved_files = []
|
||||||
|
for f in agenda_files:
|
||||||
|
f = glob.glob(os.path.join(
|
||||||
|
os.path.expanduser(os.path.dirname(f)),
|
||||||
|
os.path.basename(f)))
|
||||||
|
resolved_files.extend(f)
|
||||||
|
|
||||||
|
agenda_files = [os.path.realpath(f) for f in resolved_files]
|
||||||
|
|
||||||
|
# load the agenda files into buffers
|
||||||
|
for agenda_file in agenda_files:
|
||||||
|
vim.command(u_encode(u'badd %s' % agenda_file.replace(" ", "\ ")))
|
||||||
|
|
||||||
|
# determine the buffer nr of the agenda files
|
||||||
|
agenda_nums = [get_bufnumber(fn) for fn in agenda_files]
|
||||||
|
|
||||||
|
# collect all documents of the agenda files and create the agenda
|
||||||
|
return [ORGMODE.get_document(i) for i in agenda_nums if i is not None]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def opendoc(cls, split=False, switch=False):
|
||||||
|
u"""
|
||||||
|
If you are in the agenda view jump to the document the item in the
|
||||||
|
current line belongs to. cls.line2doc is used for that.
|
||||||
|
|
||||||
|
:split: if True, open the document in a new split window.
|
||||||
|
:switch: if True, switch to another window and open the the document
|
||||||
|
there.
|
||||||
|
"""
|
||||||
|
row, _ = vim.current.window.cursor
|
||||||
|
try:
|
||||||
|
bufname, bufnr, destrow = cls.line2doc[row]
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
# reload source file if it is not loaded
|
||||||
|
if get_bufname(bufnr) is None:
|
||||||
|
vim.command(u_encode(u'badd %s' % bufname))
|
||||||
|
bufnr = get_bufnumber(bufname)
|
||||||
|
tmp = cls.line2doc[row]
|
||||||
|
cls.line2doc[bufnr] = tmp
|
||||||
|
# delete old endry
|
||||||
|
del cls.line2doc[row]
|
||||||
|
|
||||||
|
if split:
|
||||||
|
vim.command(u_encode(u"sbuffer %s" % bufnr))
|
||||||
|
elif switch:
|
||||||
|
vim.command(u_encode(u"wincmd w"))
|
||||||
|
vim.command(u_encode(u"buffer %d" % bufnr))
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u"buffer %s" % bufnr))
|
||||||
|
vim.command(u_encode(u"normal! %dgg <CR>" % (destrow + 1)))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_next_week(cls):
|
||||||
|
agenda_documents = cls._get_agendadocuments()
|
||||||
|
if not agenda_documents:
|
||||||
|
return
|
||||||
|
cls.list_next_week_for(agenda_documents)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_next_week_for_buffer(cls):
|
||||||
|
agenda_documents = vim.current.buffer.name
|
||||||
|
loaded_agendafiles = cls._load_agendafiles([agenda_documents])
|
||||||
|
cls.list_next_week_for(loaded_agendafiles)
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_next_week_for(cls, agenda_documents):
|
||||||
|
raw_agenda = ORGMODE.agenda_manager.get_next_week_and_active_todo(
|
||||||
|
agenda_documents)
|
||||||
|
|
||||||
|
# if raw_agenda is empty, return directly
|
||||||
|
if not raw_agenda:
|
||||||
|
vim.command('echom "All caught-up. No agenda or active todo next week."')
|
||||||
|
return
|
||||||
|
|
||||||
|
# create buffer at bottom
|
||||||
|
cmd = [u'setlocal filetype=orgagenda', ]
|
||||||
|
cls._switch_to(u'AGENDA', cmd)
|
||||||
|
|
||||||
|
# line2doc is a dic with the mapping:
|
||||||
|
# line in agenda buffer --> source document
|
||||||
|
# It's easy to jump to the right document this way
|
||||||
|
cls.line2doc = {}
|
||||||
|
# format text for agenda
|
||||||
|
last_date = raw_agenda[0].active_date
|
||||||
|
final_agenda = [u'Week Agenda:', unicode(last_date)]
|
||||||
|
for i, h in enumerate(raw_agenda):
|
||||||
|
# insert date information for every new date (not datetime)
|
||||||
|
if unicode(h.active_date)[1:11] != unicode(last_date)[1:11]:
|
||||||
|
today = date.today()
|
||||||
|
# insert additional "TODAY" string
|
||||||
|
if h.active_date.year == today.year and \
|
||||||
|
h.active_date.month == today.month and \
|
||||||
|
h.active_date.day == today.day:
|
||||||
|
section = unicode(h.active_date) + u" TODAY"
|
||||||
|
today_row = len(final_agenda) + 1
|
||||||
|
else:
|
||||||
|
section = unicode(h.active_date)
|
||||||
|
final_agenda.append(section)
|
||||||
|
|
||||||
|
# update last_date
|
||||||
|
last_date = h.active_date
|
||||||
|
|
||||||
|
bufname = os.path.basename(vim.buffers[h.document.bufnr].name)
|
||||||
|
bufname = bufname[:-4] if bufname.endswith(u'.org') else bufname
|
||||||
|
formated = u" %(bufname)s (%(bufnr)d) %(todo)s %(title)s" % {
|
||||||
|
'bufname': bufname,
|
||||||
|
'bufnr': h.document.bufnr,
|
||||||
|
'todo': h.todo,
|
||||||
|
'title': h.title
|
||||||
|
}
|
||||||
|
final_agenda.append(formated)
|
||||||
|
cls.line2doc[len(final_agenda)] = (get_bufname(h.document.bufnr), h.document.bufnr, h.start)
|
||||||
|
|
||||||
|
# show agenda
|
||||||
|
vim.current.buffer[:] = [u_encode(i) for i in final_agenda]
|
||||||
|
vim.command(u_encode(u'setlocal nomodifiable conceallevel=2 concealcursor=nc'))
|
||||||
|
# try to jump to the positon of today
|
||||||
|
try:
|
||||||
|
vim.command(u_encode(u'normal! %sgg<CR>' % today_row))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_all_todos(cls, current_buffer=False):
|
||||||
|
u""" List all todos in one buffer.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
current_buffer (bool):
|
||||||
|
False: all agenda files
|
||||||
|
True: current org_file
|
||||||
|
"""
|
||||||
|
if current_buffer:
|
||||||
|
agenda_documents = vim.current.buffer.name
|
||||||
|
loaded_agendafiles = cls._load_agendafiles([agenda_documents])
|
||||||
|
else:
|
||||||
|
loaded_agendafiles = cls._get_agendadocuments()
|
||||||
|
if not loaded_agendafiles:
|
||||||
|
return
|
||||||
|
raw_agenda = ORGMODE.agenda_manager.get_todo(loaded_agendafiles)
|
||||||
|
|
||||||
|
cls.line2doc = {}
|
||||||
|
# create buffer at bottom
|
||||||
|
cmd = [u'setlocal filetype=orgagenda']
|
||||||
|
cls._switch_to(u'AGENDA', cmd)
|
||||||
|
|
||||||
|
# format text of agenda
|
||||||
|
final_agenda = []
|
||||||
|
for i, h in enumerate(raw_agenda):
|
||||||
|
tmp = u"%s %s" % (h.todo, h.title)
|
||||||
|
final_agenda.append(tmp)
|
||||||
|
cls.line2doc[len(final_agenda)] = (get_bufname(h.document.bufnr), h.document.bufnr, h.start)
|
||||||
|
|
||||||
|
# show agenda
|
||||||
|
vim.current.buffer[:] = [u_encode(i) for i in final_agenda]
|
||||||
|
vim.command(u_encode(u'setlocal nomodifiable conceallevel=2 concealcursor=nc'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_timeline(cls):
|
||||||
|
"""
|
||||||
|
List a timeline of the current buffer to get an overview of the
|
||||||
|
current file.
|
||||||
|
"""
|
||||||
|
raw_agenda = ORGMODE.agenda_manager.get_timestamped_items(
|
||||||
|
[ORGMODE.get_document()])
|
||||||
|
|
||||||
|
# create buffer at bottom
|
||||||
|
cmd = [u'setlocal filetype=orgagenda']
|
||||||
|
cls._switch_to(u'AGENDA', cmd)
|
||||||
|
|
||||||
|
cls.line2doc = {}
|
||||||
|
# format text of agenda
|
||||||
|
final_agenda = []
|
||||||
|
for i, h in enumerate(raw_agenda):
|
||||||
|
tmp = u"%s %s" % (h.todo, h.title)
|
||||||
|
final_agenda.append(tmp)
|
||||||
|
cls.line2doc[len(final_agenda)] = (get_bufname(h.document.bufnr), h.document.bufnr, h.start)
|
||||||
|
|
||||||
|
# show agenda
|
||||||
|
vim.current.buffer[:] = [u_encode(i) for i in final_agenda]
|
||||||
|
vim.command(u_encode(u'setlocal nomodifiable conceallevel=2 concealcursor=nc'))
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of the plugin.
|
||||||
|
|
||||||
|
Key bindings and other initialization should be done here.
|
||||||
|
"""
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u"OrgAgendaTodo",
|
||||||
|
function=u'%s ORGMODE.plugins[u"Agenda"].list_all_todos()' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>cat',
|
||||||
|
menu_desrc=u'Agenda for all TODOs'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u"OrgBufferAgendaTodo",
|
||||||
|
function=u'%s ORGMODE.plugins[u"Agenda"].list_all_todos(current_buffer=True)' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>caT',
|
||||||
|
menu_desrc=u'Agenda for all TODOs based on current buffer'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u"OrgAgendaWeek",
|
||||||
|
function=u'%s ORGMODE.plugins[u"Agenda"].list_next_week()' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>caa',
|
||||||
|
menu_desrc=u'Agenda for the week'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u"OrgBufferAgendaWeek",
|
||||||
|
function=u'%s ORGMODE.plugins[u"Agenda"].list_next_week_for_buffer()' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>caA',
|
||||||
|
menu_desrc=u'Agenda for the week based on current buffer'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgAgendaTimeline',
|
||||||
|
function=u'%s ORGMODE.plugins[u"Agenda"].list_timeline()' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>caL',
|
||||||
|
menu_desrc=u'Timeline for this buffer'
|
||||||
|
)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
318
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Date.py
Normal file
318
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Date.py
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
from datetime import timedelta, date, datetime
|
||||||
|
|
||||||
|
import operator
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE, echom, insert_at_cursor, get_user_input
|
||||||
|
from orgmode import settings
|
||||||
|
from orgmode.keybinding import Keybinding, Plug
|
||||||
|
from orgmode.menu import Submenu, ActionEntry, add_cmd_mapping_menu
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class Date(object):
|
||||||
|
u"""
|
||||||
|
Handles all date and timestamp related tasks.
|
||||||
|
|
||||||
|
TODO: extend functionality (calendar, repetitions, ranges). See
|
||||||
|
http://orgmode.org/guide/Dates-and-Times.html#Dates-and-Times
|
||||||
|
"""
|
||||||
|
|
||||||
|
date_regex = r"\d\d\d\d-\d\d-\d\d"
|
||||||
|
datetime_regex = r"[A-Z]\w\w \d\d\d\d-\d\d-\d\d \d\d:\d\d>"
|
||||||
|
|
||||||
|
month_mapping = {
|
||||||
|
u'jan': 1, u'feb': 2, u'mar': 3, u'apr': 4, u'may': 5,
|
||||||
|
u'jun': 6, u'jul': 7, u'aug': 8, u'sep': 9, u'oct': 10, u'nov': 11,
|
||||||
|
u'dec': 12}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'Dates and Scheduling')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
# set speeddating format that is compatible with orgmode
|
||||||
|
try:
|
||||||
|
if int(vim.eval(u_encode(u'exists(":SpeedDatingFormat")'))) == 2:
|
||||||
|
vim.command(u_encode(u':1SpeedDatingFormat %Y-%m-%d %a'))
|
||||||
|
vim.command(u_encode(u':1SpeedDatingFormat %Y-%m-%d %a %H:%M'))
|
||||||
|
else:
|
||||||
|
echom(u'Speeddating plugin not installed. Please install it.')
|
||||||
|
except:
|
||||||
|
echom(u'Speeddating plugin not installed. Please install it.')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _modify_time(cls, startdate, modifier):
|
||||||
|
u"""Modify the given startdate according to modifier. Return the new
|
||||||
|
date or datetime.
|
||||||
|
|
||||||
|
See http://orgmode.org/manual/The-date_002ftime-prompt.html
|
||||||
|
"""
|
||||||
|
if modifier is None or modifier == '' or modifier == '.':
|
||||||
|
return startdate
|
||||||
|
|
||||||
|
# rm crap from modifier
|
||||||
|
modifier = modifier.strip()
|
||||||
|
|
||||||
|
ops = {'-': operator.sub, '+': operator.add}
|
||||||
|
|
||||||
|
# check real date
|
||||||
|
date_regex = r"(\d\d\d\d)-(\d\d)-(\d\d)"
|
||||||
|
match = re.search(date_regex, modifier)
|
||||||
|
if match:
|
||||||
|
year, month, day = match.groups()
|
||||||
|
newdate = date(int(year), int(month), int(day))
|
||||||
|
|
||||||
|
# check abbreviated date, seperated with '-'
|
||||||
|
date_regex = u"(\d{1,2})-(\d+)-(\d+)"
|
||||||
|
match = re.search(date_regex, modifier)
|
||||||
|
if match:
|
||||||
|
year, month, day = match.groups()
|
||||||
|
newdate = date(2000 + int(year), int(month), int(day))
|
||||||
|
|
||||||
|
# check abbreviated date, seperated with '/'
|
||||||
|
# month/day
|
||||||
|
date_regex = u"(\d{1,2})/(\d{1,2})"
|
||||||
|
match = re.search(date_regex, modifier)
|
||||||
|
if match:
|
||||||
|
month, day = match.groups()
|
||||||
|
newdate = date(startdate.year, int(month), int(day))
|
||||||
|
# date should be always in the future
|
||||||
|
if newdate < startdate:
|
||||||
|
newdate = date(startdate.year + 1, int(month), int(day))
|
||||||
|
|
||||||
|
# check full date, seperated with 'space'
|
||||||
|
# month day year
|
||||||
|
# 'sep 12 9' --> 2009 9 12
|
||||||
|
date_regex = u"(\w\w\w) (\d{1,2}) (\d{1,2})"
|
||||||
|
match = re.search(date_regex, modifier)
|
||||||
|
if match:
|
||||||
|
gr = match.groups()
|
||||||
|
day = int(gr[1])
|
||||||
|
month = int(cls.month_mapping[gr[0]])
|
||||||
|
year = 2000 + int(gr[2])
|
||||||
|
newdate = date(year, int(month), int(day))
|
||||||
|
|
||||||
|
# check days as integers
|
||||||
|
date_regex = u"^(\d{1,2})$"
|
||||||
|
match = re.search(date_regex, modifier)
|
||||||
|
if match:
|
||||||
|
newday, = match.groups()
|
||||||
|
newday = int(newday)
|
||||||
|
if newday > startdate.day:
|
||||||
|
newdate = date(startdate.year, startdate.month, newday)
|
||||||
|
else:
|
||||||
|
# TODO: DIRTY, fix this
|
||||||
|
# this does NOT cover all edge cases
|
||||||
|
newdate = startdate + timedelta(days=28)
|
||||||
|
newdate = date(newdate.year, newdate.month, newday)
|
||||||
|
|
||||||
|
# check for full days: Mon, Tue, Wed, Thu, Fri, Sat, Sun
|
||||||
|
modifier_lc = modifier.lower()
|
||||||
|
match = re.search(u'mon|tue|wed|thu|fri|sat|sun', modifier_lc)
|
||||||
|
if match:
|
||||||
|
weekday_mapping = {
|
||||||
|
u'mon': 0, u'tue': 1, u'wed': 2, u'thu': 3,
|
||||||
|
u'fri': 4, u'sat': 5, u'sun': 6}
|
||||||
|
diff = (weekday_mapping[modifier_lc] - startdate.weekday()) % 7
|
||||||
|
# use next weeks weekday if current weekday is the same as modifier
|
||||||
|
if diff == 0:
|
||||||
|
diff = 7
|
||||||
|
newdate = startdate + timedelta(days=diff)
|
||||||
|
|
||||||
|
# check for days modifier with appended d
|
||||||
|
match = re.search(u'^(\+|-)(\d*)d', modifier)
|
||||||
|
if match:
|
||||||
|
op, days = match.groups()
|
||||||
|
newdate = ops[op](startdate, timedelta(days=int(days)))
|
||||||
|
|
||||||
|
# check for days modifier without appended d
|
||||||
|
match = re.search(u'^(\+|-)(\d*) |^(\+|-)(\d*)$', modifier)
|
||||||
|
if match:
|
||||||
|
groups = match.groups()
|
||||||
|
try:
|
||||||
|
op = groups[0]
|
||||||
|
days = int(groups[1])
|
||||||
|
except:
|
||||||
|
op = groups[2]
|
||||||
|
days = int(groups[3])
|
||||||
|
newdate = ops[op](startdate, timedelta(days=days))
|
||||||
|
|
||||||
|
# check for week modifier
|
||||||
|
match = re.search(u'^(\+|-)(\d+)w', modifier)
|
||||||
|
if match:
|
||||||
|
op, weeks = match.groups()
|
||||||
|
newdate = ops[op](startdate, timedelta(weeks=int(weeks)))
|
||||||
|
|
||||||
|
# check for month modifier
|
||||||
|
match = re.search(u'^(\+|-)(\d+)m', modifier)
|
||||||
|
if match:
|
||||||
|
op, months = match.groups()
|
||||||
|
newdate = date(startdate.year, ops[op](startdate.month, int(months)),
|
||||||
|
startdate.day)
|
||||||
|
|
||||||
|
# check for year modifier
|
||||||
|
match = re.search(u'^(\+|-)(\d*)y', modifier)
|
||||||
|
if match:
|
||||||
|
op, years = match.groups()
|
||||||
|
newdate = date(ops[op](startdate.year, int(years)), startdate.month,
|
||||||
|
startdate.day)
|
||||||
|
|
||||||
|
# check for month day
|
||||||
|
match = re.search(
|
||||||
|
u'(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) (\d{1,2})',
|
||||||
|
modifier.lower())
|
||||||
|
if match:
|
||||||
|
month = cls.month_mapping[match.groups()[0]]
|
||||||
|
day = int(match.groups()[1])
|
||||||
|
newdate = date(startdate.year, int(month), int(day))
|
||||||
|
# date should be always in the future
|
||||||
|
if newdate < startdate:
|
||||||
|
newdate = date(startdate.year + 1, int(month), int(day))
|
||||||
|
|
||||||
|
# check abbreviated date, seperated with '/'
|
||||||
|
# month/day/year
|
||||||
|
date_regex = u"(\d{1,2})/(\d+)/(\d+)"
|
||||||
|
match = re.search(date_regex, modifier)
|
||||||
|
if match:
|
||||||
|
month, day, year = match.groups()
|
||||||
|
newdate = date(2000 + int(year), int(month), int(day))
|
||||||
|
|
||||||
|
# check for month day year
|
||||||
|
# sep 12 2011
|
||||||
|
match = re.search(
|
||||||
|
u'(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) (\d{1,2}) (\d{1,4})',
|
||||||
|
modifier.lower())
|
||||||
|
if match:
|
||||||
|
month = int(cls.month_mapping[match.groups()[0]])
|
||||||
|
day = int(match.groups()[1])
|
||||||
|
if len(match.groups()[2]) < 4:
|
||||||
|
year = 2000 + int(match.groups()[2])
|
||||||
|
else:
|
||||||
|
year = int(match.groups()[2])
|
||||||
|
newdate = date(year, month, day)
|
||||||
|
|
||||||
|
# check for time: HH:MM
|
||||||
|
# '12:45' --> datetime(2006, 06, 13, 12, 45))
|
||||||
|
match = re.search(u'(\d{1,2}):(\d\d)$', modifier)
|
||||||
|
if match:
|
||||||
|
try:
|
||||||
|
startdate = newdate
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return datetime(
|
||||||
|
startdate.year, startdate.month, startdate.day,
|
||||||
|
int(match.groups()[0]), int(match.groups()[1]))
|
||||||
|
|
||||||
|
try:
|
||||||
|
return newdate
|
||||||
|
except:
|
||||||
|
return startdate
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def insert_timestamp(cls, active=True):
|
||||||
|
u"""
|
||||||
|
Insert a timestamp at the cursor position.
|
||||||
|
|
||||||
|
TODO: show fancy calendar to pick the date from.
|
||||||
|
TODO: add all modifier of orgmode.
|
||||||
|
"""
|
||||||
|
today = date.today()
|
||||||
|
msg = u''.join([
|
||||||
|
u'Inserting ',
|
||||||
|
unicode(u_decode(today.strftime(u'%Y-%m-%d %a'))),
|
||||||
|
u' | Modify date'])
|
||||||
|
modifier = get_user_input(msg)
|
||||||
|
|
||||||
|
# abort if the user canceled the input promt
|
||||||
|
if modifier is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
newdate = cls._modify_time(today, modifier)
|
||||||
|
|
||||||
|
# format
|
||||||
|
if isinstance(newdate, datetime):
|
||||||
|
newdate = newdate.strftime(
|
||||||
|
u_decode(u_encode(u'%Y-%m-%d %a %H:%M')))
|
||||||
|
else:
|
||||||
|
newdate = newdate.strftime(
|
||||||
|
u_decode(u_encode(u'%Y-%m-%d %a')))
|
||||||
|
timestamp = u'<%s>' % newdate if active else u'[%s]' % newdate
|
||||||
|
|
||||||
|
insert_at_cursor(timestamp)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def insert_timestamp_with_calendar(cls, active=True):
|
||||||
|
u"""
|
||||||
|
Insert a timestamp at the cursor position.
|
||||||
|
Show fancy calendar to pick the date from.
|
||||||
|
|
||||||
|
TODO: add all modifier of orgmode.
|
||||||
|
"""
|
||||||
|
if int(vim.eval(u_encode(u'exists(":CalendarH")'))) != 2:
|
||||||
|
vim.command("echo 'Please install plugin Calendar to enable this function'")
|
||||||
|
return
|
||||||
|
vim.command("CalendarH")
|
||||||
|
# backup calendar_action
|
||||||
|
calendar_action = vim.eval("g:calendar_action")
|
||||||
|
vim.command("let g:org_calendar_action_backup = '" + calendar_action + "'")
|
||||||
|
vim.command("let g:calendar_action = 'CalendarAction'")
|
||||||
|
|
||||||
|
timestamp_template = u'<%s>' if active else u'[%s]'
|
||||||
|
# timestamp template
|
||||||
|
vim.command("let g:org_timestamp_template = '" + timestamp_template + "'")
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of the plugin.
|
||||||
|
|
||||||
|
Key bindings and other initialization should be done here.
|
||||||
|
"""
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgDateInsertTimestampActiveCmdLine',
|
||||||
|
key_mapping=u'<localleader>sa',
|
||||||
|
function=u'%s ORGMODE.plugins[u"Date"].insert_timestamp()' % VIM_PY_CALL,
|
||||||
|
menu_desrc=u'Timest&'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgDateInsertTimestampInactiveCmdLine',
|
||||||
|
key_mapping='<localleader>si',
|
||||||
|
function=u'%s ORGMODE.plugins[u"Date"].insert_timestamp(False)' % VIM_PY_CALL,
|
||||||
|
menu_desrc=u'Timestamp (&inactive)'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgDateInsertTimestampActiveWithCalendar',
|
||||||
|
key_mapping=u'<localleader>pa',
|
||||||
|
function=u'%s ORGMODE.plugins[u"Date"].insert_timestamp_with_calendar()' % VIM_PY_CALL,
|
||||||
|
menu_desrc=u'Timestamp with Calendar'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgDateInsertTimestampInactiveWithCalendar',
|
||||||
|
key_mapping=u'<localleader>pi',
|
||||||
|
function=u'%s ORGMODE.plugins[u"Date"].insert_timestamp_with_calendar(False)' % VIM_PY_CALL,
|
||||||
|
menu_desrc=u'Timestamp with Calendar(inactive)'
|
||||||
|
)
|
||||||
|
|
||||||
|
submenu = self.menu + Submenu(u'Change &Date')
|
||||||
|
submenu + ActionEntry(u'Day &Earlier', u'<C-x>', u'<C-x>')
|
||||||
|
submenu + ActionEntry(u'Day &Later', u'<C-a>', u'<C-a>')
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,330 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
from orgmode._vim import echo, echom, echoe, ORGMODE, apply_count, repeat, insert_at_cursor, indent_orgmode
|
||||||
|
from orgmode import settings
|
||||||
|
from orgmode.menu import Submenu, Separator, ActionEntry, add_cmd_mapping_menu
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, Command
|
||||||
|
from orgmode.liborgmode.checkboxes import Checkbox
|
||||||
|
from orgmode.liborgmode.dom_obj import OrderListType
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
class EditCheckbox(object):
|
||||||
|
u"""
|
||||||
|
Checkbox plugin.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'Edit Checkbox')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_checkbox(cls, below=None, plain=None):
|
||||||
|
'''
|
||||||
|
if below is:
|
||||||
|
True -> create new list below current line
|
||||||
|
False/None -> create new list above current line
|
||||||
|
if plain is:
|
||||||
|
True -> create a plainlist item
|
||||||
|
False/None -> create an empty checkbox
|
||||||
|
'''
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
h = d.current_heading()
|
||||||
|
if h is None:
|
||||||
|
return
|
||||||
|
# init checkboxes for current heading
|
||||||
|
h.init_checkboxes()
|
||||||
|
c = h.current_checkbox()
|
||||||
|
|
||||||
|
nc = Checkbox()
|
||||||
|
nc._heading = h
|
||||||
|
|
||||||
|
# default checkbox level
|
||||||
|
level = h.level + 1
|
||||||
|
start = vim.current.window.cursor[0] - 1
|
||||||
|
# if no checkbox is found, insert at current line with indent level=1
|
||||||
|
if c is None:
|
||||||
|
h.checkboxes.append(nc)
|
||||||
|
else:
|
||||||
|
l = c.get_parent_list()
|
||||||
|
idx = c.get_index_in_parent_list()
|
||||||
|
if l is not None and idx is not None:
|
||||||
|
l.insert(idx + (1 if below else 0), nc)
|
||||||
|
# workaround for broken associations, Issue #165
|
||||||
|
nc._parent = c.parent
|
||||||
|
if below:
|
||||||
|
if c.next_sibling:
|
||||||
|
c.next_sibling._previous_sibling = nc
|
||||||
|
nc._next_sibling = c.next_sibling
|
||||||
|
c._next_sibling = nc
|
||||||
|
nc._previous_sibling = c
|
||||||
|
else:
|
||||||
|
if c.previous_sibling:
|
||||||
|
c.previous_sibling._next_sibling = nc
|
||||||
|
nc._next_sibling = c
|
||||||
|
nc._previous_sibling = c.previous_sibling
|
||||||
|
c._previous_sibling = nc
|
||||||
|
|
||||||
|
t = c.type
|
||||||
|
# increase key for ordered lists
|
||||||
|
if t[-1] in OrderListType:
|
||||||
|
try:
|
||||||
|
num = int(t[:-1]) + (1 if below else -1)
|
||||||
|
if num < 0:
|
||||||
|
# don't decrease to numbers below zero
|
||||||
|
echom(u"Can't decrement further than '0'")
|
||||||
|
return
|
||||||
|
t = '%d%s' % (num, t[-1])
|
||||||
|
except ValueError:
|
||||||
|
try:
|
||||||
|
char = ord(t[:-1]) + (1 if below else -1)
|
||||||
|
if below:
|
||||||
|
if char == 91:
|
||||||
|
# stop incrementing at Z (90)
|
||||||
|
echom(u"Can't increment further than 'Z'")
|
||||||
|
return
|
||||||
|
elif char == 123:
|
||||||
|
# increment from z (122) to A
|
||||||
|
char = 65
|
||||||
|
else:
|
||||||
|
if char == 96:
|
||||||
|
# stop decrementing at a (97)
|
||||||
|
echom(u"Can't decrement further than 'a'")
|
||||||
|
return
|
||||||
|
elif char == 64:
|
||||||
|
# decrement from A (65) to z
|
||||||
|
char = 122
|
||||||
|
t = u'%s%s' % (chr(char), t[-1])
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
nc.type = t
|
||||||
|
level = c.level
|
||||||
|
|
||||||
|
if below:
|
||||||
|
start = c.end_of_last_child
|
||||||
|
else:
|
||||||
|
start = c.start
|
||||||
|
|
||||||
|
if plain: # only create plainlist item when requested
|
||||||
|
nc.status = None
|
||||||
|
nc.level = level
|
||||||
|
|
||||||
|
if below:
|
||||||
|
start += 1
|
||||||
|
# vim's buffer behave just opposite to Python's list when inserting a
|
||||||
|
# new item. The new entry is appended in vim put prepended in Python!
|
||||||
|
vim.current.buffer.append("") # workaround for neovim
|
||||||
|
vim.current.buffer[start:start] = [unicode(nc)]
|
||||||
|
del vim.current.buffer[-1] # restore from workaround for neovim
|
||||||
|
|
||||||
|
# update checkboxes status
|
||||||
|
cls.update_checkboxes_status()
|
||||||
|
|
||||||
|
# do not start insert upon adding new checkbox, Issue #211
|
||||||
|
if int(settings.get(u'org_prefer_insert_mode', u'1')):
|
||||||
|
vim.command(u_encode(u'exe "normal %dgg"|startinsert!' % (start + 1, )))
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'exe "normal %dgg$"' % (start + 1, )))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def toggle(cls, checkbox=None):
|
||||||
|
u"""
|
||||||
|
Toggle the checkbox given in the parameter.
|
||||||
|
If the checkbox is not given, it will toggle the current checkbox.
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
current_heading = d.current_heading()
|
||||||
|
# init checkboxes for current heading
|
||||||
|
if current_heading is None:
|
||||||
|
return
|
||||||
|
current_heading = current_heading.init_checkboxes()
|
||||||
|
|
||||||
|
if checkbox is None:
|
||||||
|
# get current_checkbox
|
||||||
|
c = current_heading.current_checkbox()
|
||||||
|
# no checkbox found
|
||||||
|
if c is None:
|
||||||
|
cls.update_checkboxes_status()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
c = checkbox
|
||||||
|
|
||||||
|
if c.status == Checkbox.STATUS_OFF or c.status is None:
|
||||||
|
# set checkbox status on if all children are on
|
||||||
|
if c.all_children_status()[0] == 0 or c.are_children_all(Checkbox.STATUS_ON):
|
||||||
|
c.toggle()
|
||||||
|
d.write_checkbox(c)
|
||||||
|
elif c.status is None:
|
||||||
|
c.status = Checkbox.STATUS_OFF
|
||||||
|
d.write_checkbox(c)
|
||||||
|
|
||||||
|
elif c.status == Checkbox.STATUS_ON:
|
||||||
|
if c.all_children_status()[0] == 0 or c.is_child_one(Checkbox.STATUS_OFF):
|
||||||
|
c.toggle()
|
||||||
|
d.write_checkbox(c)
|
||||||
|
|
||||||
|
elif c.status == Checkbox.STATUS_INT:
|
||||||
|
# can't toggle intermediate state directly according to emacs orgmode
|
||||||
|
pass
|
||||||
|
# update checkboxes status
|
||||||
|
cls.update_checkboxes_status()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _update_subtasks(cls):
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
h = d.current_heading()
|
||||||
|
# init checkboxes for current heading
|
||||||
|
h.init_checkboxes()
|
||||||
|
# update heading subtask info
|
||||||
|
c = h.first_checkbox
|
||||||
|
if c is None:
|
||||||
|
return
|
||||||
|
total, on = c.all_siblings_status()
|
||||||
|
h.update_subtasks(total, on)
|
||||||
|
# update all checkboxes under current heading
|
||||||
|
cls._update_checkboxes_subtasks(c)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _update_checkboxes_subtasks(cls, checkbox):
|
||||||
|
# update checkboxes
|
||||||
|
for c in checkbox.all_siblings():
|
||||||
|
if c.children:
|
||||||
|
total, on = c.first_child.all_siblings_status()
|
||||||
|
c.update_subtasks(total, on)
|
||||||
|
cls._update_checkboxes_subtasks(c.first_child)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_checkboxes_status(cls):
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
h = d.current_heading()
|
||||||
|
if h is None:
|
||||||
|
return
|
||||||
|
# init checkboxes for current heading
|
||||||
|
h.init_checkboxes()
|
||||||
|
|
||||||
|
cls._update_checkboxes_status(h.first_checkbox)
|
||||||
|
cls._update_subtasks()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _update_checkboxes_status(cls, checkbox=None):
|
||||||
|
u""" helper function for update checkboxes status
|
||||||
|
:checkbox: The first checkbox of this indent level
|
||||||
|
:return: The status of the parent checkbox
|
||||||
|
"""
|
||||||
|
if checkbox is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
status_off, status_on, status_int, total = 0, 0, 0, 0
|
||||||
|
# update all top level checkboxes' status
|
||||||
|
for c in checkbox.all_siblings():
|
||||||
|
current_status = c.status
|
||||||
|
# if this checkbox is not leaf, its status should determine by all its children
|
||||||
|
if c.all_children_status()[0] > 0:
|
||||||
|
current_status = cls._update_checkboxes_status(c.first_child)
|
||||||
|
|
||||||
|
# don't update status if the checkbox has no status
|
||||||
|
if c.status is None:
|
||||||
|
current_status = None
|
||||||
|
# the checkbox needs to have status
|
||||||
|
else:
|
||||||
|
total += 1
|
||||||
|
|
||||||
|
# count number of status in this checkbox level
|
||||||
|
if current_status == Checkbox.STATUS_OFF:
|
||||||
|
status_off += 1
|
||||||
|
elif current_status == Checkbox.STATUS_ON:
|
||||||
|
status_on += 1
|
||||||
|
elif current_status == Checkbox.STATUS_INT:
|
||||||
|
status_int += 1
|
||||||
|
|
||||||
|
# write status if any update
|
||||||
|
if current_status is not None and c.status != current_status:
|
||||||
|
c.status = current_status
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
d.write_checkbox(c)
|
||||||
|
|
||||||
|
parent_status = Checkbox.STATUS_INT
|
||||||
|
# all silbing checkboxes are off status
|
||||||
|
if total == 0:
|
||||||
|
pass
|
||||||
|
elif status_off == total:
|
||||||
|
parent_status = Checkbox.STATUS_OFF
|
||||||
|
# all silbing checkboxes are on status
|
||||||
|
elif status_on == total:
|
||||||
|
parent_status = Checkbox.STATUS_ON
|
||||||
|
# one silbing checkbox is on or int status
|
||||||
|
elif status_on != 0 or status_int != 0:
|
||||||
|
parent_status = Checkbox.STATUS_INT
|
||||||
|
# other cases
|
||||||
|
else:
|
||||||
|
parent_status = None
|
||||||
|
|
||||||
|
return parent_status
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of the plugin.
|
||||||
|
|
||||||
|
Key bindings and other initialization should be done here.
|
||||||
|
"""
|
||||||
|
# default setting if it is not already set.
|
||||||
|
|
||||||
|
# checkbox related operation
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgCheckBoxNewAbove',
|
||||||
|
function=u'%s ORGMODE.plugins[u"EditCheckbox"].new_checkbox()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>cN',
|
||||||
|
menu_desrc=u'New CheckBox Above'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgCheckBoxNewBelow',
|
||||||
|
function=u'%s ORGMODE.plugins[u"EditCheckbox"].new_checkbox(below=True)<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>cn',
|
||||||
|
menu_desrc=u'New CheckBox Below'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgCheckBoxToggle',
|
||||||
|
function=u':silent! %s ORGMODE.plugins[u"EditCheckbox"].toggle()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>cc',
|
||||||
|
menu_desrc=u'Toggle Checkbox'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgCheckBoxUpdate',
|
||||||
|
function=u':silent! %s ORGMODE.plugins[u"EditCheckbox"].update_checkboxes_status()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>c#',
|
||||||
|
menu_desrc=u'Update Subtasks'
|
||||||
|
)
|
||||||
|
# plainlist related operation
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgPlainListItemNewAbove',
|
||||||
|
function=u'%s ORGMODE.plugins[u"EditCheckbox"].new_checkbox(plain=True)<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>cL',
|
||||||
|
menu_desrc=u'New PlainList Item Above'
|
||||||
|
)
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgPlainListItemNewBelow',
|
||||||
|
function=u'%s ORGMODE.plugins[u"EditCheckbox"].new_checkbox(below=True, plain=True)<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>cl',
|
||||||
|
menu_desrc=u'New PlainList Item Below'
|
||||||
|
)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,430 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE, apply_count, repeat, realign_tags
|
||||||
|
from orgmode import settings
|
||||||
|
from orgmode.exceptions import HeadingDomError
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, MODE_INSERT, MODE_NORMAL
|
||||||
|
from orgmode.menu import Submenu, Separator, ActionEntry
|
||||||
|
from orgmode.liborgmode.base import Direction
|
||||||
|
from orgmode.liborgmode.headings import Heading
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
|
||||||
|
class EditStructure(object):
|
||||||
|
u""" EditStructure plugin """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'&Edit Structure')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_heading(cls, below=None, insert_mode=False, end_of_last_child=False):
|
||||||
|
u"""
|
||||||
|
:below: True, insert heading below current heading, False,
|
||||||
|
insert heading above current heading, None, special
|
||||||
|
behavior for insert mode, use the current text as
|
||||||
|
heading
|
||||||
|
:insert_mode: True, if action is performed in insert mode
|
||||||
|
:end_of_last_child: True, insert heading at the end of last child,
|
||||||
|
otherwise the newly created heading will "take
|
||||||
|
over" the current heading's children
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
current_heading = d.current_heading()
|
||||||
|
cursor = vim.current.window.cursor[:]
|
||||||
|
if not current_heading:
|
||||||
|
# the user is in meta data region
|
||||||
|
pos = cursor[0] - 1
|
||||||
|
heading = Heading(title=d.meta_information[pos], body=d.meta_information[pos + 1:])
|
||||||
|
d.headings.insert(0, heading)
|
||||||
|
del d.meta_information[pos:]
|
||||||
|
d.write()
|
||||||
|
vim.command(u_encode(u'exe "normal %dgg"|startinsert!' % (heading.start_vim, )))
|
||||||
|
return heading
|
||||||
|
|
||||||
|
# check for plain list(checkbox)
|
||||||
|
current_heading.init_checkboxes()
|
||||||
|
c = current_heading.current_checkbox()
|
||||||
|
if c is not None:
|
||||||
|
ORGMODE.plugins[u"EditCheckbox"].new_checkbox(below, not c.status)
|
||||||
|
return
|
||||||
|
|
||||||
|
heading = Heading(level=current_heading.level)
|
||||||
|
|
||||||
|
# it's weird but this is the behavior of original orgmode
|
||||||
|
if below is None:
|
||||||
|
below = cursor[1] != 0 or end_of_last_child
|
||||||
|
|
||||||
|
# insert newly created heading
|
||||||
|
l = current_heading.get_parent_list()
|
||||||
|
idx = current_heading.get_index_in_parent_list()
|
||||||
|
if l is not None and idx is not None:
|
||||||
|
l.insert(idx + (1 if below else 0), heading)
|
||||||
|
else:
|
||||||
|
raise HeadingDomError(u'Current heading is not properly linked in DOM')
|
||||||
|
|
||||||
|
if below and not end_of_last_child:
|
||||||
|
# append heading at the end of current heading and also take
|
||||||
|
# over the children of current heading
|
||||||
|
for child in current_heading.children:
|
||||||
|
heading.children.append(child, taint=False)
|
||||||
|
current_heading.children.remove_slice(
|
||||||
|
0, len(current_heading.children),
|
||||||
|
taint=False)
|
||||||
|
|
||||||
|
# if cursor is currently on a heading, insert parts of it into the
|
||||||
|
# newly created heading
|
||||||
|
if insert_mode and cursor[1] != 0 and cursor[0] == current_heading.start_vim:
|
||||||
|
offset = cursor[1] - current_heading.level - 1 - (
|
||||||
|
len(current_heading.todo) + 1 if current_heading.todo else 0)
|
||||||
|
if offset < 0:
|
||||||
|
offset = 0
|
||||||
|
if int(settings.get(u'org_improve_split_heading', u'1')) and \
|
||||||
|
offset > 0 and len(current_heading.title) == offset + 1 \
|
||||||
|
and current_heading.title[offset - 1] not in (u' ', u'\t'):
|
||||||
|
offset += 1
|
||||||
|
heading.title = current_heading.title[offset:]
|
||||||
|
current_heading.title = current_heading.title[:offset]
|
||||||
|
heading.body = current_heading.body[:]
|
||||||
|
current_heading.body = []
|
||||||
|
|
||||||
|
d.write()
|
||||||
|
# do not start insert upon adding new headings, unless already in insert mode. Issue #211
|
||||||
|
if int(settings.get(u'org_prefer_insert_mode', u'1')) or insert_mode:
|
||||||
|
vim.command(u_encode(u'exe "normal %dgg"|startinsert!' % (heading.start_vim, )))
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'exe "normal %dgg$"' % (heading.start_vim, )))
|
||||||
|
|
||||||
|
# return newly created heading
|
||||||
|
return heading
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _append_heading(cls, heading, parent):
|
||||||
|
if heading.level <= parent.level:
|
||||||
|
raise ValueError('Heading level not is lower than parent level: %d ! > %d' % (heading.level, parent.level))
|
||||||
|
|
||||||
|
if parent.children and parent.children[-1].level < heading.level:
|
||||||
|
cls._append_heading(heading, parent.children[-1])
|
||||||
|
else:
|
||||||
|
parent.children.append(heading, taint=False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _change_heading_level(cls, level, including_children=True, on_heading=False, insert_mode=False):
|
||||||
|
u"""
|
||||||
|
Change level of heading realtively with or without including children.
|
||||||
|
|
||||||
|
:level: the number of levels to promote/demote heading
|
||||||
|
:including_children: True if should should be included in promoting/demoting
|
||||||
|
:on_heading: True if promoting/demoting should only happen when the cursor is on the heading
|
||||||
|
:insert_mode: True if vim is in insert mode
|
||||||
|
"""
|
||||||
|
# TODO : current promote and demote works for only headings. Since
|
||||||
|
# checkboxes also have tree structure. We should think of
|
||||||
|
# expanding the functionality of promoting and demoting to
|
||||||
|
# checkboxes as well
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
current_heading = d.current_heading()
|
||||||
|
if not current_heading or on_heading and current_heading.start_vim != vim.current.window.cursor[0]:
|
||||||
|
# TODO figure out the actually pressed keybinding and feed these
|
||||||
|
# keys instead of making keys up like this
|
||||||
|
if level > 0:
|
||||||
|
if insert_mode:
|
||||||
|
vim.eval(u_encode(u'feedkeys("\<C-t>", "n")'))
|
||||||
|
elif including_children:
|
||||||
|
vim.eval(u_encode(u'feedkeys(">]]", "n")'))
|
||||||
|
elif on_heading:
|
||||||
|
vim.eval(u_encode(u'feedkeys(">>", "n")'))
|
||||||
|
else:
|
||||||
|
vim.eval(u_encode(u'feedkeys(">}", "n")'))
|
||||||
|
else:
|
||||||
|
if insert_mode:
|
||||||
|
vim.eval(u_encode(u'feedkeys("\<C-d>", "n")'))
|
||||||
|
elif including_children:
|
||||||
|
vim.eval(u_encode(u'feedkeys("<]]", "n")'))
|
||||||
|
elif on_heading:
|
||||||
|
vim.eval(u_encode(u'feedkeys("<<", "n")'))
|
||||||
|
else:
|
||||||
|
vim.eval(u_encode(u'feedkeys("<}", "n")'))
|
||||||
|
# return True because otherwise apply_count will not work
|
||||||
|
return True
|
||||||
|
|
||||||
|
# don't allow demotion below level 1
|
||||||
|
if current_heading.level == 1 and level < 1:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# reduce level of demotion to a minimum heading level of 1
|
||||||
|
if (current_heading.level + level) < 1:
|
||||||
|
level = 1
|
||||||
|
|
||||||
|
def indent(heading, ic):
|
||||||
|
if not heading:
|
||||||
|
return
|
||||||
|
heading.level += level
|
||||||
|
|
||||||
|
if ic:
|
||||||
|
for child in heading.children:
|
||||||
|
indent(child, ic)
|
||||||
|
|
||||||
|
# save cursor position
|
||||||
|
c = vim.current.window.cursor[:]
|
||||||
|
|
||||||
|
# indent the promoted/demoted heading
|
||||||
|
indent_end_vim = current_heading.end_of_last_child_vim if including_children else current_heading.end_vim
|
||||||
|
indent(current_heading, including_children)
|
||||||
|
|
||||||
|
# when changing the level of a heading, its position in the DOM
|
||||||
|
# needs to be updated. It's likely that the heading gets a new
|
||||||
|
# parent and new children when demoted or promoted
|
||||||
|
|
||||||
|
# find new parent
|
||||||
|
p = current_heading.parent
|
||||||
|
pl = current_heading.get_parent_list()
|
||||||
|
ps = current_heading.previous_sibling
|
||||||
|
nhl = current_heading.level
|
||||||
|
|
||||||
|
if level > 0:
|
||||||
|
# demotion
|
||||||
|
# subheading or top level heading
|
||||||
|
if ps and nhl > ps.level:
|
||||||
|
pl.remove(current_heading, taint=False)
|
||||||
|
# find heading that is the new parent heading
|
||||||
|
oh = ps
|
||||||
|
h = ps
|
||||||
|
while nhl > h.level:
|
||||||
|
oh = h
|
||||||
|
if h.children:
|
||||||
|
h = h.children[-1]
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
np = h if nhl > h.level else oh
|
||||||
|
|
||||||
|
# append current heading to new heading
|
||||||
|
np.children.append(current_heading, taint=False)
|
||||||
|
|
||||||
|
# if children are not included, distribute them among the
|
||||||
|
# parent heading and it's siblings
|
||||||
|
if not including_children:
|
||||||
|
for h in current_heading.children[:]:
|
||||||
|
if h and h.level <= nhl:
|
||||||
|
cls._append_heading(h, np)
|
||||||
|
current_heading.children.remove(h, taint=False)
|
||||||
|
else:
|
||||||
|
# promotion
|
||||||
|
if p and nhl <= p.level:
|
||||||
|
idx = current_heading.get_index_in_parent_list() + 1
|
||||||
|
# find the new parent heading
|
||||||
|
oh = p
|
||||||
|
h = p
|
||||||
|
while nhl <= h.level:
|
||||||
|
# append new children to current heading
|
||||||
|
for child in h.children[idx:]:
|
||||||
|
cls._append_heading(child, current_heading)
|
||||||
|
h.children.remove_slice(idx, len(h.children), taint=False)
|
||||||
|
idx = h.get_index_in_parent_list() + 1
|
||||||
|
if h.parent:
|
||||||
|
h = h.parent
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
ns = oh.next_sibling
|
||||||
|
while ns and ns.level > current_heading.level:
|
||||||
|
nns = ns.next_sibling
|
||||||
|
cls._append_heading(ns, current_heading)
|
||||||
|
ns = nns
|
||||||
|
|
||||||
|
# append current heading to new parent heading / document
|
||||||
|
pl.remove(current_heading, taint=False)
|
||||||
|
if nhl > h.level:
|
||||||
|
h.children.insert(idx, current_heading, taint=False)
|
||||||
|
else:
|
||||||
|
d.headings.insert(idx, current_heading, taint=False)
|
||||||
|
|
||||||
|
d.write()
|
||||||
|
|
||||||
|
# restore cursor position
|
||||||
|
vim.current.window.cursor = (c[0], c[1] + level)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@realign_tags
|
||||||
|
@repeat
|
||||||
|
@apply_count
|
||||||
|
def demote_heading(cls, including_children=True, on_heading=False, insert_mode=False):
|
||||||
|
if cls._change_heading_level(1, including_children=including_children, on_heading=on_heading, insert_mode=insert_mode):
|
||||||
|
if including_children:
|
||||||
|
return u'OrgDemoteSubtree'
|
||||||
|
return u'OrgDemoteHeading'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@realign_tags
|
||||||
|
@repeat
|
||||||
|
@apply_count
|
||||||
|
def promote_heading(cls, including_children=True, on_heading=False, insert_mode=False):
|
||||||
|
if cls._change_heading_level(-1, including_children=including_children, on_heading=on_heading, insert_mode=insert_mode):
|
||||||
|
if including_children:
|
||||||
|
return u'OrgPromoteSubtreeNormal'
|
||||||
|
return u'OrgPromoteHeadingNormal'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _move_heading(cls, direction=Direction.FORWARD, including_children=True):
|
||||||
|
u""" Move heading up or down
|
||||||
|
|
||||||
|
:returns: heading or None
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
current_heading = d.current_heading()
|
||||||
|
if not current_heading or \
|
||||||
|
(direction == Direction.FORWARD and not current_heading.next_sibling) or \
|
||||||
|
(direction == Direction.BACKWARD and not current_heading.previous_sibling):
|
||||||
|
return None
|
||||||
|
|
||||||
|
cursor_offset = vim.current.window.cursor[0] - (current_heading._orig_start + 1)
|
||||||
|
l = current_heading.get_parent_list()
|
||||||
|
if l is None:
|
||||||
|
raise HeadingDomError(u'Current heading is not properly linked in DOM')
|
||||||
|
|
||||||
|
if not including_children:
|
||||||
|
if current_heading.previous_sibling:
|
||||||
|
npl = current_heading.previous_sibling.children
|
||||||
|
for child in current_heading.children:
|
||||||
|
npl.append(child, taint=False)
|
||||||
|
elif current_heading.parent:
|
||||||
|
# if the current heading doesn't have a previous sibling it
|
||||||
|
# must be the first heading
|
||||||
|
np = current_heading.parent
|
||||||
|
for child in current_heading.children:
|
||||||
|
cls._append_heading(child, np)
|
||||||
|
else:
|
||||||
|
# if the current heading doesn't have a parent, its children
|
||||||
|
# must be added as top level headings to the document
|
||||||
|
npl = l
|
||||||
|
for child in current_heading.children[::-1]:
|
||||||
|
npl.insert(0, child, taint=False)
|
||||||
|
current_heading.children.remove_slice(0, len(current_heading.children), taint=False)
|
||||||
|
|
||||||
|
idx = current_heading.get_index_in_parent_list()
|
||||||
|
if idx is None:
|
||||||
|
raise HeadingDomError(u'Current heading is not properly linked in DOM')
|
||||||
|
|
||||||
|
offset = 1 if direction == Direction.FORWARD else -1
|
||||||
|
del l[idx]
|
||||||
|
l.insert(idx + offset, current_heading)
|
||||||
|
|
||||||
|
d.write()
|
||||||
|
|
||||||
|
vim.current.window.cursor = (
|
||||||
|
current_heading.start_vim + cursor_offset,
|
||||||
|
vim.current.window.cursor[1])
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@repeat
|
||||||
|
@apply_count
|
||||||
|
def move_heading_upward(cls, including_children=True):
|
||||||
|
if cls._move_heading(direction=Direction.BACKWARD, including_children=including_children):
|
||||||
|
if including_children:
|
||||||
|
return u'OrgMoveSubtreeUpward'
|
||||||
|
return u'OrgMoveHeadingUpward'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@repeat
|
||||||
|
@apply_count
|
||||||
|
def move_heading_downward(cls, including_children=True):
|
||||||
|
if cls._move_heading(direction=Direction.FORWARD, including_children=including_children):
|
||||||
|
if including_children:
|
||||||
|
return u'OrgMoveSubtreeDownward'
|
||||||
|
return u'OrgMoveHeadingDownward'
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of plugin. Key bindings and other initialization should be done.
|
||||||
|
"""
|
||||||
|
# EditStructure related default settings
|
||||||
|
settings.set(u'org_improve_split_heading', u'1')
|
||||||
|
# EditStructure related keybindings
|
||||||
|
self.keybindings.append(Keybinding(u'<C-S-CR>',
|
||||||
|
Plug(u'OrgNewHeadingAboveNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].new_heading(below=False)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'New Heading &above', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>hN', u'<Plug>OrgNewHeadingAboveNormal', mode=MODE_NORMAL))
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader><CR>', u'<Plug>OrgNewHeadingAboveNormal', mode=MODE_NORMAL))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<S-CR>',
|
||||||
|
Plug(u'OrgNewHeadingBelowNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].new_heading(below=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'New Heading &below', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>hh', u'<Plug>OrgNewHeadingBelowNormal', mode=MODE_NORMAL))
|
||||||
|
self.keybindings.append(Keybinding(u'<leader><CR>', u'<Plug>OrgNewHeadingBelowNormal', mode=MODE_NORMAL))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<C-CR>', Plug(u'OrgNewHeadingBelowAfterChildrenNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].new_heading(below=True, end_of_last_child=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'New Heading below, after &children', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>hn', u'<Plug>OrgNewHeadingBelowAfterChildrenNormal', mode=MODE_NORMAL))
|
||||||
|
self.keybindings.append(Keybinding(u'<CR>', u'<Plug>OrgNewHeadingBelowAfterChildrenNormal', mode=MODE_NORMAL))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<C-S-CR>', Plug(u'OrgNewHeadingAboveInsert', u'<C-o>:<C-u>silent! %s ORGMODE.plugins[u"EditStructure"].new_heading(below=False, insert_mode=True)<CR>' % VIM_PY_CALL, mode=MODE_INSERT)))
|
||||||
|
self.keybindings.append(Keybinding(u'<S-CR>', Plug(u'OrgNewHeadingBelowInsert', u'<C-o>:<C-u>silent! %s ORGMODE.plugins[u"EditStructure"].new_heading(below=True, insert_mode=True)<CR>' % VIM_PY_CALL, mode=MODE_INSERT)))
|
||||||
|
self.keybindings.append(Keybinding(u'<C-CR>', Plug(u'OrgNewHeadingBelowAfterChildrenInsert', u'<C-o>:<C-u>silent! %s ORGMODE.plugins[u"EditStructure"].new_heading(insert_mode=True, end_of_last_child=True)<CR>' % VIM_PY_CALL, mode=MODE_INSERT)))
|
||||||
|
|
||||||
|
self.menu + Separator()
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'm{', Plug(u'OrgMoveHeadingUpward',
|
||||||
|
u'%s ORGMODE.plugins[u"EditStructure"].move_heading_upward(including_children=False)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.keybindings.append(Keybinding(u'm[[',
|
||||||
|
Plug(u'OrgMoveSubtreeUpward', u'%s ORGMODE.plugins[u"EditStructure"].move_heading_upward()<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'Move Subtree &Up', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'm}',
|
||||||
|
Plug(u'OrgMoveHeadingDownward', u'%s ORGMODE.plugins[u"EditStructure"].move_heading_downward(including_children=False)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.keybindings.append(Keybinding(u'm]]',
|
||||||
|
Plug(u'OrgMoveSubtreeDownward', u'%s ORGMODE.plugins[u"EditStructure"].move_heading_downward()<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'Move Subtree &Down', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.menu + Separator()
|
||||||
|
|
||||||
|
self.menu + ActionEntry(u'&Copy Heading', u'yah', u'yah')
|
||||||
|
self.menu + ActionEntry(u'C&ut Heading', u'dah', u'dah')
|
||||||
|
|
||||||
|
self.menu + Separator()
|
||||||
|
|
||||||
|
self.menu + ActionEntry(u'&Copy Subtree', u'yar', u'yar')
|
||||||
|
self.menu + ActionEntry(u'C&ut Subtree', u'dar', u'dar')
|
||||||
|
self.menu + ActionEntry(u'&Paste Subtree', u'p', u'p')
|
||||||
|
|
||||||
|
self.menu + Separator()
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<ah', Plug(u'OrgPromoteHeadingNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].promote_heading(including_children=False)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Promote Heading', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'<<', Plug(u'OrgPromoteOnHeadingNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].promote_heading(including_children=False, on_heading=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.keybindings.append(Keybinding(u'<{', u'<Plug>OrgPromoteHeadingNormal', mode=MODE_NORMAL))
|
||||||
|
self.keybindings.append(Keybinding(u'<ih', u'<Plug>OrgPromoteHeadingNormal', mode=MODE_NORMAL))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<ar', Plug(u'OrgPromoteSubtreeNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].promote_heading()<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Promote Subtree', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'<[[', u'<Plug>OrgPromoteSubtreeNormal', mode=MODE_NORMAL))
|
||||||
|
self.keybindings.append(Keybinding(u'<ir', u'<Plug>OrgPromoteSubtreeNormal', mode=MODE_NORMAL))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'>ah', Plug(u'OrgDemoteHeadingNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].demote_heading(including_children=False)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Demote Heading', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'>>', Plug(u'OrgDemoteOnHeadingNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].demote_heading(including_children=False, on_heading=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.keybindings.append(Keybinding(u'>}', u'<Plug>OrgDemoteHeadingNormal', mode=MODE_NORMAL))
|
||||||
|
self.keybindings.append(Keybinding(u'>ih', u'<Plug>OrgDemoteHeadingNormal', mode=MODE_NORMAL))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'>ar', Plug(u'OrgDemoteSubtreeNormal', u':silent! %s ORGMODE.plugins[u"EditStructure"].demote_heading()<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Demote Subtree', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'>]]', u'<Plug>OrgDemoteSubtreeNormal', mode=MODE_NORMAL))
|
||||||
|
self.keybindings.append(Keybinding(u'>ir', u'<Plug>OrgDemoteSubtreeNormal', mode=MODE_NORMAL))
|
||||||
|
|
||||||
|
# other keybindings
|
||||||
|
self.keybindings.append(Keybinding(u'<C-d>', Plug(u'OrgPromoteOnHeadingInsert', u'<C-o>:silent! %s ORGMODE.plugins[u"EditStructure"].promote_heading(including_children=False, on_heading=True, insert_mode=True)<CR>' % VIM_PY_CALL, mode=MODE_INSERT)))
|
||||||
|
self.keybindings.append(Keybinding(u'<C-t>', Plug(u'OrgDemoteOnHeadingInsert', u'<C-o>:silent! %s ORGMODE.plugins[u"EditStructure"].demote_heading(including_children=False, on_heading=True, insert_mode=True)<CR>' % VIM_PY_CALL, mode=MODE_INSERT)))
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
183
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Export.py
Normal file
183
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Export.py
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE, echoe, echom
|
||||||
|
from orgmode.menu import Submenu, ActionEntry, add_cmd_mapping_menu
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, Command
|
||||||
|
from orgmode import settings
|
||||||
|
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class Export(object):
|
||||||
|
u"""
|
||||||
|
Export a orgmode file using emacs orgmode.
|
||||||
|
|
||||||
|
This is a *very simple* wrapper of the emacs/orgmode export. emacs and
|
||||||
|
orgmode need to be installed. We simply call emacs with some options to
|
||||||
|
export the .org.
|
||||||
|
|
||||||
|
TODO: Offer export options in vim. Don't use the menu.
|
||||||
|
TODO: Maybe use a native implementation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'Export')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_init_script(cls):
|
||||||
|
init_script = settings.get(u'org_export_init_script', u'')
|
||||||
|
if init_script:
|
||||||
|
init_script = os.path.expandvars(os.path.expanduser(init_script))
|
||||||
|
if os.path.exists(init_script):
|
||||||
|
return init_script
|
||||||
|
else:
|
||||||
|
echoe(u'Unable to find init script %s' % init_script)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _export(cls, format_):
|
||||||
|
"""Export current file to format.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
format_: pdf or html
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
return code
|
||||||
|
"""
|
||||||
|
emacsbin = os.path.expandvars(os.path.expanduser(
|
||||||
|
settings.get(u'org_export_emacs', u'/usr/bin/emacs')))
|
||||||
|
if not os.path.exists(emacsbin):
|
||||||
|
echoe(u'Unable to find emacs binary %s' % emacsbin)
|
||||||
|
|
||||||
|
# build the export command
|
||||||
|
cmd = [
|
||||||
|
emacsbin,
|
||||||
|
u'-nw',
|
||||||
|
u'--batch',
|
||||||
|
u'--visit=%s' % vim.eval(u'expand("%:p")'),
|
||||||
|
u'--funcall=%s' % format_
|
||||||
|
]
|
||||||
|
# source init script as well
|
||||||
|
init_script = cls._get_init_script()
|
||||||
|
if init_script:
|
||||||
|
cmd.extend(['--script', init_script])
|
||||||
|
|
||||||
|
# export
|
||||||
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
p.wait()
|
||||||
|
|
||||||
|
if p.returncode != 0 or settings.get(u'org_export_verbose') == 1:
|
||||||
|
echom('\n'.join(p.communicate()))
|
||||||
|
return p.returncode
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def topdf(cls):
|
||||||
|
u"""Export the current buffer as pdf using emacs orgmode."""
|
||||||
|
ret = cls._export(u'org-latex-export-to-pdf')
|
||||||
|
if ret != 0:
|
||||||
|
echoe(u'PDF export failed.')
|
||||||
|
else:
|
||||||
|
echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'pdf'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tobeamer(cls):
|
||||||
|
u"""Export the current buffer as beamer pdf using emacs orgmode."""
|
||||||
|
ret = cls._export(u'org-beamer-export-to-pdf')
|
||||||
|
if ret != 0:
|
||||||
|
echoe(u'PDF export failed.')
|
||||||
|
else:
|
||||||
|
echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'pdf'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tohtml(cls):
|
||||||
|
u"""Export the current buffer as html using emacs orgmode."""
|
||||||
|
ret = cls._export(u'org-html-export-to-html')
|
||||||
|
if ret != 0:
|
||||||
|
echoe(u'HTML export failed.')
|
||||||
|
else:
|
||||||
|
echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'html'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tolatex(cls):
|
||||||
|
u"""Export the current buffer as latex using emacs orgmode."""
|
||||||
|
ret = cls._export(u'org-latex-export-to-latex')
|
||||||
|
if ret != 0:
|
||||||
|
echoe(u'latex export failed.')
|
||||||
|
else:
|
||||||
|
echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'tex'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tomarkdown(cls):
|
||||||
|
u"""Export the current buffer as markdown using emacs orgmode."""
|
||||||
|
ret = cls._export(u'org-md-export-to-markdown')
|
||||||
|
if ret != 0:
|
||||||
|
echoe('Markdown export failed. Make sure org-md-export-to-markdown is loaded in emacs, see the manual for details.')
|
||||||
|
else:
|
||||||
|
echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'md'))
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""Registration and keybindings."""
|
||||||
|
|
||||||
|
# path to emacs executable
|
||||||
|
settings.set(u'org_export_emacs', u'/usr/bin/emacs')
|
||||||
|
# verbose output for export
|
||||||
|
settings.set(u'org_export_verbose', 0)
|
||||||
|
# allow the user to define an initialization script
|
||||||
|
settings.set(u'org_export_init_script', u'')
|
||||||
|
|
||||||
|
# to PDF
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgExportToPDF',
|
||||||
|
function=u':%s ORGMODE.plugins[u"Export"].topdf()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>ep',
|
||||||
|
menu_desrc=u'To PDF (via Emacs)'
|
||||||
|
)
|
||||||
|
# to Beamer PDF
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgExportToBeamerPDF',
|
||||||
|
function=u':%s ORGMODE.plugins[u"Export"].tobeamer()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>eb',
|
||||||
|
menu_desrc=u'To Beamer PDF (via Emacs)'
|
||||||
|
)
|
||||||
|
# to latex
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgExportToLaTeX',
|
||||||
|
function=u':%s ORGMODE.plugins[u"Export"].tolatex()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>el',
|
||||||
|
menu_desrc=u'To LaTeX (via Emacs)'
|
||||||
|
)
|
||||||
|
# to HTML
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgExportToHTML',
|
||||||
|
function=u':%s ORGMODE.plugins[u"Export"].tohtml()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>eh',
|
||||||
|
menu_desrc=u'To HTML (via Emacs)'
|
||||||
|
)
|
||||||
|
# to Markdown
|
||||||
|
add_cmd_mapping_menu(
|
||||||
|
self,
|
||||||
|
name=u'OrgExportToMarkdown',
|
||||||
|
function=u':%s ORGMODE.plugins[u"Export"].tomarkdown()<CR>' % VIM_PY_CALL,
|
||||||
|
key_mapping=u'<localleader>em',
|
||||||
|
menu_desrc=u'To Markdown (via Emacs)'
|
||||||
|
)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,221 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import echom, ORGMODE, realign_tags
|
||||||
|
from orgmode.menu import Submenu, Separator, ActionEntry
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, Command
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class Hyperlinks(object):
|
||||||
|
u""" Hyperlinks plugin """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'Hyperlinks')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
uri_match = re.compile(
|
||||||
|
r'^\[{2}(?P<uri>[^][]*)(\]\[(?P<description>[^][]*))?\]{2}')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_link(cls, cursor=None):
|
||||||
|
u"""
|
||||||
|
Get the link the cursor is on and return it's URI and description
|
||||||
|
|
||||||
|
:cursor: None or (Line, Column)
|
||||||
|
:returns: None if no link was found, otherwise {uri:URI,
|
||||||
|
description:DESCRIPTION, line:LINE, start:START, end:END}
|
||||||
|
or uri and description could be None if not set
|
||||||
|
"""
|
||||||
|
cursor = cursor if cursor else vim.current.window.cursor
|
||||||
|
line = u_decode(vim.current.buffer[cursor[0] - 1])
|
||||||
|
|
||||||
|
# if the cursor is on the last bracket, it's not recognized as a hyperlink
|
||||||
|
start = line.rfind(u'[[', 0, cursor[1])
|
||||||
|
if start == -1:
|
||||||
|
start = line.rfind(u'[[', 0, cursor[1] + 2)
|
||||||
|
end = line.find(u']]', cursor[1])
|
||||||
|
if end == -1:
|
||||||
|
end = line.find(u']]', cursor[1] - 1)
|
||||||
|
|
||||||
|
# extract link
|
||||||
|
if start != -1 and end != -1:
|
||||||
|
end += 2
|
||||||
|
match = Hyperlinks.uri_match.match(line[start:end])
|
||||||
|
|
||||||
|
res = {
|
||||||
|
u'line': line,
|
||||||
|
u'start': start,
|
||||||
|
u'end': end,
|
||||||
|
u'uri': None,
|
||||||
|
u'description': None}
|
||||||
|
if match:
|
||||||
|
res.update(match.groupdict())
|
||||||
|
# reverse character escaping(partly done due to matching)
|
||||||
|
res[u'uri'] = res[u'uri'].replace(u'\\\\', u'\\')
|
||||||
|
return res
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def follow(cls, action=u'openLink', visual=u''):
|
||||||
|
u""" Follow hyperlink. If called on a regular string UTL determines the
|
||||||
|
outcome. Normally a file with that name will be opened.
|
||||||
|
|
||||||
|
:action: "copy" if the link should be copied to clipboard, otherwise
|
||||||
|
the link will be opened
|
||||||
|
:visual: "visual" if Universal Text Linking should be triggered in
|
||||||
|
visual mode
|
||||||
|
|
||||||
|
:returns: URI or None
|
||||||
|
"""
|
||||||
|
if not int(vim.eval(u'exists(":Utl")')):
|
||||||
|
echom(u'Universal Text Linking plugin not installed, unable to proceed.')
|
||||||
|
return
|
||||||
|
|
||||||
|
action = u'copyLink' \
|
||||||
|
if (action and action.startswith(u'copy')) \
|
||||||
|
else u'openLink'
|
||||||
|
visual = u'visual' if visual and visual.startswith(u'visual') else u''
|
||||||
|
|
||||||
|
link = Hyperlinks._get_link()
|
||||||
|
|
||||||
|
if link and link[u'uri'] is not None:
|
||||||
|
# call UTL with the URI
|
||||||
|
vim.command(u_encode(u'Utl %s %s %s' % (action, visual, link[u'uri'])))
|
||||||
|
return link[u'uri']
|
||||||
|
else:
|
||||||
|
# call UTL and let it decide what to do
|
||||||
|
vim.command(u_encode(u'Utl %s %s' % (action, visual)))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@realign_tags
|
||||||
|
def insert(cls, uri=None, description=None):
|
||||||
|
u""" Inserts a hyperlink. If no arguments are provided, an interactive
|
||||||
|
query will be started.
|
||||||
|
|
||||||
|
:uri: The URI that will be opened
|
||||||
|
:description: An optional description that will be displayed instead of
|
||||||
|
the URI
|
||||||
|
|
||||||
|
:returns: (URI, description)
|
||||||
|
"""
|
||||||
|
link = Hyperlinks._get_link()
|
||||||
|
if link:
|
||||||
|
if uri is None and link[u'uri'] is not None:
|
||||||
|
uri = link[u'uri']
|
||||||
|
if description is None and link[u'description'] is not None:
|
||||||
|
description = link[u'description']
|
||||||
|
|
||||||
|
if uri is None:
|
||||||
|
uri = vim.eval(u'input("Link: ", "", "file")')
|
||||||
|
elif link:
|
||||||
|
uri = vim.eval(u'input("Link: ", "%s", "file")' % link[u'uri'])
|
||||||
|
if uri is None:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
uri = u_decode(uri)
|
||||||
|
|
||||||
|
# character escaping
|
||||||
|
uri = uri.replace(u'\\', u'\\\\\\\\')
|
||||||
|
uri = uri.replace(u' ', u'\ ')
|
||||||
|
|
||||||
|
if description is None:
|
||||||
|
description = u_decode(vim.eval(u'input("Description: ")'))
|
||||||
|
elif link:
|
||||||
|
description = vim.eval(
|
||||||
|
u'input("Description: ", "%s")' %
|
||||||
|
u_decode(link[u'description']))
|
||||||
|
if description is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
cursor = vim.current.window.cursor
|
||||||
|
cl = u_decode(vim.current.buffer[cursor[0] - 1])
|
||||||
|
head = cl[:cursor[1] + 1] if not link else cl[:link[u'start']]
|
||||||
|
tail = cl[cursor[1] + 1:] if not link else cl[link[u'end']:]
|
||||||
|
|
||||||
|
separator = u''
|
||||||
|
if description:
|
||||||
|
separator = u']['
|
||||||
|
|
||||||
|
if uri or description:
|
||||||
|
vim.current.buffer[cursor[0] - 1] = \
|
||||||
|
u_encode(u''.join((head, u'[[%s%s%s]]' % (uri, separator, description), tail)))
|
||||||
|
elif link:
|
||||||
|
vim.current.buffer[cursor[0] - 1] = \
|
||||||
|
u_encode(u''.join((head, tail)))
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of plugin. Key bindings and other initialization should be done.
|
||||||
|
"""
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgHyperlinkFollow',
|
||||||
|
u'%s ORGMODE.plugins[u"Hyperlinks"].follow()' % VIM_PY_CALL)
|
||||||
|
self.commands.append(cmd)
|
||||||
|
self.keybindings.append(
|
||||||
|
Keybinding(u'gl', Plug(u'OrgHyperlinkFollow', self.commands[-1])))
|
||||||
|
self.menu + ActionEntry(u'&Follow Link', self.keybindings[-1])
|
||||||
|
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgHyperlinkCopy',
|
||||||
|
u'%s ORGMODE.plugins[u"Hyperlinks"].follow(action=u"copy")' % VIM_PY_CALL)
|
||||||
|
self.commands.append(cmd)
|
||||||
|
self.keybindings.append(
|
||||||
|
Keybinding(u'gyl', Plug(u'OrgHyperlinkCopy', self.commands[-1])))
|
||||||
|
self.menu + ActionEntry(u'&Copy Link', self.keybindings[-1])
|
||||||
|
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgHyperlinkInsert',
|
||||||
|
u'%s ORGMODE.plugins[u"Hyperlinks"].insert(<f-args>)' % VIM_PY_CALL,
|
||||||
|
arguments=u'*')
|
||||||
|
self.commands.append(cmd)
|
||||||
|
self.keybindings.append(
|
||||||
|
Keybinding(u'gil', Plug(u'OrgHyperlinkInsert', self.commands[-1])))
|
||||||
|
self.menu + ActionEntry(u'&Insert Link', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.menu + Separator()
|
||||||
|
|
||||||
|
# find next link
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgHyperlinkNextLink',
|
||||||
|
u":if search('\[\{2}\zs[^][]*\(\]\[[^][]*\)\?\ze\]\{2}', 's') == 0 | echo 'No further link found.' | endif")
|
||||||
|
self.commands.append(cmd)
|
||||||
|
self.keybindings.append(
|
||||||
|
Keybinding(u'gn', Plug(u'OrgHyperlinkNextLink', self.commands[-1])))
|
||||||
|
self.menu + ActionEntry(u'&Next Link', self.keybindings[-1])
|
||||||
|
|
||||||
|
# find previous link
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgHyperlinkPreviousLink',
|
||||||
|
u":if search('\[\{2}\zs[^][]*\(\]\[[^][]*\)\?\ze\]\{2}', 'bs') == 0 | echo 'No further link found.' | endif")
|
||||||
|
self.commands.append(cmd)
|
||||||
|
self.keybindings.append(
|
||||||
|
Keybinding(u'go', Plug(u'OrgHyperlinkPreviousLink', self.commands[-1])))
|
||||||
|
self.menu + ActionEntry(u'&Previous Link', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.menu + Separator()
|
||||||
|
|
||||||
|
# Descriptive Links
|
||||||
|
cmd = Command(u'OrgHyperlinkDescriptiveLinks', u':setlocal cole=2')
|
||||||
|
self.commands.append(cmd)
|
||||||
|
self.menu + ActionEntry(u'&Descriptive Links', self.commands[-1])
|
||||||
|
|
||||||
|
# Literal Links
|
||||||
|
cmd = Command(u'OrgHyperlinkLiteralLinks', u':setlocal cole=0')
|
||||||
|
self.commands.append(cmd)
|
||||||
|
self.menu + ActionEntry(u'&Literal Links', self.commands[-1])
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1,42 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import echo, echom, echoe, ORGMODE, apply_count, repeat
|
||||||
|
from orgmode.menu import Submenu, Separator, ActionEntry
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, Command
|
||||||
|
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class LoggingWork(object):
|
||||||
|
u""" LoggingWork plugin """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'&Logging work')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def action(cls):
|
||||||
|
u""" Some kind of action
|
||||||
|
|
||||||
|
:returns: TODO
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of plugin. Key bindings and other initialization should be done.
|
||||||
|
"""
|
||||||
|
# an Action menu entry which binds "keybinding" to action ":action"
|
||||||
|
self.commands.append(Command(u'OrgLoggingRecordDoneTime', u'%s ORGMODE.plugins[u"LoggingWork"].action()' % VIM_PY_CALL))
|
||||||
|
self.menu + ActionEntry(u'&Record DONE time', self.commands[-1])
|
173
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Misc.py
Normal file
173
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Misc.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE, apply_count
|
||||||
|
from orgmode.menu import Submenu
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, MODE_VISUAL, MODE_OPERATOR
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class Misc(object):
|
||||||
|
u""" Miscellaneous functionality """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'Misc')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def jump_to_first_character(cls):
|
||||||
|
heading = ORGMODE.get_document().current_heading()
|
||||||
|
if not heading or heading.start_vim != vim.current.window.cursor[0]:
|
||||||
|
vim.eval(u_encode(u'feedkeys("^", "n")'))
|
||||||
|
return
|
||||||
|
|
||||||
|
vim.current.window.cursor = (vim.current.window.cursor[0], heading.level + 1)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def edit_at_first_character(cls):
|
||||||
|
heading = ORGMODE.get_document().current_heading()
|
||||||
|
if not heading or heading.start_vim != vim.current.window.cursor[0]:
|
||||||
|
vim.eval(u_encode(u'feedkeys("I", "n")'))
|
||||||
|
return
|
||||||
|
|
||||||
|
vim.current.window.cursor = (vim.current.window.cursor[0], heading.level + 1)
|
||||||
|
vim.command(u_encode(u'startinsert'))
|
||||||
|
|
||||||
|
# @repeat
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def i_heading(cls, mode=u'visual', selection=u'inner', skip_children=False):
|
||||||
|
u"""
|
||||||
|
inner heading text object
|
||||||
|
"""
|
||||||
|
heading = ORGMODE.get_document().current_heading()
|
||||||
|
if heading:
|
||||||
|
if selection != u'inner':
|
||||||
|
heading = heading if not heading.parent else heading.parent
|
||||||
|
|
||||||
|
line_start, col_start = [int(i) for i in vim.eval(u_encode(u'getpos("\'<")'))[1:3]]
|
||||||
|
line_end, col_end = [int(i) for i in vim.eval(u_encode(u'getpos("\'>")'))[1:3]]
|
||||||
|
|
||||||
|
if mode != u'visual':
|
||||||
|
line_start = vim.current.window.cursor[0]
|
||||||
|
line_end = line_start
|
||||||
|
|
||||||
|
start = line_start
|
||||||
|
end = line_end
|
||||||
|
move_one_character_back = u'' if mode == u'visual' else u'h'
|
||||||
|
|
||||||
|
if heading.start_vim < line_start:
|
||||||
|
start = heading.start_vim
|
||||||
|
if heading.end_vim > line_end and not skip_children:
|
||||||
|
end = heading.end_vim
|
||||||
|
elif heading.end_of_last_child_vim > line_end and skip_children:
|
||||||
|
end = heading.end_of_last_child_vim
|
||||||
|
|
||||||
|
if mode != u'visual' and not vim.current.buffer[end - 1]:
|
||||||
|
end -= 1
|
||||||
|
move_one_character_back = u''
|
||||||
|
|
||||||
|
swap_cursor = u'o' if vim.current.window.cursor[0] == line_start else u''
|
||||||
|
|
||||||
|
if selection == u'inner' and vim.current.window.cursor[0] != line_start:
|
||||||
|
h = ORGMODE.get_document().current_heading()
|
||||||
|
if h:
|
||||||
|
heading = h
|
||||||
|
|
||||||
|
visualmode = u_decode(vim.eval(u'visualmode()')) if mode == u'visual' else u'v'
|
||||||
|
|
||||||
|
if line_start == start and line_start != heading.start_vim:
|
||||||
|
if col_start in (0, 1):
|
||||||
|
vim.command(u_encode(u'normal! %dgg0%s%dgg$%s%s' % (start, visualmode, end, move_one_character_back, swap_cursor)))
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'normal! %dgg0%dl%s%dgg$%s%s' % (start, col_start - 1, visualmode, end, move_one_character_back, swap_cursor)))
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'normal! %dgg0%dl%s%dgg$%s%s' % (start, heading.level + 1, visualmode, end, move_one_character_back, swap_cursor)))
|
||||||
|
|
||||||
|
if selection == u'inner':
|
||||||
|
if mode == u'visual':
|
||||||
|
return u'OrgInnerHeadingVisual' if not skip_children else u'OrgInnerTreeVisual'
|
||||||
|
else:
|
||||||
|
return u'OrgInnerHeadingOperator' if not skip_children else u'OrgInnerTreeOperator'
|
||||||
|
else:
|
||||||
|
if mode == u'visual':
|
||||||
|
return u'OrgOuterHeadingVisual' if not skip_children else u'OrgOuterTreeVisual'
|
||||||
|
else:
|
||||||
|
return u'OrgOuterHeadingOperator' if not skip_children else u'OrgOuterTreeOperator'
|
||||||
|
elif mode == u'visual':
|
||||||
|
vim.command(u_encode(u'normal! gv'))
|
||||||
|
|
||||||
|
# @repeat
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def a_heading(cls, selection=u'inner', skip_children=False):
|
||||||
|
u"""
|
||||||
|
a heading text object
|
||||||
|
"""
|
||||||
|
heading = ORGMODE.get_document().current_heading()
|
||||||
|
if heading:
|
||||||
|
if selection != u'inner':
|
||||||
|
heading = heading if not heading.parent else heading.parent
|
||||||
|
|
||||||
|
line_start, col_start = [int(i) for i in vim.eval(u_encode(u'getpos("\'<")'))[1:3]]
|
||||||
|
line_end, col_end = [int(i) for i in vim.eval(u_encode(u'getpos("\'>")'))[1:3]]
|
||||||
|
|
||||||
|
start = line_start
|
||||||
|
end = line_end
|
||||||
|
|
||||||
|
if heading.start_vim < line_start:
|
||||||
|
start = heading.start_vim
|
||||||
|
if heading.end_vim > line_end and not skip_children:
|
||||||
|
end = heading.end_vim
|
||||||
|
elif heading.end_of_last_child_vim > line_end and skip_children:
|
||||||
|
end = heading.end_of_last_child_vim
|
||||||
|
|
||||||
|
swap_cursor = u'o' if vim.current.window.cursor[0] == line_start else u''
|
||||||
|
|
||||||
|
vim.command(u_encode(u'normal! %dgg%s%dgg$%s' % (start, vim.eval(u_encode(u'visualmode()')), end, swap_cursor)))
|
||||||
|
if selection == u'inner':
|
||||||
|
return u'OrgAInnerHeadingVisual' if not skip_children else u'OrgAInnerTreeVisual'
|
||||||
|
else:
|
||||||
|
return u'OrgAOuterHeadingVisual' if not skip_children else u'OrgAOuterTreeVisual'
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'normal! gv'))
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of plugin. Key bindings and other initialization should be done.
|
||||||
|
"""
|
||||||
|
self.keybindings.append(Keybinding(u'^',
|
||||||
|
Plug(u'OrgJumpToFirstCharacter', u'%s ORGMODE.plugins[u"Misc"].jump_to_first_character()<CR>' % VIM_PY_CALL)))
|
||||||
|
self.keybindings.append(Keybinding(u'I',
|
||||||
|
Plug(u'OrgEditAtFirstCharacter', u'%s ORGMODE.plugins[u"Misc"].edit_at_first_character()<CR>' % VIM_PY_CALL)))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'ih', Plug(u'OrgInnerHeadingVisual', u':<C-u>%s ORGMODE.plugins[u"Misc"].i_heading()<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'ah', Plug(u'OrgAInnerHeadingVisual', u':<C-u>%s ORGMODE.plugins[u"Misc"].a_heading()<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'Oh', Plug(u'OrgOuterHeadingVisual', u':<C-u>%s ORGMODE.plugins[u"Misc"].i_heading(selection=u"outer")<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'OH', Plug(u'OrgAOuterHeadingVisual', u':<C-u>%s ORGMODE.plugins[u"Misc"].a_heading(selection=u"outer")<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'ih', Plug(u'OrgInnerHeadingOperator', u':<C-u>%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator")<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u'ah', u':normal Vah<CR>', mode=MODE_OPERATOR))
|
||||||
|
self.keybindings.append(Keybinding(u'Oh', Plug(u'OrgOuterHeadingOperator', ':<C-u>%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator", selection=u"outer")<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u'OH', u':normal VOH<CR>', mode=MODE_OPERATOR))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'ir', Plug(u'OrgInnerTreeVisual', u':<C-u>%s ORGMODE.plugins[u"Misc"].i_heading(skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'ar', Plug(u'OrgAInnerTreeVisual', u':<C-u>%s ORGMODE.plugins[u"Misc"].a_heading(skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'Or', Plug(u'OrgOuterTreeVisual', u'<:<C-u>%s ORGMODE.plugins[u"Misc"].i_heading(selection=u"outer", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'OR', Plug(u'OrgAOuterTreeVisual', u':<C-u>%s ORGMODE.plugins[u"Misc"].a_heading(selection=u"outer", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'ir', Plug(u'OrgInnerTreeOperator', u':<C-u>%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u'ar', u':normal Var<CR>', mode=MODE_OPERATOR))
|
||||||
|
self.keybindings.append(Keybinding(u'Or', Plug(u'OrgOuterTreeOperator', u':<C-u>%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator", selection=u"outer", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u'OR', u':normal VOR<CR>', mode=MODE_OPERATOR))
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
326
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Navigator.py
Normal file
326
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Navigator.py
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import echo, ORGMODE, apply_count
|
||||||
|
from orgmode.menu import Submenu, ActionEntry
|
||||||
|
from orgmode.keybinding import Keybinding, MODE_VISUAL, MODE_OPERATOR, Plug
|
||||||
|
from orgmode.liborgmode.documents import Direction
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class Navigator(object):
|
||||||
|
u""" Implement navigation in org-mode documents """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
object.__init__(self)
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'&Navigate Headings')
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def parent(cls, mode):
|
||||||
|
u"""
|
||||||
|
Focus parent heading
|
||||||
|
|
||||||
|
:returns: parent heading or None
|
||||||
|
"""
|
||||||
|
heading = ORGMODE.get_document().current_heading()
|
||||||
|
if not heading:
|
||||||
|
if mode == u'visual':
|
||||||
|
vim.command(u_encode(u'normal! gv'))
|
||||||
|
else:
|
||||||
|
echo(u'No heading found')
|
||||||
|
return
|
||||||
|
|
||||||
|
if not heading.parent:
|
||||||
|
if mode == u'visual':
|
||||||
|
vim.command(u_encode(u'normal! gv'))
|
||||||
|
else:
|
||||||
|
echo(u'No parent heading found')
|
||||||
|
return
|
||||||
|
|
||||||
|
p = heading.parent
|
||||||
|
|
||||||
|
if mode == u'visual':
|
||||||
|
cls._change_visual_selection(heading, p, direction=Direction.BACKWARD, parent=True)
|
||||||
|
else:
|
||||||
|
vim.current.window.cursor = (p.start_vim, p.level + 1)
|
||||||
|
return p
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def parent_next_sibling(cls, mode):
|
||||||
|
u"""
|
||||||
|
Focus the parent's next sibling
|
||||||
|
|
||||||
|
:returns: parent's next sibling heading or None
|
||||||
|
"""
|
||||||
|
heading = ORGMODE.get_document().current_heading()
|
||||||
|
if not heading:
|
||||||
|
if mode == u'visual':
|
||||||
|
vim.command(u_encode(u'normal! gv'))
|
||||||
|
else:
|
||||||
|
echo(u'No heading found')
|
||||||
|
return
|
||||||
|
|
||||||
|
if not heading.parent or not heading.parent.next_sibling:
|
||||||
|
if mode == u'visual':
|
||||||
|
vim.command(u_encode(u'normal! gv'))
|
||||||
|
else:
|
||||||
|
echo(u'No parent heading found')
|
||||||
|
return
|
||||||
|
|
||||||
|
ns = heading.parent.next_sibling
|
||||||
|
|
||||||
|
if mode == u'visual':
|
||||||
|
cls._change_visual_selection(heading, ns, direction=Direction.FORWARD, parent=False)
|
||||||
|
elif mode == u'operator':
|
||||||
|
vim.current.window.cursor = (ns.start_vim, 0)
|
||||||
|
else:
|
||||||
|
vim.current.window.cursor = (ns.start_vim, ns.level + 1)
|
||||||
|
return ns
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _change_visual_selection(cls, current_heading, heading, direction=Direction.FORWARD, noheadingfound=False, parent=False):
|
||||||
|
current = vim.current.window.cursor[0]
|
||||||
|
line_start, col_start = [int(i) for i in vim.eval(u_encode(u'getpos("\'<")'))[1:3]]
|
||||||
|
line_end, col_end = [int(i) for i in vim.eval(u_encode(u'getpos("\'>")'))[1:3]]
|
||||||
|
|
||||||
|
f_start = heading.start_vim
|
||||||
|
f_end = heading.end_vim
|
||||||
|
swap_cursor = True
|
||||||
|
|
||||||
|
# << |visual start
|
||||||
|
# selection end >>
|
||||||
|
if current == line_start:
|
||||||
|
if (direction == Direction.FORWARD and line_end < f_start) or noheadingfound and not direction == Direction.BACKWARD:
|
||||||
|
swap_cursor = False
|
||||||
|
|
||||||
|
# focus heading HERE
|
||||||
|
# << |visual start
|
||||||
|
# selection end >>
|
||||||
|
|
||||||
|
# << |visual start
|
||||||
|
# focus heading HERE
|
||||||
|
# selection end >>
|
||||||
|
if f_start < line_start and direction == Direction.BACKWARD:
|
||||||
|
if current_heading.start_vim < line_start and not parent:
|
||||||
|
line_start = current_heading.start_vim
|
||||||
|
else:
|
||||||
|
line_start = f_start
|
||||||
|
|
||||||
|
elif (f_start < line_start or f_start < line_end) and not noheadingfound:
|
||||||
|
line_start = f_start
|
||||||
|
|
||||||
|
# << |visual start
|
||||||
|
# selection end >>
|
||||||
|
# focus heading HERE
|
||||||
|
else:
|
||||||
|
if direction == Direction.FORWARD:
|
||||||
|
if line_end < f_start and not line_start == f_start - 1 and current_heading:
|
||||||
|
# focus end of previous heading instead of beginning of next heading
|
||||||
|
line_start = line_end
|
||||||
|
line_end = f_start - 1
|
||||||
|
else:
|
||||||
|
# focus end of next heading
|
||||||
|
line_start = line_end
|
||||||
|
line_end = f_end
|
||||||
|
elif direction == Direction.BACKWARD:
|
||||||
|
if line_end < f_end:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
line_start = line_end
|
||||||
|
line_end = f_end
|
||||||
|
|
||||||
|
# << visual start
|
||||||
|
# selection end| >>
|
||||||
|
else:
|
||||||
|
# focus heading HERE
|
||||||
|
# << visual start
|
||||||
|
# selection end| >>
|
||||||
|
if line_start > f_start and line_end > f_end and not parent:
|
||||||
|
line_end = f_end
|
||||||
|
swap_cursor = False
|
||||||
|
|
||||||
|
elif (line_start > f_start or line_start == f_start) and \
|
||||||
|
line_end <= f_end and direction == Direction.BACKWARD:
|
||||||
|
line_end = line_start
|
||||||
|
line_start = f_start
|
||||||
|
|
||||||
|
# << visual start
|
||||||
|
# selection end and focus heading end HERE| >>
|
||||||
|
|
||||||
|
# << visual start
|
||||||
|
# focus heading HERE
|
||||||
|
# selection end| >>
|
||||||
|
|
||||||
|
# << visual start
|
||||||
|
# selection end| >>
|
||||||
|
# focus heading HERE
|
||||||
|
else:
|
||||||
|
if direction == Direction.FORWARD:
|
||||||
|
if line_end < f_start - 1:
|
||||||
|
# focus end of previous heading instead of beginning of next heading
|
||||||
|
line_end = f_start - 1
|
||||||
|
else:
|
||||||
|
# focus end of next heading
|
||||||
|
line_end = f_end
|
||||||
|
else:
|
||||||
|
line_end = f_end
|
||||||
|
swap_cursor = False
|
||||||
|
|
||||||
|
move_col_start = u'%dl' % (col_start - 1) if (col_start - 1) > 0 and (col_start - 1) < 2000000000 else u''
|
||||||
|
move_col_end = u'%dl' % (col_end - 1) if (col_end - 1) > 0 and (col_end - 1) < 2000000000 else u''
|
||||||
|
swap = u'o' if swap_cursor else u''
|
||||||
|
|
||||||
|
vim.command(u_encode(u'normal! %dgg%s%s%dgg%s%s' % (line_start, move_col_start, vim.eval(u_encode(u'visualmode()')), line_end, move_col_end, swap)))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _focus_heading(cls, mode, direction=Direction.FORWARD, skip_children=False):
|
||||||
|
u"""
|
||||||
|
Focus next or previous heading in the given direction
|
||||||
|
|
||||||
|
:direction: True for next heading, False for previous heading
|
||||||
|
:returns: next heading or None
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
current_heading = d.current_heading()
|
||||||
|
heading = current_heading
|
||||||
|
focus_heading = None
|
||||||
|
# FIXME this is just a piece of really ugly and unmaintainable code. It
|
||||||
|
# should be rewritten
|
||||||
|
if not heading:
|
||||||
|
if direction == Direction.FORWARD and d.headings \
|
||||||
|
and vim.current.window.cursor[0] < d.headings[0].start_vim:
|
||||||
|
# the cursor is in the meta information are, therefore focus
|
||||||
|
# first heading
|
||||||
|
focus_heading = d.headings[0]
|
||||||
|
if not (heading or focus_heading):
|
||||||
|
if mode == u'visual':
|
||||||
|
# restore visual selection when no heading was found
|
||||||
|
vim.command(u_encode(u'normal! gv'))
|
||||||
|
else:
|
||||||
|
echo(u'No heading found')
|
||||||
|
return
|
||||||
|
elif direction == Direction.BACKWARD:
|
||||||
|
if vim.current.window.cursor[0] != heading.start_vim:
|
||||||
|
# the cursor is in the body of the current heading, therefore
|
||||||
|
# the current heading will be focused
|
||||||
|
if mode == u'visual':
|
||||||
|
line_start, col_start = [int(i) for i in
|
||||||
|
vim.eval(u_encode(u'getpos("\'<")'))[1:3]]
|
||||||
|
line_end, col_end = [int(i) for i in vim.eval(u_encode(u'getpos("\'>")'))[1:3]]
|
||||||
|
if line_start >= heading.start_vim and line_end > heading.start_vim:
|
||||||
|
focus_heading = heading
|
||||||
|
else:
|
||||||
|
focus_heading = heading
|
||||||
|
|
||||||
|
# so far no heading has been found that the next focus should be on
|
||||||
|
if not focus_heading:
|
||||||
|
if not skip_children and direction == Direction.FORWARD and heading.children:
|
||||||
|
focus_heading = heading.children[0]
|
||||||
|
elif direction == Direction.FORWARD and heading.next_sibling:
|
||||||
|
focus_heading = heading.next_sibling
|
||||||
|
elif direction == Direction.BACKWARD and heading.previous_sibling:
|
||||||
|
focus_heading = heading.previous_sibling
|
||||||
|
if not skip_children:
|
||||||
|
while focus_heading.children:
|
||||||
|
focus_heading = focus_heading.children[-1]
|
||||||
|
else:
|
||||||
|
if direction == Direction.FORWARD:
|
||||||
|
focus_heading = current_heading.next_heading
|
||||||
|
else:
|
||||||
|
focus_heading = current_heading.previous_heading
|
||||||
|
|
||||||
|
noheadingfound = False
|
||||||
|
if not focus_heading:
|
||||||
|
if mode in (u'visual', u'operator'):
|
||||||
|
# the cursor seems to be on the last or first heading of this
|
||||||
|
# document and performes another next/previous operation
|
||||||
|
focus_heading = heading
|
||||||
|
noheadingfound = True
|
||||||
|
else:
|
||||||
|
if direction == Direction.FORWARD:
|
||||||
|
echo(u'Already focussing last heading')
|
||||||
|
else:
|
||||||
|
echo(u'Already focussing first heading')
|
||||||
|
return
|
||||||
|
|
||||||
|
if mode == u'visual':
|
||||||
|
cls._change_visual_selection(current_heading, focus_heading, direction=direction, noheadingfound=noheadingfound)
|
||||||
|
elif mode == u'operator':
|
||||||
|
if direction == Direction.FORWARD and vim.current.window.cursor[0] >= focus_heading.start_vim:
|
||||||
|
vim.current.window.cursor = (focus_heading.end_vim, len(u_decode(vim.current.buffer[focus_heading.end])))
|
||||||
|
else:
|
||||||
|
vim.current.window.cursor = (focus_heading.start_vim, 0)
|
||||||
|
else:
|
||||||
|
vim.current.window.cursor = (focus_heading.start_vim, focus_heading.level + 1)
|
||||||
|
if noheadingfound:
|
||||||
|
return
|
||||||
|
return focus_heading
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def previous(cls, mode, skip_children=False):
|
||||||
|
u"""
|
||||||
|
Focus previous heading
|
||||||
|
"""
|
||||||
|
return cls._focus_heading(mode, direction=Direction.BACKWARD, skip_children=skip_children)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def next(cls, mode, skip_children=False):
|
||||||
|
u"""
|
||||||
|
Focus next heading
|
||||||
|
"""
|
||||||
|
return cls._focus_heading(mode, direction=Direction.FORWARD, skip_children=skip_children)
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
# normal mode
|
||||||
|
self.keybindings.append(Keybinding(u'g{', Plug('OrgJumpToParentNormal',
|
||||||
|
u'%s ORGMODE.plugins[u"Navigator"].parent(mode=u"normal")<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Up', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'g}',
|
||||||
|
Plug('OrgJumpToParentsSiblingNormal', u'%s ORGMODE.plugins[u"Navigator"].parent_next_sibling(mode=u"normal")<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Down', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'{',
|
||||||
|
Plug(u'OrgJumpToPreviousNormal', u'%s ORGMODE.plugins[u"Navigator"].previous(mode=u"normal")<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Previous', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u'}', Plug(u'OrgJumpToNextNormal',
|
||||||
|
u'%s ORGMODE.plugins[u"Navigator"].next(mode=u"normal")<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Next', self.keybindings[-1])
|
||||||
|
|
||||||
|
# visual mode
|
||||||
|
self.keybindings.append(Keybinding(u'g{', Plug(u'OrgJumpToParentVisual', u'<Esc>:<C-u>%s ORGMODE.plugins[u"Navigator"].parent(mode=u"visual")<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'g}', Plug('OrgJumpToParentsSiblingVisual', u'<Esc>:<C-u>%s ORGMODE.plugins[u"Navigator"].parent_next_sibling(mode=u"visual")<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'{', Plug(u'OrgJumpToPreviousVisual', u'<Esc>:<C-u>%s ORGMODE.plugins[u"Navigator"].previous(mode=u"visual")<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u'}', Plug(u'OrgJumpToNextVisual', u'<Esc>:<C-u>%s ORGMODE.plugins[u"Navigator"].next(mode=u"visual")<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
|
||||||
|
# operator-pending mode
|
||||||
|
self.keybindings.append(Keybinding(u'g{', Plug(u'OrgJumpToParentOperator', u':<C-u>%s ORGMODE.plugins[u"Navigator"].parent(mode=u"operator")<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u'g}', Plug('OrgJumpToParentsSiblingOperator', u':<C-u>%s ORGMODE.plugins[u"Navigator"].parent_next_sibling(mode=u"operator")<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u'{', Plug(u'OrgJumpToPreviousOperator', u':<C-u>%s ORGMODE.plugins[u"Navigator"].previous(mode=u"operator")<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u'}', Plug(u'OrgJumpToNextOperator', u':<C-u>%s ORGMODE.plugins[u"Navigator"].next(mode=u"operator")<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
|
||||||
|
# section wise movement (skip children)
|
||||||
|
# normal mode
|
||||||
|
self.keybindings.append(Keybinding(u'[[',
|
||||||
|
Plug(u'OrgJumpToPreviousSkipChildrenNormal',
|
||||||
|
u'%s ORGMODE.plugins[u"Navigator"].previous(mode=u"normal", skip_children=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'Ne&xt Same Level', self.keybindings[-1])
|
||||||
|
self.keybindings.append(Keybinding(u']]',
|
||||||
|
Plug(u'OrgJumpToNextSkipChildrenNormal',
|
||||||
|
u'%s ORGMODE.plugins[u"Navigator"].next(mode=u"normal", skip_children=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'Pre&vious Same Level', self.keybindings[-1])
|
||||||
|
|
||||||
|
# visual mode
|
||||||
|
self.keybindings.append(Keybinding(u'[[', Plug(u'OrgJumpToPreviousSkipChildrenVisual', u'<Esc>:<C-u>%s ORGMODE.plugins[u"Navigator"].previous(mode=u"visual", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
self.keybindings.append(Keybinding(u']]', Plug(u'OrgJumpToNextSkipChildrenVisual', u'<Esc>:<C-u>%s ORGMODE.plugins[u"Navigator"].next(mode=u"visual", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_VISUAL)))
|
||||||
|
|
||||||
|
# operator-pending mode
|
||||||
|
self.keybindings.append(Keybinding(u'[[', Plug(u'OrgJumpToPreviousSkipChildrenOperator', u':<C-u>%s ORGMODE.plugins[u"Navigator"].previous(mode=u"operator", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
self.keybindings.append(Keybinding(u']]', Plug(u'OrgJumpToNextSkipChildrenOperator', u':<C-u>%s ORGMODE.plugins[u"Navigator"].next(mode=u"operator", skip_children=True)<CR>' % VIM_PY_CALL, mode=MODE_OPERATOR)))
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
181
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/ShowHide.py
Normal file
181
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/ShowHide.py
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode.liborgmode.headings import Heading
|
||||||
|
from orgmode._vim import ORGMODE, apply_count
|
||||||
|
from orgmode import settings
|
||||||
|
from orgmode.menu import Submenu, ActionEntry
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, MODE_NORMAL
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.xrange_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class ShowHide(object):
|
||||||
|
u""" Show Hide plugin """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'&Show Hide')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _fold_depth(cls, h):
|
||||||
|
""" Find the deepest level of open folds
|
||||||
|
|
||||||
|
:h: Heading
|
||||||
|
:returns: Tuple (int - level of open folds, boolean - found fold) or None if h is not a Heading
|
||||||
|
"""
|
||||||
|
if not isinstance(h, Heading):
|
||||||
|
return
|
||||||
|
|
||||||
|
if int(vim.eval(u_encode(u'foldclosed(%d)' % h.start_vim))) != -1:
|
||||||
|
return (h.number_of_parents, True)
|
||||||
|
|
||||||
|
res = [h.number_of_parents + 1]
|
||||||
|
found = False
|
||||||
|
for c in h.children:
|
||||||
|
d, f = cls._fold_depth(c)
|
||||||
|
res.append(d)
|
||||||
|
found |= f
|
||||||
|
|
||||||
|
return (max(res), found)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def toggle_folding(cls, reverse=False):
|
||||||
|
u""" Toggle folding similar to the way orgmode does
|
||||||
|
|
||||||
|
This is just a convenience function, don't hesitate to use the z*
|
||||||
|
keybindings vim offers to deal with folding!
|
||||||
|
|
||||||
|
:reverse: If False open folding by one level otherwise close it by one.
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
heading = d.current_heading()
|
||||||
|
if not heading:
|
||||||
|
vim.eval(u_encode(u'feedkeys("<Tab>", "n")'))
|
||||||
|
return
|
||||||
|
|
||||||
|
cursor = vim.current.window.cursor[:]
|
||||||
|
|
||||||
|
if int(vim.eval(u_encode(u'foldclosed(%d)' % heading.start_vim))) != -1:
|
||||||
|
if not reverse:
|
||||||
|
# open closed fold
|
||||||
|
p = heading.number_of_parents
|
||||||
|
if not p:
|
||||||
|
p = heading.level
|
||||||
|
vim.command(u_encode(u'normal! %dzo' % p))
|
||||||
|
else:
|
||||||
|
# reverse folding opens all folds under the cursor
|
||||||
|
vim.command(u_encode(u'%d,%dfoldopen!' % (heading.start_vim, heading.end_of_last_child_vim)))
|
||||||
|
vim.current.window.cursor = cursor
|
||||||
|
return heading
|
||||||
|
|
||||||
|
def open_fold(h):
|
||||||
|
if h.number_of_parents <= open_depth:
|
||||||
|
vim.command(u_encode(u'normal! %dgg%dzo' % (h.start_vim, open_depth)))
|
||||||
|
for c in h.children:
|
||||||
|
open_fold(c)
|
||||||
|
|
||||||
|
def close_fold(h):
|
||||||
|
for c in h.children:
|
||||||
|
close_fold(c)
|
||||||
|
if h.number_of_parents >= open_depth - 1 and \
|
||||||
|
int(vim.eval(u_encode(u'foldclosed(%d)' % h.start_vim))) == -1:
|
||||||
|
vim.command(u_encode(u'normal! %dggzc' % (h.start_vim, )))
|
||||||
|
|
||||||
|
# find deepest fold
|
||||||
|
open_depth, found_fold = cls._fold_depth(heading)
|
||||||
|
|
||||||
|
if not reverse:
|
||||||
|
# recursively open folds
|
||||||
|
if found_fold:
|
||||||
|
for child in heading.children:
|
||||||
|
open_fold(child)
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'%d,%dfoldclose!' % (heading.start_vim, heading.end_of_last_child_vim)))
|
||||||
|
|
||||||
|
if heading.number_of_parents:
|
||||||
|
# restore cursor position, it might have been changed by open_fold
|
||||||
|
vim.current.window.cursor = cursor
|
||||||
|
|
||||||
|
p = heading.number_of_parents
|
||||||
|
if not p:
|
||||||
|
p = heading.level
|
||||||
|
# reopen fold again beacause the former closing of the fold closed all levels, including parents!
|
||||||
|
vim.command(u_encode(u'normal! %dzo' % (p, )))
|
||||||
|
else:
|
||||||
|
# close the last level of folds
|
||||||
|
close_fold(heading)
|
||||||
|
|
||||||
|
# restore cursor position
|
||||||
|
vim.current.window.cursor = cursor
|
||||||
|
return heading
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@apply_count
|
||||||
|
def global_toggle_folding(cls, reverse=False):
|
||||||
|
""" Toggle folding globally
|
||||||
|
|
||||||
|
:reverse: If False open folding by one level otherwise close it by one.
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
if reverse:
|
||||||
|
foldlevel = int(vim.eval(u_encode(u'&foldlevel')))
|
||||||
|
if foldlevel == 0:
|
||||||
|
# open all folds because the user tries to close folds beyound 0
|
||||||
|
vim.eval(u_encode(u'feedkeys("zR", "n")'))
|
||||||
|
else:
|
||||||
|
# vim can reduce the foldlevel on its own
|
||||||
|
vim.eval(u_encode(u'feedkeys("zm", "n")'))
|
||||||
|
else:
|
||||||
|
found = False
|
||||||
|
for h in d.headings:
|
||||||
|
res = cls._fold_depth(h)
|
||||||
|
if res:
|
||||||
|
found = res[1]
|
||||||
|
if found:
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
# no fold found and the user tries to advance the fold level
|
||||||
|
# beyond maximum so close everything
|
||||||
|
vim.eval(u_encode(u'feedkeys("zM", "n")'))
|
||||||
|
else:
|
||||||
|
# fold found, vim can increase the foldlevel on its own
|
||||||
|
vim.eval(u_encode(u'feedkeys("zr", "n")'))
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of plugin. Key bindings and other initialization should be done.
|
||||||
|
"""
|
||||||
|
# register plug
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<Tab>',
|
||||||
|
Plug(u'OrgToggleFoldingNormal', u'%s ORGMODE.plugins[u"ShowHide"].toggle_folding()<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&Cycle Visibility', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<S-Tab>',
|
||||||
|
Plug(u'OrgToggleFoldingReverse', u'%s ORGMODE.plugins[u"ShowHide"].toggle_folding(reverse=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'Cycle Visibility &Reverse', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>.',
|
||||||
|
Plug(u'OrgGlobalToggleFoldingNormal', u'%s ORGMODE.plugins[u"ShowHide"].global_toggle_folding()<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'Cycle Visibility &Globally', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>,',
|
||||||
|
Plug(u'OrgGlobalToggleFoldingReverse',
|
||||||
|
u'%s ORGMODE.plugins[u"ShowHide"].global_toggle_folding(reverse=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'Cycle Visibility Reverse G&lobally', self.keybindings[-1])
|
||||||
|
|
||||||
|
for i in range(0, 10):
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>%d' % (i, ), u'zM:set fdl=%d<CR>' % i, mode=MODE_NORMAL))
|
|
@ -0,0 +1,215 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE, repeat
|
||||||
|
from orgmode.menu import Submenu, ActionEntry
|
||||||
|
from orgmode.keybinding import Keybinding, Plug, Command
|
||||||
|
from orgmode import settings
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
class TagsProperties(object):
|
||||||
|
u""" TagsProperties plugin """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'&TAGS and Properties')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
# commands for this plugin
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def complete_tags(cls):
|
||||||
|
u""" build a list of tags and store it in variable b:org_tag_completion
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
heading = d.current_heading()
|
||||||
|
if not heading:
|
||||||
|
return
|
||||||
|
|
||||||
|
leading_portion = u_decode(vim.eval(u'a:ArgLead'))
|
||||||
|
cursor = int(vim.eval(u'a:CursorPos'))
|
||||||
|
|
||||||
|
# extract currently completed tag
|
||||||
|
idx_orig = leading_portion.rfind(u':', 0, cursor)
|
||||||
|
if idx_orig == -1:
|
||||||
|
idx = 0
|
||||||
|
else:
|
||||||
|
idx = idx_orig
|
||||||
|
|
||||||
|
current_tag = leading_portion[idx: cursor].lstrip(u':')
|
||||||
|
head = leading_portion[:idx + 1]
|
||||||
|
if idx_orig == -1:
|
||||||
|
head = u''
|
||||||
|
tail = leading_portion[cursor:]
|
||||||
|
|
||||||
|
# extract all tags of the current file
|
||||||
|
all_tags = set()
|
||||||
|
for h in d.all_headings():
|
||||||
|
for t in h.tags:
|
||||||
|
all_tags.add(t)
|
||||||
|
|
||||||
|
ignorecase = bool(int(settings.get(u'org_tag_completion_ignorecase', int(vim.eval(u'&ignorecase')))))
|
||||||
|
possible_tags = []
|
||||||
|
# TODO current tags never used...
|
||||||
|
current_tags = heading.tags
|
||||||
|
for t in all_tags:
|
||||||
|
if ignorecase:
|
||||||
|
if t.lower().startswith(current_tag.lower()):
|
||||||
|
possible_tags.append(t)
|
||||||
|
elif t.startswith(current_tag):
|
||||||
|
possible_tags.append(t)
|
||||||
|
|
||||||
|
vim.command(u_encode(u'let b:org_complete_tags = [%s]' % u', '.join([u'"%s%s:%s"' % (head, i, tail) for i in possible_tags])))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@repeat
|
||||||
|
def set_tags(cls):
|
||||||
|
u""" Set tags for current heading
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
heading = d.current_heading()
|
||||||
|
if not heading:
|
||||||
|
return
|
||||||
|
|
||||||
|
# retrieve tags
|
||||||
|
res = None
|
||||||
|
if heading.tags:
|
||||||
|
res = vim.eval(u'input("Tags: ", ":%s:", "customlist,Org_complete_tags")' % u':'.join(heading.tags))
|
||||||
|
else:
|
||||||
|
res = vim.eval(u'input("Tags: ", "", "customlist,Org_complete_tags")')
|
||||||
|
|
||||||
|
if res is None:
|
||||||
|
# user pressed <Esc> abort any further processing
|
||||||
|
return
|
||||||
|
|
||||||
|
# remove empty tags
|
||||||
|
heading.tags = [x for x in u_decode(res).strip().strip(u':').split(u':') if x.strip() != u'']
|
||||||
|
|
||||||
|
d.write()
|
||||||
|
|
||||||
|
return u'OrgSetTags'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find_tags(cls):
|
||||||
|
""" Find tags in current file
|
||||||
|
"""
|
||||||
|
tags = vim.eval(u'input("Find Tags: ", "", "customlist,Org_complete_tags")')
|
||||||
|
if tags is None:
|
||||||
|
# user pressed <Esc> abort any further processing
|
||||||
|
return
|
||||||
|
|
||||||
|
tags = [x for x in u_decode(tags).strip().strip(u':').split(u':') if x.strip() != u'']
|
||||||
|
if tags:
|
||||||
|
searchstring = u'\\('
|
||||||
|
first = True
|
||||||
|
for t1 in tags:
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
searchstring += u'%s' % t1
|
||||||
|
else:
|
||||||
|
searchstring += u'\\|%s' % t1
|
||||||
|
|
||||||
|
for t2 in tags:
|
||||||
|
if t1 == t2:
|
||||||
|
continue
|
||||||
|
searchstring += u'\\(:[a-zA-Z:]*\\)\?:%s' % t2
|
||||||
|
searchstring += u'\\)'
|
||||||
|
|
||||||
|
vim.command(u'/\\zs:%s:\\ze' % searchstring)
|
||||||
|
return u'OrgFindTags'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def realign_tags(cls):
|
||||||
|
u"""
|
||||||
|
Updates tags when user finished editing a heading
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document(allow_dirty=True)
|
||||||
|
heading = d.find_current_heading()
|
||||||
|
if not heading:
|
||||||
|
return
|
||||||
|
|
||||||
|
if vim.current.window.cursor[0] == heading.start_vim:
|
||||||
|
heading.set_dirty_heading()
|
||||||
|
d.write_heading(heading, including_children=False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def realign_all_tags(cls):
|
||||||
|
u"""
|
||||||
|
Updates tags when user finishes editing a heading
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
for heading in d.all_headings():
|
||||||
|
heading.set_dirty_heading()
|
||||||
|
|
||||||
|
d.write()
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of plugin. Key bindings and other initialization should be done.
|
||||||
|
"""
|
||||||
|
# an Action menu entry which binds "keybinding" to action ":action"
|
||||||
|
settings.set(u'org_tag_column', vim.eval(u'&textwidth'))
|
||||||
|
settings.set(u'org_tag_completion_ignorecase', int(vim.eval(u'&ignorecase')))
|
||||||
|
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgSetTags',
|
||||||
|
u'%s ORGMODE.plugins[u"TagsProperties"].set_tags()' % VIM_PY_CALL)
|
||||||
|
self.commands.append(cmd)
|
||||||
|
keybinding = Keybinding(
|
||||||
|
u'<localleader>st',
|
||||||
|
Plug(u'OrgSetTags', cmd))
|
||||||
|
self.keybindings.append(keybinding)
|
||||||
|
self.menu + ActionEntry(u'Set &Tags', keybinding)
|
||||||
|
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgFindTags',
|
||||||
|
u'%s ORGMODE.plugins[u"TagsProperties"].find_tags()' % VIM_PY_CALL)
|
||||||
|
self.commands.append(cmd)
|
||||||
|
keybinding = Keybinding(
|
||||||
|
u'<localleader>ft',
|
||||||
|
Plug(u'OrgFindTags', cmd))
|
||||||
|
self.keybindings.append(keybinding)
|
||||||
|
self.menu + ActionEntry(u'&Find Tags', keybinding)
|
||||||
|
|
||||||
|
cmd = Command(
|
||||||
|
u'OrgTagsRealign',
|
||||||
|
u"%s ORGMODE.plugins[u'TagsProperties'].realign_all_tags()" % VIM_PY_CALL)
|
||||||
|
self.commands.append(cmd)
|
||||||
|
|
||||||
|
# workaround to align tags when user is leaving insert mode
|
||||||
|
vim.command(u_encode(u"""function Org_complete_tags(ArgLead, CmdLine, CursorPos)
|
||||||
|
python << EOF
|
||||||
|
ORGMODE.plugins[u'TagsProperties'].complete_tags()
|
||||||
|
EOF
|
||||||
|
if exists('b:org_complete_tags')
|
||||||
|
let tmp = b:org_complete_tags
|
||||||
|
unlet b:org_complete_tags
|
||||||
|
return tmp
|
||||||
|
else
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
endfunction"""))
|
||||||
|
|
||||||
|
vim.command(u_encode(u"""function Org_realign_tags_on_insert_leave()
|
||||||
|
if !exists('b:org_complete_tag_on_insertleave_au')
|
||||||
|
:au orgmode InsertLeave <buffer> %s ORGMODE.plugins[u'TagsProperties'].realign_tags()
|
||||||
|
let b:org_complete_tag_on_insertleave_au = 1
|
||||||
|
endif
|
||||||
|
endfunction""" % VIM_PY_CALL))
|
||||||
|
|
||||||
|
# this is for all org files opened after this file
|
||||||
|
vim.command(u_encode(u"au orgmode FileType org call Org_realign_tags_on_insert_leave()"))
|
||||||
|
# this is for the current file
|
||||||
|
vim.command(u_encode(u"call Org_realign_tags_on_insert_leave()"))
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
345
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Todo.py
Normal file
345
pack/acp/start/vim-orgmode/ftplugin/orgmode/plugins/Todo.py
Normal file
|
@ -0,0 +1,345 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
import itertools as it
|
||||||
|
|
||||||
|
from orgmode._vim import echom, ORGMODE, apply_count, repeat, realign_tags
|
||||||
|
from orgmode import settings
|
||||||
|
from orgmode.liborgmode.base import Direction
|
||||||
|
from orgmode.menu import Submenu, ActionEntry
|
||||||
|
from orgmode.keybinding import Keybinding, Plug
|
||||||
|
from orgmode.exceptions import PluginError
|
||||||
|
|
||||||
|
# temporary todo states for differnent orgmode buffers
|
||||||
|
ORGTODOSTATES = {}
|
||||||
|
|
||||||
|
from orgmode.py3compat.xrange_compatibility import *
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
from orgmode.py3compat.py_py3_string import *
|
||||||
|
|
||||||
|
|
||||||
|
def split_access_key(t, sub=None):
|
||||||
|
u""" Split access key
|
||||||
|
|
||||||
|
Args:
|
||||||
|
t (str): Todo state
|
||||||
|
sub: A value that will be returned instead of access key if there was
|
||||||
|
not access key
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: Todo state and access key separated (TODO, ACCESS_KEY)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> split_access_key('TODO(t)')
|
||||||
|
>>> ('TODO', '(t)')
|
||||||
|
>>> split_access_key('WANT', sub='(hi)')
|
||||||
|
>>> ('WANT', '(hi)')
|
||||||
|
"""
|
||||||
|
if type(t) != unicode:
|
||||||
|
echom("String must be unicode")
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
idx = t.find(u'(')
|
||||||
|
|
||||||
|
v, k = (t, sub)
|
||||||
|
if idx != -1 and t[idx + 1:-1]:
|
||||||
|
v, k = (t[:idx], t[idx + 1:-1])
|
||||||
|
return (v, k)
|
||||||
|
|
||||||
|
|
||||||
|
class Todo(object):
|
||||||
|
u"""
|
||||||
|
Todo plugin.
|
||||||
|
|
||||||
|
Description taken from orgmode.org:
|
||||||
|
|
||||||
|
You can use TODO keywords to indicate different sequential states in the
|
||||||
|
process of working on an item, for example:
|
||||||
|
|
||||||
|
["TODO", "FEEDBACK", "VERIFY", "|", "DONE", "DELEGATED"]
|
||||||
|
|
||||||
|
The vertical bar separates the TODO keywords (states that need action) from
|
||||||
|
the DONE states (which need no further action). If you don't provide the
|
||||||
|
separator bar, the last state is used as the DONE state. With this setup,
|
||||||
|
the command ``,d`` will cycle an entry from TODO to FEEDBACK, then to
|
||||||
|
VERIFY, and finally to DONE and DELEGATED.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
u""" Initialize plugin """
|
||||||
|
object.__init__(self)
|
||||||
|
# menu entries this plugin should create
|
||||||
|
self.menu = ORGMODE.orgmenu + Submenu(u'&TODO Lists')
|
||||||
|
|
||||||
|
# key bindings for this plugin
|
||||||
|
# key bindings are also registered through the menu so only additional
|
||||||
|
# bindings should be put in this variable
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _process_all_states(cls, all_states):
|
||||||
|
u""" verify if states defined by user is valid.
|
||||||
|
Return cleaned_todo and flattened if is. Raise Exception if not.
|
||||||
|
Valid checking:
|
||||||
|
* no two state share a same name
|
||||||
|
"""
|
||||||
|
# TODO Write tests. -- Ron89
|
||||||
|
cleaned_todos = [[
|
||||||
|
split_access_key(todo)[0] for todo in it.chain.from_iterable(x)]
|
||||||
|
for x in all_states] + [[None]]
|
||||||
|
|
||||||
|
flattened_todos = list(it.chain.from_iterable(cleaned_todos))
|
||||||
|
if len(flattened_todos) != len(set(flattened_todos)):
|
||||||
|
raise PluginError(u"Duplicate names detected in TODO keyword list. Please examine `g/b:org_todo_keywords`")
|
||||||
|
# TODO This is the case when there are 2 todo states with the same
|
||||||
|
# name. It should be handled by making a simple class to hold TODO
|
||||||
|
# states, which would avoid mixing 2 todo states with the same name
|
||||||
|
# since they would have a different reference (but same content),
|
||||||
|
# albeit this can fail because python optimizes short strings (i.e.
|
||||||
|
# they hold the same ref) so care should be taken in implementation
|
||||||
|
return (cleaned_todos, flattened_todos)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_next_state(
|
||||||
|
cls, current_state, all_states, direction=Direction.FORWARD,
|
||||||
|
next_set=False):
|
||||||
|
u""" Get the next todo state
|
||||||
|
|
||||||
|
Args:
|
||||||
|
current_state (str): The current todo state
|
||||||
|
all_states (list): A list containing all todo states within
|
||||||
|
sublists. The todo states may contain access keys
|
||||||
|
direction: Direction of state or keyword set change (forward or
|
||||||
|
backward)
|
||||||
|
next_set: Advance to the next keyword set in defined direction.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str or None: next todo state, or None if there is no next state.
|
||||||
|
|
||||||
|
Note: all_states should have the form of:
|
||||||
|
[(['TODO(t)'], ['DONE(d)']),
|
||||||
|
(['REPORT(r)', 'BUG(b)', 'KNOWNCAUSE(k)'], ['FIXED(f)']),
|
||||||
|
([], ['CANCELED(c)'])]
|
||||||
|
"""
|
||||||
|
cleaned_todos, flattened_todos = cls._process_all_states(all_states)
|
||||||
|
|
||||||
|
# backward direction should really be -1 not 2
|
||||||
|
next_dir = -1 if direction == Direction.BACKWARD else 1
|
||||||
|
# work only with top level index
|
||||||
|
if next_set:
|
||||||
|
top_set = next((
|
||||||
|
todo_set[0] for todo_set in enumerate(cleaned_todos)
|
||||||
|
if current_state in todo_set[1]), -1)
|
||||||
|
ind = (top_set + next_dir) % len(cleaned_todos)
|
||||||
|
if ind != len(cleaned_todos) - 1:
|
||||||
|
echom("Using set: %s" % str(all_states[ind]))
|
||||||
|
else:
|
||||||
|
echom("Keyword removed.")
|
||||||
|
return cleaned_todos[ind][0]
|
||||||
|
# No next set, cycle around everything
|
||||||
|
else:
|
||||||
|
ind = next((
|
||||||
|
todo_iter[0] for todo_iter in enumerate(flattened_todos)
|
||||||
|
if todo_iter[1] == current_state), -1)
|
||||||
|
return flattened_todos[(ind + next_dir) % len(flattened_todos)]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@realign_tags
|
||||||
|
@repeat
|
||||||
|
@apply_count
|
||||||
|
def toggle_todo_state(
|
||||||
|
cls, direction=Direction.FORWARD, interactive=False, next_set=False):
|
||||||
|
u""" Toggle state of TODO item
|
||||||
|
|
||||||
|
:returns: The changed heading
|
||||||
|
"""
|
||||||
|
d = ORGMODE.get_document(allow_dirty=True)
|
||||||
|
|
||||||
|
# get heading
|
||||||
|
heading = d.find_current_heading()
|
||||||
|
if not heading:
|
||||||
|
vim.eval(u'feedkeys("^", "n")')
|
||||||
|
return
|
||||||
|
|
||||||
|
todo_states = d.get_todo_states(strip_access_key=False)
|
||||||
|
# get todo states
|
||||||
|
if not todo_states:
|
||||||
|
echom(u'No todo keywords configured.')
|
||||||
|
return
|
||||||
|
|
||||||
|
current_state = heading.todo
|
||||||
|
|
||||||
|
# get new state interactively
|
||||||
|
if interactive:
|
||||||
|
# determine position of the interactive prompt
|
||||||
|
prompt_pos = settings.get(u'org_todo_prompt_position', u'botright')
|
||||||
|
if prompt_pos not in [u'botright', u'topleft']:
|
||||||
|
prompt_pos = u'botright'
|
||||||
|
|
||||||
|
# pass todo states to new window
|
||||||
|
ORGTODOSTATES[d.bufnr] = todo_states
|
||||||
|
settings.set(
|
||||||
|
u'org_current_state_%d' % d.bufnr,
|
||||||
|
current_state if current_state is not None else u'', overwrite=True)
|
||||||
|
todo_buffer_exists = bool(int(vim.eval(u_encode(
|
||||||
|
u'bufexists("org:todo/%d")' % (d.bufnr, )))))
|
||||||
|
if todo_buffer_exists:
|
||||||
|
# if the buffer already exists, reuse it
|
||||||
|
vim.command(u_encode(
|
||||||
|
u'%s sbuffer org:todo/%d' % (prompt_pos, d.bufnr, )))
|
||||||
|
else:
|
||||||
|
# create a new window
|
||||||
|
vim.command(u_encode(
|
||||||
|
u'keepalt %s %dsplit org:todo/%d' % (prompt_pos, len(todo_states), d.bufnr)))
|
||||||
|
else:
|
||||||
|
new_state = Todo._get_next_state(
|
||||||
|
current_state, todo_states, direction=direction,
|
||||||
|
next_set=next_set)
|
||||||
|
|
||||||
|
cls.set_todo_state(new_state)
|
||||||
|
|
||||||
|
# plug
|
||||||
|
plug = u'OrgTodoForward'
|
||||||
|
if direction == Direction.BACKWARD:
|
||||||
|
plug = u'OrgTodoBackward'
|
||||||
|
|
||||||
|
return plug
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_todo_state(cls, state):
|
||||||
|
u""" Set todo state for buffer.
|
||||||
|
|
||||||
|
:bufnr: Number of buffer the todo state should be updated for
|
||||||
|
:state: The new todo state
|
||||||
|
"""
|
||||||
|
lineno, colno = vim.current.window.cursor
|
||||||
|
d = ORGMODE.get_document(allow_dirty=True)
|
||||||
|
heading = d.find_current_heading()
|
||||||
|
|
||||||
|
if not heading:
|
||||||
|
return
|
||||||
|
|
||||||
|
current_state = heading.todo
|
||||||
|
|
||||||
|
# set new headline
|
||||||
|
heading.todo = state
|
||||||
|
d.write_heading(heading)
|
||||||
|
|
||||||
|
# move cursor along with the inserted state only when current position
|
||||||
|
# is in the heading; otherwite do nothing
|
||||||
|
if heading.start_vim == lineno and colno > heading.level:
|
||||||
|
if current_state is not None and \
|
||||||
|
colno <= heading.level + len(current_state):
|
||||||
|
# the cursor is actually on the todo keyword
|
||||||
|
# move it back to the beginning of the keyword in that case
|
||||||
|
vim.current.window.cursor = (lineno, heading.level + 1)
|
||||||
|
else:
|
||||||
|
# the cursor is somewhere in the text, move it along
|
||||||
|
if current_state is None and state is None:
|
||||||
|
offset = 0
|
||||||
|
elif current_state is None and state is not None:
|
||||||
|
offset = len(state) + 1
|
||||||
|
elif current_state is not None and state is None:
|
||||||
|
offset = -len(current_state) - 1
|
||||||
|
else:
|
||||||
|
offset = len(state) - len(current_state)
|
||||||
|
vim.current.window.cursor = (lineno, colno + offset)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def init_org_todo(cls):
|
||||||
|
u""" Initialize org todo selection window.
|
||||||
|
"""
|
||||||
|
bufnr = int(vim.current.buffer.name.split('/')[-1])
|
||||||
|
all_states = ORGTODOSTATES.get(bufnr, None)
|
||||||
|
|
||||||
|
vim_commands = [
|
||||||
|
u'let g:org_sav_timeoutlen=&timeoutlen',
|
||||||
|
u'au orgmode BufEnter <buffer> :if ! exists("g:org_sav_timeoutlen")|let g:org_sav_timeoutlen=&timeoutlen|set timeoutlen=1|endif',
|
||||||
|
u'au orgmode BufLeave <buffer> :if exists("g:org_sav_timeoutlen")|let &timeoutlen=g:org_sav_timeoutlen|unlet g:org_sav_timeoutlen|endif',
|
||||||
|
u'setlocal nolist tabstop=16 buftype=nofile timeout timeoutlen=1 winfixheight',
|
||||||
|
u'setlocal statusline=Org\\ todo\\ (%s)' % vim.eval(u_encode(u'fnameescape(fnamemodify(bufname(%d), ":t"))' % bufnr)),
|
||||||
|
u'nnoremap <silent> <buffer> <Esc> :%sbw<CR>' % vim.eval(u_encode(u'bufnr("%")')),
|
||||||
|
u'nnoremap <silent> <buffer> <CR> :let g:org_state = fnameescape(expand("<cword>"))<Bar>bw<Bar>exec "%s ORGMODE.plugins[u\'Todo\'].set_todo_state(\'".g:org_state."\')"<Bar>unlet! g:org_state<CR>' % VIM_PY_CALL,
|
||||||
|
]
|
||||||
|
# because timeoutlen can only be set globally it needs to be stored and
|
||||||
|
# restored later
|
||||||
|
# make window a scratch window and set the statusline differently
|
||||||
|
for cmd in vim_commands:
|
||||||
|
vim.command(u_encode(cmd))
|
||||||
|
|
||||||
|
if all_states is None:
|
||||||
|
vim.command(u_encode(u'bw'))
|
||||||
|
echom(u'No todo states avaiable for buffer %s' % vim.current.buffer.name)
|
||||||
|
|
||||||
|
for idx, state in enumerate(all_states):
|
||||||
|
pairs = [split_access_key(x, sub=u' ') for x in it.chain(*state)]
|
||||||
|
line = u'\t'.join(u''.join((u'[%s] ' % x[1], x[0])) for x in pairs)
|
||||||
|
vim.current.buffer.append(u_encode(line))
|
||||||
|
for todo, key in pairs:
|
||||||
|
# FIXME if double key is used for access modified this doesn't work
|
||||||
|
vim.command(u_encode(u'nnoremap <silent> <buffer> %s :bw<CR><c-w><c-p>%s ORGMODE.plugins[u"Todo"].set_todo_state("%s")<CR>' % (key, VIM_PY_CALL, u_decode(todo))))
|
||||||
|
|
||||||
|
# position the cursor of the current todo item
|
||||||
|
vim.command(u_encode(u'normal! G'))
|
||||||
|
current_state = settings.unset(u'org_current_state_%d' % bufnr)
|
||||||
|
if current_state is not None and current_state != '':
|
||||||
|
for i, buf in enumerate(vim.current.buffer):
|
||||||
|
idx = buf.find(current_state)
|
||||||
|
if idx != -1:
|
||||||
|
vim.current.window.cursor = (i + 1, idx)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
vim.current.window.cursor = (2, 4)
|
||||||
|
|
||||||
|
# finally make buffer non modifiable
|
||||||
|
vim.command(u_encode(u'setfiletype orgtodo'))
|
||||||
|
vim.command(u_encode(u'setlocal nomodifiable'))
|
||||||
|
|
||||||
|
# remove temporary todo states for the current buffer
|
||||||
|
del ORGTODOSTATES[bufnr]
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
u"""
|
||||||
|
Registration of plugin. Key bindings and other initialization should be done.
|
||||||
|
"""
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>ct', Plug(
|
||||||
|
u'OrgTodoToggleNonInteractive',
|
||||||
|
u'%s ORGMODE.plugins[u"Todo"].toggle_todo_state(interactive=False)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&TODO/DONE/-', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<localleader>d', Plug(
|
||||||
|
u'OrgTodoToggleInteractive',
|
||||||
|
u'%s ORGMODE.plugins[u"Todo"].toggle_todo_state(interactive=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
self.menu + ActionEntry(u'&TODO/DONE/- (interactiv)', self.keybindings[-1])
|
||||||
|
|
||||||
|
# add submenu
|
||||||
|
submenu = self.menu + Submenu(u'Select &keyword')
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<S-Right>', Plug(
|
||||||
|
u'OrgTodoForward',
|
||||||
|
u'%s ORGMODE.plugins[u"Todo"].toggle_todo_state()<CR>' % VIM_PY_CALL)))
|
||||||
|
submenu + ActionEntry(u'&Next keyword', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<S-Left>', Plug(
|
||||||
|
u'OrgTodoBackward',
|
||||||
|
u'%s ORGMODE.plugins[u"Todo"].toggle_todo_state(direction=2)<CR>' % VIM_PY_CALL)))
|
||||||
|
submenu + ActionEntry(u'&Previous keyword', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<C-S-Right>', Plug(
|
||||||
|
u'OrgTodoSetForward',
|
||||||
|
u'%s ORGMODE.plugins[u"Todo"].toggle_todo_state(next_set=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
submenu + ActionEntry(u'Next keyword &set', self.keybindings[-1])
|
||||||
|
|
||||||
|
self.keybindings.append(Keybinding(u'<C-S-Left>', Plug(
|
||||||
|
u'OrgTodoSetBackward',
|
||||||
|
u'%s ORGMODE.plugins[u"Todo"].toggle_todo_state(direction=2, next_set=True)<CR>' % VIM_PY_CALL)))
|
||||||
|
submenu + ActionEntry(u'Previous &keyword set', self.keybindings[-1])
|
||||||
|
|
||||||
|
settings.set(u'org_todo_keywords', [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')])
|
||||||
|
|
||||||
|
settings.set(u'org_todo_prompt_position', u'botright')
|
||||||
|
|
||||||
|
vim.command(u_encode(u'au orgmode BufReadCmd org:todo/* %s ORGMODE.plugins[u"Todo"].init_org_todo()' % VIM_PY_CALL))
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
|
@ -0,0 +1 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
|
@ -0,0 +1 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
|
@ -0,0 +1,11 @@
|
||||||
|
import sys
|
||||||
|
if sys.version_info < (3,):
|
||||||
|
def u_encode(string):
|
||||||
|
return string.encode('utf8')
|
||||||
|
def u_decode(string):
|
||||||
|
return string.decode('utf8')
|
||||||
|
else:
|
||||||
|
def u_encode(string):
|
||||||
|
return string
|
||||||
|
def u_decode(string):
|
||||||
|
return string
|
|
@ -0,0 +1,7 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.version_info < (3,):
|
||||||
|
VIM_PY_CALL = u':py'
|
||||||
|
else:
|
||||||
|
VIM_PY_CALL = u':py3'
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
try:
|
||||||
|
unicode
|
||||||
|
except NameError:
|
||||||
|
basestring = unicode = str
|
|
@ -0,0 +1,4 @@
|
||||||
|
try:
|
||||||
|
from __builtin__ import xrange as range
|
||||||
|
except:
|
||||||
|
pass
|
98
pack/acp/start/vim-orgmode/ftplugin/orgmode/settings.py
Normal file
98
pack/acp/start/vim-orgmode/ftplugin/orgmode/settings.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
SCOPE_ALL = 1
|
||||||
|
|
||||||
|
# for all vim-orgmode buffers
|
||||||
|
SCOPE_GLOBAL = 2
|
||||||
|
|
||||||
|
# just for the current buffer - has priority before the global settings
|
||||||
|
SCOPE_BUFFER = 4
|
||||||
|
|
||||||
|
VARIABLE_LEADER = {SCOPE_GLOBAL: u'g', SCOPE_BUFFER: u'b'}
|
||||||
|
|
||||||
|
u""" Evaluate and store settings """
|
||||||
|
|
||||||
|
|
||||||
|
def get(setting, default=None, scope=SCOPE_ALL):
|
||||||
|
u""" Evaluate setting in scope of the current buffer,
|
||||||
|
globally and also from the contents of the current buffer
|
||||||
|
|
||||||
|
WARNING: Only string values are converted to unicode. If a different value
|
||||||
|
is received, e.g. a list or dict, no conversion is done.
|
||||||
|
|
||||||
|
:setting: name of the variable to evaluate
|
||||||
|
:default: default value in case the variable is empty
|
||||||
|
|
||||||
|
:returns: variable value
|
||||||
|
"""
|
||||||
|
# TODO first read setting from org file which take precedence over vim
|
||||||
|
# variable settings
|
||||||
|
if (scope & SCOPE_ALL | SCOPE_BUFFER) and \
|
||||||
|
int(vim.eval(u_encode(u'exists("b:%s")' % setting))):
|
||||||
|
res = vim.eval(u_encode(u"b:%s" % setting))
|
||||||
|
if type(res) in (unicode, str):
|
||||||
|
return u_decode(res)
|
||||||
|
return res
|
||||||
|
|
||||||
|
elif (scope & SCOPE_ALL | SCOPE_GLOBAL) and \
|
||||||
|
int(vim.eval(u_encode(u'exists("g:%s")' % setting))):
|
||||||
|
res = vim.eval(u_encode(u"g:%s" % setting))
|
||||||
|
if type(res) in (unicode, str):
|
||||||
|
return u_decode(res)
|
||||||
|
return res
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def set(setting, value, scope=SCOPE_GLOBAL, overwrite=False):
|
||||||
|
u""" Store setting in the defined scope
|
||||||
|
|
||||||
|
WARNING: For the return value, only string are converted to unicode. If a
|
||||||
|
different value is received by vim.eval, e.g. a list or dict, no conversion
|
||||||
|
is done.
|
||||||
|
|
||||||
|
:setting: name of the setting
|
||||||
|
:value: the actual value, repr is called on the value to create a string
|
||||||
|
representation
|
||||||
|
:scope: the scope o the setting/variable
|
||||||
|
:overwrite: overwrite existing settings (probably user defined settings)
|
||||||
|
|
||||||
|
:returns: the new value in case of overwrite==False the current value
|
||||||
|
"""
|
||||||
|
if (not overwrite) and (
|
||||||
|
int(vim.eval(u_encode(u'exists("%s:%s")' % \
|
||||||
|
(VARIABLE_LEADER[scope], setting))))):
|
||||||
|
res = vim.eval(
|
||||||
|
u_encode(u'%s:%s' % (VARIABLE_LEADER[scope], setting)))
|
||||||
|
if type(res) in (unicode, str):
|
||||||
|
return u_decode(res)
|
||||||
|
return res
|
||||||
|
v = repr(value)
|
||||||
|
if type(value) == unicode and sys.version_info < (3,):
|
||||||
|
# strip leading u of unicode string representations
|
||||||
|
v = v[1:]
|
||||||
|
|
||||||
|
cmd = u'let %s:%s = %s' % (VARIABLE_LEADER[scope], setting, v)
|
||||||
|
vim.command(u_encode(cmd))
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def unset(setting, scope=SCOPE_GLOBAL):
|
||||||
|
u""" Unset setting in the defined scope
|
||||||
|
:setting: name of the setting
|
||||||
|
:scope: the scope o the setting/variable
|
||||||
|
|
||||||
|
:returns: last value of setting
|
||||||
|
"""
|
||||||
|
value = get(setting, scope=scope)
|
||||||
|
cmd = u'unlet! %s:%s' % (VARIABLE_LEADER[scope], setting)
|
||||||
|
vim.command(u_encode(cmd))
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
503
pack/acp/start/vim-orgmode/ftplugin/orgmode/vimbuffer.py
Normal file
503
pack/acp/start/vim-orgmode/ftplugin/orgmode/vimbuffer.py
Normal file
|
@ -0,0 +1,503 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
vimbuffer
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
VimBuffer and VimBufferContent are the interface between liborgmode and
|
||||||
|
vim.
|
||||||
|
|
||||||
|
VimBuffer extends the liborgmode.document.Document().
|
||||||
|
Document() is just a general implementation for loading an org file. It
|
||||||
|
has no interface to an actual file or vim buffer. This is the task of
|
||||||
|
vimbuffer.VimBuffer(). It is the interfaces to vim. The main tasks for
|
||||||
|
VimBuffer are to provide read and write access to a real vim buffer.
|
||||||
|
|
||||||
|
VimBufferContent is a helper class for VimBuffer. Basically, it hides the
|
||||||
|
details of encoding - everything read from or written to VimBufferContent
|
||||||
|
is UTF-8.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from collections import UserList
|
||||||
|
except:
|
||||||
|
from UserList import UserList
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode import settings
|
||||||
|
from orgmode.exceptions import BufferNotFound, BufferNotInSync
|
||||||
|
from orgmode.liborgmode.documents import Document, MultiPurposeList, Direction
|
||||||
|
from orgmode.liborgmode.headings import Heading
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
|
||||||
|
class VimBuffer(Document):
|
||||||
|
def __init__(self, bufnr=0):
|
||||||
|
u"""
|
||||||
|
:bufnr: 0: current buffer, every other number refers to another buffer
|
||||||
|
"""
|
||||||
|
Document.__init__(self)
|
||||||
|
self._bufnr = vim.current.buffer.number if bufnr == 0 else bufnr
|
||||||
|
self._changedtick = -1
|
||||||
|
self._cached_heading = None
|
||||||
|
if self._bufnr == vim.current.buffer.number:
|
||||||
|
self._content = VimBufferContent(vim.current.buffer)
|
||||||
|
else:
|
||||||
|
_buffer = None
|
||||||
|
for b in vim.buffers:
|
||||||
|
if self._bufnr == b.number:
|
||||||
|
_buffer = b
|
||||||
|
break
|
||||||
|
|
||||||
|
if not _buffer:
|
||||||
|
raise BufferNotFound(u'Unable to locate buffer number #%d' % self._bufnr)
|
||||||
|
self._content = VimBufferContent(_buffer)
|
||||||
|
|
||||||
|
self.update_changedtick()
|
||||||
|
self._orig_changedtick = self._changedtick
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tabstop(self):
|
||||||
|
return int(vim.eval(u_encode(u'&ts')))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tag_column(self):
|
||||||
|
return int(settings.get(u'org_tag_column', u'77'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_insync(self):
|
||||||
|
if self._changedtick == self._orig_changedtick:
|
||||||
|
self.update_changedtick()
|
||||||
|
return self._changedtick == self._orig_changedtick
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bufnr(self):
|
||||||
|
u"""
|
||||||
|
:returns: The buffer's number for the current document
|
||||||
|
"""
|
||||||
|
return self._bufnr
|
||||||
|
|
||||||
|
@property
|
||||||
|
def changedtick(self):
|
||||||
|
u""" Number of changes in vimbuffer """
|
||||||
|
return self._changedtick
|
||||||
|
|
||||||
|
@changedtick.setter
|
||||||
|
def changedtick(self, value):
|
||||||
|
self._changedtick = value
|
||||||
|
|
||||||
|
def get_todo_states(self, strip_access_key=True):
|
||||||
|
u""" Returns a list containing a tuple of two lists of allowed todo
|
||||||
|
states split by todo and done states. Multiple todo-done state
|
||||||
|
sequences can be defined.
|
||||||
|
|
||||||
|
:returns: [([todo states], [done states]), ..]
|
||||||
|
"""
|
||||||
|
states = settings.get(u'org_todo_keywords', [])
|
||||||
|
# TODO this function gets called too many times when change of state of
|
||||||
|
# one todo is triggered, check with:
|
||||||
|
# print(states)
|
||||||
|
# this should be changed by saving todo states into some var and only
|
||||||
|
# if new states are set hook should be called to register them again
|
||||||
|
# into a property
|
||||||
|
# TODO move this to documents.py, it is all tangled up like this, no
|
||||||
|
# structure...
|
||||||
|
if type(states) not in (list, tuple):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def parse_states(s, stop=0):
|
||||||
|
res = []
|
||||||
|
if not s:
|
||||||
|
return res
|
||||||
|
if type(s[0]) in (unicode, str):
|
||||||
|
r = []
|
||||||
|
for i in s:
|
||||||
|
_i = i
|
||||||
|
if type(_i) == str:
|
||||||
|
_i = u_decode(_i)
|
||||||
|
if type(_i) == unicode and _i:
|
||||||
|
if strip_access_key and u'(' in _i:
|
||||||
|
_i = _i[:_i.index(u'(')]
|
||||||
|
if _i:
|
||||||
|
r.append(_i)
|
||||||
|
else:
|
||||||
|
r.append(_i)
|
||||||
|
if not u'|' in r:
|
||||||
|
if not stop:
|
||||||
|
res.append((r[:-1], [r[-1]]))
|
||||||
|
else:
|
||||||
|
res = (r[:-1], [r[-1]])
|
||||||
|
else:
|
||||||
|
seperator_pos = r.index(u'|')
|
||||||
|
if not stop:
|
||||||
|
res.append((r[0:seperator_pos], r[seperator_pos + 1:]))
|
||||||
|
else:
|
||||||
|
res = (r[0:seperator_pos], r[seperator_pos + 1:])
|
||||||
|
elif type(s) in (list, tuple) and not stop:
|
||||||
|
for i in s:
|
||||||
|
r = parse_states(i, stop=1)
|
||||||
|
if r:
|
||||||
|
res.append(r)
|
||||||
|
return res
|
||||||
|
|
||||||
|
return parse_states(states)
|
||||||
|
|
||||||
|
def update_changedtick(self):
|
||||||
|
if self.bufnr == vim.current.buffer.number:
|
||||||
|
self._changedtick = int(vim.eval(u_encode(u'b:changedtick')))
|
||||||
|
else:
|
||||||
|
vim.command(u_encode(u'unlet! g:org_changedtick | let g:org_lz = &lz | let g:org_hidden = &hidden | set lz hidden'))
|
||||||
|
# TODO is this likely to fail? maybe some error hangling should be added
|
||||||
|
vim.command(u_encode(u'keepalt buffer %d | let g:org_changedtick = b:changedtick | buffer %d' % \
|
||||||
|
(self.bufnr, vim.current.buffer.number)))
|
||||||
|
vim.command(u_encode(u'let &lz = g:org_lz | let &hidden = g:org_hidden | unlet! g:org_lz g:org_hidden | redraw'))
|
||||||
|
self._changedtick = int(vim.eval(u_encode(u'g:org_changedtick')))
|
||||||
|
|
||||||
|
def write(self):
|
||||||
|
u""" write the changes to the vim buffer
|
||||||
|
|
||||||
|
:returns: True if something was written, otherwise False
|
||||||
|
"""
|
||||||
|
if not self.is_dirty:
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.update_changedtick()
|
||||||
|
if not self.is_insync:
|
||||||
|
raise BufferNotInSync(u'Buffer is not in sync with vim!')
|
||||||
|
|
||||||
|
# write meta information
|
||||||
|
if self.is_dirty_meta_information:
|
||||||
|
meta_end = 0 if self._orig_meta_information_len is None else self._orig_meta_information_len
|
||||||
|
self._content[:meta_end] = self.meta_information
|
||||||
|
self._orig_meta_information_len = len(self.meta_information)
|
||||||
|
|
||||||
|
# remove deleted headings
|
||||||
|
already_deleted = []
|
||||||
|
for h in sorted(self._deleted_headings, key=lambda x: x._orig_start, reverse=True):
|
||||||
|
if h._orig_start is not None and h._orig_start not in already_deleted:
|
||||||
|
# this is a heading that actually exists on the buffer and it
|
||||||
|
# needs to be removed
|
||||||
|
del self._content[h._orig_start:h._orig_start + h._orig_len]
|
||||||
|
already_deleted.append(h._orig_start)
|
||||||
|
del self._deleted_headings[:]
|
||||||
|
del already_deleted
|
||||||
|
|
||||||
|
# update changed headings and add new headings
|
||||||
|
for h in self.all_headings():
|
||||||
|
if h.is_dirty:
|
||||||
|
vim.current.buffer.append("") # workaround for neovim bug
|
||||||
|
if h._orig_start is not None:
|
||||||
|
# this is a heading that existed before and was changed. It
|
||||||
|
# needs to be replaced
|
||||||
|
if h.is_dirty_heading:
|
||||||
|
self._content[h.start:h.start + 1] = [unicode(h)]
|
||||||
|
if h.is_dirty_body:
|
||||||
|
self._content[h.start + 1:h.start + h._orig_len] = h.body
|
||||||
|
else:
|
||||||
|
# this is a new heading. It needs to be inserted
|
||||||
|
self._content[h.start:h.start] = [unicode(h)] + h.body
|
||||||
|
del vim.current.buffer[-1] # restore workaround for neovim bug
|
||||||
|
h._dirty_heading = False
|
||||||
|
h._dirty_body = False
|
||||||
|
# for all headings the length and start offset needs to be updated
|
||||||
|
h._orig_start = h.start
|
||||||
|
h._orig_len = len(h)
|
||||||
|
|
||||||
|
self._dirty_meta_information = False
|
||||||
|
self._dirty_document = False
|
||||||
|
|
||||||
|
self.update_changedtick()
|
||||||
|
self._orig_changedtick = self._changedtick
|
||||||
|
return True
|
||||||
|
|
||||||
|
def write_heading(self, heading, including_children=True):
|
||||||
|
""" WARNING: use this function only when you know what you are doing!
|
||||||
|
This function writes a heading to the vim buffer. It offers performance
|
||||||
|
advantages over the regular write() function. This advantage is
|
||||||
|
combined with no sanity checks! Whenever you use this function, make
|
||||||
|
sure the heading you are writing contains the right offsets
|
||||||
|
(Heading._orig_start, Heading._orig_len).
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
# Retrieve a potentially dirty document
|
||||||
|
d = ORGMODE.get_document(allow_dirty=True)
|
||||||
|
# Don't rely on the DOM, retrieve the heading afresh
|
||||||
|
h = d.find_heading(direction=Direction.FORWARD, position=100)
|
||||||
|
# Update tags
|
||||||
|
h.tags = ['tag1', 'tag2']
|
||||||
|
# Write the heading
|
||||||
|
d.write_heading(h)
|
||||||
|
|
||||||
|
This function can't be used to delete a heading!
|
||||||
|
|
||||||
|
:heading: Write this heading with to the vim buffer
|
||||||
|
:including_children: Also include children in the update
|
||||||
|
|
||||||
|
:returns The written heading
|
||||||
|
"""
|
||||||
|
if including_children and heading.children:
|
||||||
|
for child in heading.children[::-1]:
|
||||||
|
self.write_heading(child, including_children)
|
||||||
|
|
||||||
|
if heading.is_dirty:
|
||||||
|
if heading._orig_start is not None:
|
||||||
|
# this is a heading that existed before and was changed. It
|
||||||
|
# needs to be replaced
|
||||||
|
if heading.is_dirty_heading:
|
||||||
|
self._content[heading._orig_start:heading._orig_start + 1] = [unicode(heading)]
|
||||||
|
if heading.is_dirty_body:
|
||||||
|
self._content[heading._orig_start + 1:heading._orig_start + heading._orig_len] = heading.body
|
||||||
|
else:
|
||||||
|
# this is a new heading. It needs to be inserted
|
||||||
|
raise ValueError('Heading must contain the attribute _orig_start! %s' % heading)
|
||||||
|
heading._dirty_heading = False
|
||||||
|
heading._dirty_body = False
|
||||||
|
# for all headings the length offset needs to be updated
|
||||||
|
heading._orig_len = len(heading)
|
||||||
|
|
||||||
|
return heading
|
||||||
|
|
||||||
|
def write_checkbox(self, checkbox, including_children=True):
|
||||||
|
if including_children and checkbox.children:
|
||||||
|
for child in checkbox.children[::-1]:
|
||||||
|
self.write_checkbox(child, including_children)
|
||||||
|
|
||||||
|
if checkbox.is_dirty:
|
||||||
|
if checkbox._orig_start is not None:
|
||||||
|
# this is a heading that existed before and was changed. It
|
||||||
|
# needs to be replaced
|
||||||
|
# print "checkbox is dirty? " + str(checkbox.is_dirty_checkbox)
|
||||||
|
# print checkbox
|
||||||
|
if checkbox.is_dirty_checkbox:
|
||||||
|
self._content[checkbox._orig_start:checkbox._orig_start + 1] = [unicode(checkbox)]
|
||||||
|
if checkbox.is_dirty_body:
|
||||||
|
self._content[checkbox._orig_start + 1:checkbox._orig_start + checkbox._orig_len] = checkbox.body
|
||||||
|
else:
|
||||||
|
# this is a new checkbox. It needs to be inserted
|
||||||
|
raise ValueError('Checkbox must contain the attribute _orig_start! %s' % checkbox)
|
||||||
|
checkbox._dirty_checkbox = False
|
||||||
|
checkbox._dirty_body = False
|
||||||
|
# for all headings the length offset needs to be updated
|
||||||
|
checkbox._orig_len = len(checkbox)
|
||||||
|
|
||||||
|
return checkbox
|
||||||
|
|
||||||
|
def write_checkboxes(self, checkboxes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def previous_heading(self, position=None):
|
||||||
|
u""" Find the next heading (search forward) and return the related object
|
||||||
|
:returns: Heading object or None
|
||||||
|
"""
|
||||||
|
h = self.current_heading(position=position)
|
||||||
|
if h:
|
||||||
|
return h.previous_heading
|
||||||
|
|
||||||
|
def current_heading(self, position=None):
|
||||||
|
u""" Find the current heading (search backward) and return the related object
|
||||||
|
:returns: Heading object or None
|
||||||
|
"""
|
||||||
|
if position is None:
|
||||||
|
position = vim.current.window.cursor[0] - 1
|
||||||
|
|
||||||
|
if not self.headings:
|
||||||
|
return
|
||||||
|
|
||||||
|
def binaryFindInDocument():
|
||||||
|
hi = len(self.headings)
|
||||||
|
lo = 0
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo+hi)//2
|
||||||
|
h = self.headings[mid]
|
||||||
|
if h.end_of_last_child < position:
|
||||||
|
lo = mid + 1
|
||||||
|
elif h.start > position:
|
||||||
|
hi = mid
|
||||||
|
else:
|
||||||
|
return binaryFindHeading(h)
|
||||||
|
|
||||||
|
def binaryFindHeading(heading):
|
||||||
|
if not heading.children or heading.end >= position:
|
||||||
|
return heading
|
||||||
|
|
||||||
|
hi = len(heading.children)
|
||||||
|
lo = 0
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo+hi)//2
|
||||||
|
h = heading.children[mid]
|
||||||
|
if h.end_of_last_child < position:
|
||||||
|
lo = mid + 1
|
||||||
|
elif h.start > position:
|
||||||
|
hi = mid
|
||||||
|
else:
|
||||||
|
return binaryFindHeading(h)
|
||||||
|
|
||||||
|
# look at the cache to find the heading
|
||||||
|
h_tmp = self._cached_heading
|
||||||
|
if h_tmp is not None:
|
||||||
|
if h_tmp.end_of_last_child > position and \
|
||||||
|
h_tmp.start < position:
|
||||||
|
if h_tmp.end < position:
|
||||||
|
self._cached_heading = binaryFindHeading(h_tmp)
|
||||||
|
return self._cached_heading
|
||||||
|
|
||||||
|
self._cached_heading = binaryFindInDocument()
|
||||||
|
return self._cached_heading
|
||||||
|
|
||||||
|
def next_heading(self, position=None):
|
||||||
|
u""" Find the next heading (search forward) and return the related object
|
||||||
|
:returns: Heading object or None
|
||||||
|
"""
|
||||||
|
h = self.current_heading(position=position)
|
||||||
|
if h:
|
||||||
|
return h.next_heading
|
||||||
|
|
||||||
|
def find_current_heading(self, position=None, heading=Heading):
|
||||||
|
u""" Find the next heading backwards from the position of the cursor.
|
||||||
|
The difference to the function current_heading is that the returned
|
||||||
|
object is not built into the DOM. In case the DOM doesn't exist or is
|
||||||
|
out of sync this function is much faster in fetching the current
|
||||||
|
heading.
|
||||||
|
|
||||||
|
:position: The position to start the search from
|
||||||
|
|
||||||
|
:heading: The base class for the returned heading
|
||||||
|
|
||||||
|
:returns: Heading object or None
|
||||||
|
"""
|
||||||
|
return self.find_heading(vim.current.window.cursor[0] - 1 \
|
||||||
|
if position is None else position, \
|
||||||
|
direction=Direction.BACKWARD, heading=heading, \
|
||||||
|
connect_with_document=False)
|
||||||
|
|
||||||
|
|
||||||
|
class VimBufferContent(MultiPurposeList):
|
||||||
|
u""" Vim Buffer Content is a UTF-8 wrapper around a vim buffer. When
|
||||||
|
retrieving or setting items in the buffer an automatic conversion is
|
||||||
|
performed.
|
||||||
|
|
||||||
|
This ensures UTF-8 usage on the side of liborgmode and the vim plugin
|
||||||
|
vim-orgmode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, vimbuffer, on_change=None):
|
||||||
|
MultiPurposeList.__init__(self, on_change=on_change)
|
||||||
|
|
||||||
|
# replace data with vimbuffer to make operations change the actual
|
||||||
|
# buffer
|
||||||
|
self.data = vimbuffer
|
||||||
|
|
||||||
|
def __contains__(self, item):
|
||||||
|
i = item
|
||||||
|
if type(i) is unicode:
|
||||||
|
i = u_encode(item)
|
||||||
|
return MultiPurposeList.__contains__(self, i)
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
if isinstance(i, slice):
|
||||||
|
return [u_decode(item) if type(item) is str else item \
|
||||||
|
for item in MultiPurposeList.__getitem__(self, i)]
|
||||||
|
else:
|
||||||
|
item = MultiPurposeList.__getitem__(self, i)
|
||||||
|
if type(item) is str:
|
||||||
|
return u_decode(item)
|
||||||
|
return item
|
||||||
|
|
||||||
|
def __setitem__(self, i, item):
|
||||||
|
if isinstance(i, slice):
|
||||||
|
o = []
|
||||||
|
o_tmp = item
|
||||||
|
if type(o_tmp) not in (list, tuple) and not isinstance(o_tmp, UserList):
|
||||||
|
o_tmp = list(o_tmp)
|
||||||
|
for item in o_tmp:
|
||||||
|
if type(item) == unicode:
|
||||||
|
o.append(u_encode(item))
|
||||||
|
else:
|
||||||
|
o.append(item)
|
||||||
|
MultiPurposeList.__setitem__(self, i, o)
|
||||||
|
else:
|
||||||
|
_i = item
|
||||||
|
if type(_i) is unicode:
|
||||||
|
_i = u_encode(item)
|
||||||
|
|
||||||
|
# TODO: fix this bug properly, it is really strange that it fails on
|
||||||
|
# python3 without it. Problem is that when _i = ['* '] it fails in
|
||||||
|
# UserList.__setitem__() but if it is changed in debuggr in __setitem__
|
||||||
|
# like item[0] = '* ' it works, hence this is some quirk with unicode
|
||||||
|
# stuff but very likely vim 7.4 BUG too.
|
||||||
|
if isinstance(_i, UserList) and sys.version_info > (3, ):
|
||||||
|
_i = [s.encode('utf8').decode('utf8') for s in _i]
|
||||||
|
|
||||||
|
MultiPurposeList.__setitem__(self, i, _i)
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
raise NotImplementedError()
|
||||||
|
# TODO: implement me
|
||||||
|
if isinstance(other, UserList):
|
||||||
|
return self.__class__(self.data + other.data)
|
||||||
|
elif isinstance(other, type(self.data)):
|
||||||
|
return self.__class__(self.data + other)
|
||||||
|
else:
|
||||||
|
return self.__class__(self.data + list(other))
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
raise NotImplementedError()
|
||||||
|
# TODO: implement me
|
||||||
|
if isinstance(other, UserList):
|
||||||
|
return self.__class__(other.data + self.data)
|
||||||
|
elif isinstance(other, type(self.data)):
|
||||||
|
return self.__class__(other + self.data)
|
||||||
|
else:
|
||||||
|
return self.__class__(list(other) + self.data)
|
||||||
|
|
||||||
|
def __iadd__(self, other):
|
||||||
|
o = []
|
||||||
|
o_tmp = other
|
||||||
|
if type(o_tmp) not in (list, tuple) and not isinstance(o_tmp, UserList):
|
||||||
|
o_tmp = list(o_tmp)
|
||||||
|
for i in o_tmp:
|
||||||
|
if type(i) is unicode:
|
||||||
|
o.append(u_encode(i))
|
||||||
|
else:
|
||||||
|
o.append(i)
|
||||||
|
|
||||||
|
return MultiPurposeList.__iadd__(self, o)
|
||||||
|
|
||||||
|
def append(self, item):
|
||||||
|
i = item
|
||||||
|
if type(item) is str:
|
||||||
|
i = u_encode(item)
|
||||||
|
MultiPurposeList.append(self, i)
|
||||||
|
|
||||||
|
def insert(self, i, item):
|
||||||
|
_i = item
|
||||||
|
if type(_i) is str:
|
||||||
|
_i = u_encode(item)
|
||||||
|
MultiPurposeList.insert(self, i, _i)
|
||||||
|
|
||||||
|
def index(self, item, *args):
|
||||||
|
i = item
|
||||||
|
if type(i) is unicode:
|
||||||
|
i = u_encode(item)
|
||||||
|
MultiPurposeList.index(self, i, *args)
|
||||||
|
|
||||||
|
def pop(self, i=-1):
|
||||||
|
return u_decode(MultiPurposeList.pop(self, i))
|
||||||
|
|
||||||
|
def extend(self, other):
|
||||||
|
o = []
|
||||||
|
o_tmp = other
|
||||||
|
if type(o_tmp) not in (list, tuple) and not isinstance(o_tmp, UserList):
|
||||||
|
o_tmp = list(o_tmp)
|
||||||
|
for i in o_tmp:
|
||||||
|
if type(i) is unicode:
|
||||||
|
o.append(u_encode(i))
|
||||||
|
else:
|
||||||
|
o.append(i)
|
||||||
|
MultiPurposeList.extend(self, o)
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
133
pack/acp/start/vim-orgmode/indent/org.vim
Normal file
133
pack/acp/start/vim-orgmode/indent/org.vim
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
" Delete the next line to avoid the special indention of items
|
||||||
|
if !exists("g:org_indent")
|
||||||
|
let g:org_indent = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
setlocal foldtext=GetOrgFoldtext()
|
||||||
|
setlocal fillchars-=fold:-
|
||||||
|
setlocal fillchars+=fold:\
|
||||||
|
setlocal foldexpr=GetOrgFolding()
|
||||||
|
setlocal foldmethod=expr
|
||||||
|
setlocal indentexpr=GetOrgIndent()
|
||||||
|
setlocal nolisp
|
||||||
|
setlocal nosmartindent
|
||||||
|
setlocal autoindent
|
||||||
|
|
||||||
|
if has('python3')
|
||||||
|
let s:py_env = 'python3 << EOF'
|
||||||
|
else
|
||||||
|
let s:py_env = 'python << EOF'
|
||||||
|
endif
|
||||||
|
|
||||||
|
function! GetOrgIndent()
|
||||||
|
if g:org_indent == 0
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
exe s:py_env
|
||||||
|
from orgmode._vim import indent_orgmode
|
||||||
|
indent_orgmode()
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if exists('b:indent_level')
|
||||||
|
let l:tmp = b:indent_level
|
||||||
|
unlet b:indent_level
|
||||||
|
return l:tmp
|
||||||
|
else
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! GetOrgFolding()
|
||||||
|
let l:mode = mode()
|
||||||
|
if l:mode == 'i'
|
||||||
|
" the cache size is limited to 3, because vim queries the current and
|
||||||
|
" both surrounding lines when the user is typing in insert mode. The
|
||||||
|
" cache is shared between GetOrgFolding and GetOrgFoldtext
|
||||||
|
if ! exists('b:org_folding_cache')
|
||||||
|
let b:org_folding_cache = {}
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(b:org_folding_cache, v:lnum)
|
||||||
|
if match(b:org_folding_cache[v:lnum], '^>') == 0 &&
|
||||||
|
\ match(getline(v:lnum), '^\*\+\s') != 0
|
||||||
|
" when the user pastes text or presses enter, it happens that
|
||||||
|
" the cache starts to confuse vim's folding abilities
|
||||||
|
" these entries can safely be removed
|
||||||
|
unlet b:org_folding_cache[v:lnum]
|
||||||
|
|
||||||
|
" the fold text cache is probably also damaged, delete it as
|
||||||
|
" well
|
||||||
|
unlet! b:org_foldtext_cache
|
||||||
|
else
|
||||||
|
return b:org_folding_cache[v:lnum]
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
exe s:py_env
|
||||||
|
from orgmode._vim import fold_orgmode
|
||||||
|
fold_orgmode(allow_dirty=True)
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
|
||||||
|
exe s:py_env
|
||||||
|
from orgmode._vim import fold_orgmode
|
||||||
|
fold_orgmode()
|
||||||
|
EOF
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('b:fold_expr')
|
||||||
|
let l:tmp = b:fold_expr
|
||||||
|
unlet b:fold_expr
|
||||||
|
if l:mode == 'i'
|
||||||
|
if ! has_key(b:org_folding_cache, v:lnum)
|
||||||
|
if len(b:org_folding_cache) > 3
|
||||||
|
let b:org_folding_cache = {}
|
||||||
|
endif
|
||||||
|
let b:org_folding_cache[v:lnum] = l:tmp
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
return l:tmp
|
||||||
|
else
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! SetOrgFoldtext(text)
|
||||||
|
let b:foldtext = a:text
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! GetOrgFoldtext()
|
||||||
|
let l:mode = mode()
|
||||||
|
if l:mode == 'i'
|
||||||
|
" add a separate cache for fold text
|
||||||
|
if ! exists('b:org_foldtext_cache') ||
|
||||||
|
\ ! has_key(b:org_foldtext_cache, 'timestamp') ||
|
||||||
|
\ b:org_foldtext_cache['timestamp'] > (localtime() + 10)
|
||||||
|
let b:org_foldtext_cache = {'timestamp': localtime()}
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(b:org_foldtext_cache, v:foldstart)
|
||||||
|
return b:org_foldtext_cache[v:foldstart]
|
||||||
|
endif
|
||||||
|
exe s:py_env
|
||||||
|
from orgmode._vim import fold_text
|
||||||
|
fold_text(allow_dirty=True)
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
unlet! b:org_foldtext_cache
|
||||||
|
exec s:py_env
|
||||||
|
from orgmode._vim import fold_text
|
||||||
|
fold_text()
|
||||||
|
EOF
|
||||||
|
endif
|
||||||
|
|
||||||
|
if exists('b:foldtext')
|
||||||
|
let l:tmp = b:foldtext
|
||||||
|
unlet b:foldtext
|
||||||
|
if l:mode == 'i'
|
||||||
|
let b:org_foldtext_cache[v:foldstart] = l:tmp
|
||||||
|
endif
|
||||||
|
return l:tmp
|
||||||
|
endif
|
||||||
|
endfunction
|
3
pack/acp/start/vim-orgmode/install_vba.vim
Normal file
3
pack/acp/start/vim-orgmode/install_vba.vim
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
:exec 'set rtp='.g:installdir
|
||||||
|
:so orgmode.vba
|
||||||
|
:q!
|
3
pack/acp/start/vim-orgmode/install_vmb.vim
Normal file
3
pack/acp/start/vim-orgmode/install_vmb.vim
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
:exec 'set rtp='.g:installdir
|
||||||
|
:so orgmode.vmb
|
||||||
|
:q!
|
54
pack/acp/start/vim-orgmode/org
Executable file
54
pack/acp/start/vim-orgmode/org
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# org
|
||||||
|
# Command line utility for working with orgmode documents
|
||||||
|
#
|
||||||
|
# Depends: python-liborgmode
|
||||||
|
#
|
||||||
|
# Copyright (C) 2012 Jan Christoph Ebersbach
|
||||||
|
#
|
||||||
|
# http://www.e-jc.de/
|
||||||
|
#
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# The source code of this program is made available
|
||||||
|
# under the terms of the GNU Affero General Public License version 3
|
||||||
|
# (GNU AGPL V3) as published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# Binary versions of this program provided by Univention to you as
|
||||||
|
# well as other copyrighted, protected or trademarked materials like
|
||||||
|
# Logos, graphics, fonts, specific documentations and configurations,
|
||||||
|
# cryptographic keys etc. are subject to a license agreement between
|
||||||
|
# you and Univention and not subject to the GNU AGPL V3.
|
||||||
|
#
|
||||||
|
# In the case you use this program under the terms of the GNU AGPL V3,
|
||||||
|
# the program is provided 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 Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public
|
||||||
|
# License with the Debian GNU/Linux or Univention distribution in file
|
||||||
|
# /usr/share/common-licenses/AGPL-3; if not, see
|
||||||
|
# <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append('ftplugin')
|
||||||
|
|
||||||
|
from orgmode.liborgmode.documents import Document
|
||||||
|
|
||||||
|
|
||||||
|
class OrgFile(Document):
|
||||||
|
def __init__(self, filename):
|
||||||
|
u"""
|
||||||
|
:filename: Name of the file that shall be opened
|
||||||
|
"""
|
||||||
|
Document.__init__(self)
|
||||||
|
with file(filename) as f:
|
||||||
|
self._content = [line.decode(u'utf-8') for line in f.readlines()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import cProfile
|
||||||
|
for filename in sys.argv[1:]:
|
||||||
|
cProfile.run('OrgFile(filename).init_dom()')
|
383
pack/acp/start/vim-orgmode/syntax/org.vim
Normal file
383
pack/acp/start/vim-orgmode/syntax/org.vim
Normal file
|
@ -0,0 +1,383 @@
|
||||||
|
" Support org authoring markup as closely as possible
|
||||||
|
" (we're adding two markdown-like variants for =code= and blockquotes)
|
||||||
|
" -----------------------------------------------------------------------------
|
||||||
|
"
|
||||||
|
" Do we use aggresive conceal?
|
||||||
|
if exists("b:org_aggressive_conceal")
|
||||||
|
let s:conceal_aggressively=b:org_aggressive_conceal
|
||||||
|
elseif exists("g:org_aggressive_conceal")
|
||||||
|
let s:conceal_aggressively=g:org_aggressive_conceal
|
||||||
|
else
|
||||||
|
let s:conceal_aggressively=0
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Inline markup {{{1
|
||||||
|
" *bold*, /italic/, _underline_, +strike-through+, =code=, ~verbatim~
|
||||||
|
" Note:
|
||||||
|
" - /italic/ is rendered as reverse in most terms (works fine in gVim, though)
|
||||||
|
" - +strike-through+ doesn't work on Vim / gVim
|
||||||
|
" - the non-standard `code' markup is also supported
|
||||||
|
" - =code= and ~verbatim~ are also supported as block-level markup, see below.
|
||||||
|
" Ref: http://orgmode.org/manual/Emphasis-and-monospace.html
|
||||||
|
"syntax match org_bold /\*[^ ]*\*/
|
||||||
|
|
||||||
|
" FIXME: Always make org_bold syntax define before org_heading syntax
|
||||||
|
" to make sure that org_heading syntax got higher priority(help :syn-priority) than org_bold.
|
||||||
|
" If there is any other good solution, please help fix it.
|
||||||
|
" \\\\*sinuate*
|
||||||
|
if (s:conceal_aggressively == 1)
|
||||||
|
syntax region org_bold matchgroup=org_border_bold start="[^ \\]\zs\*\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs\*\|\(^\|[^\\]\)\@<=\*\S\@=" end="[^ \\]\zs\*\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs\*\|[^\\]\zs\*\S\@=" concealends oneline
|
||||||
|
syntax region org_italic matchgroup=org_border_ital start="[^ \\]\zs\/\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs\/\|\(^\|[^\\]\)\@<=\/\S\@=" end="[^ \\]\zs\/\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs\/\|[^\\]\zs\/\S\@=" concealends oneline
|
||||||
|
syntax region org_underline matchgroup=org_border_undl start="[^ \\]\zs_\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs_\|\(^\|[^\\]\)\@<=_\S\@=" end="[^ \\]\zs_\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs_\|[^\\]\zs_\S\@=" concealends oneline
|
||||||
|
syntax region org_code matchgroup=org_border_code start="[^ \\]\zs=\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs=\|\(^\|[^\\]\)\@<==\S\@=" end="[^ \\]\zs=\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs=\|[^\\]\zs=\S\@=" concealends oneline
|
||||||
|
syntax region org_code matchgroup=org_border_code start="[^ \\]\zs`\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs`\|\(^\|[^\\]\)\@<=`\S\@=" end="[^ \\]\zs'\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs'\|[^\\]\zs'\S\@=" concealends oneline
|
||||||
|
syntax region org_verbatim matchgroup=org_border_verb start="[^ \\]\zs\~\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs\~\|\(^\|[^\\]\)\@<=\~\S\@=" end="[^ \\]\zs\~\|\(\(^\|[^\\]\)\zs\(\\\\\)\+\)\zs\~\|[^\\]\zs\~\S\@=" concealends oneline
|
||||||
|
else
|
||||||
|
syntax region org_bold start="\S\zs\*\|\*\S\@=" end="\S\zs\*\|\*\S\@=" keepend oneline
|
||||||
|
syntax region org_italic start="\S\zs\/\|\/\S\@=" end="\S\zs\/\|\/\S\@=" keepend oneline
|
||||||
|
syntax region org_underline start="\S\zs_\|_\S\@=" end="\S\zs_\|_\S\@=" keepend oneline
|
||||||
|
syntax region org_code start="\S\zs=\|=\S\@=" end="\S\zs=\|=\S\@=" keepend oneline
|
||||||
|
syntax region org_code start="\S\zs`\|`\S\@=" end="\S\zs'\|'\S\@=" keepend oneline
|
||||||
|
syntax region org_verbatim start="\S\zs\~\|\~\S\@=" end="\S\zs\~\|\~\S\@=" keepend oneline
|
||||||
|
endif
|
||||||
|
|
||||||
|
hi def org_bold term=bold cterm=bold gui=bold
|
||||||
|
hi def org_italic term=italic cterm=italic gui=italic
|
||||||
|
hi def org_underline term=underline cterm=underline gui=underline
|
||||||
|
|
||||||
|
if (s:conceal_aggressively == 1)
|
||||||
|
hi link org_border_bold org_bold
|
||||||
|
hi link org_border_ital org_italic
|
||||||
|
hi link org_border_undl org_underline
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Headings: {{{1
|
||||||
|
" Load Settings: {{{2
|
||||||
|
if !exists('g:org_heading_highlight_colors')
|
||||||
|
let g:org_heading_highlight_colors = ['Title', 'Constant', 'Identifier', 'Statement', 'PreProc', 'Type', 'Special']
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('g:org_heading_highlight_levels')
|
||||||
|
let g:org_heading_highlight_levels = len(g:org_heading_highlight_colors)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('g:org_heading_shade_leading_stars')
|
||||||
|
let g:org_heading_shade_leading_stars = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Enable Syntax HL: {{{2
|
||||||
|
unlet! s:i s:j s:contains
|
||||||
|
let s:i = 1
|
||||||
|
let s:j = len(g:org_heading_highlight_colors)
|
||||||
|
let s:contains = ' contains=org_timestamp,org_timestamp_inactive,org_subtask_percent,org_subtask_number,org_subtask_percent_100,org_subtask_number_all,org_list_checkbox,org_bold,org_italic,org_underline,org_code,org_verbatim'
|
||||||
|
if g:org_heading_shade_leading_stars == 1
|
||||||
|
let s:contains = s:contains . ',org_shade_stars'
|
||||||
|
syntax match org_shade_stars /^\*\{2,\}/me=e-1 contained
|
||||||
|
hi def link org_shade_stars Ignore
|
||||||
|
else
|
||||||
|
hi clear org_shade_stars
|
||||||
|
endif
|
||||||
|
|
||||||
|
while s:i <= g:org_heading_highlight_levels
|
||||||
|
exec 'syntax match org_heading' . s:i . ' /^\*\{' . s:i . '\}\s.*/' . s:contains
|
||||||
|
exec 'hi def link org_heading' . s:i . ' ' . g:org_heading_highlight_colors[(s:i - 1) % s:j]
|
||||||
|
let s:i += 1
|
||||||
|
endwhile
|
||||||
|
unlet! s:i s:j s:contains
|
||||||
|
|
||||||
|
" Todo Keywords: {{{1
|
||||||
|
" Load Settings: {{{2
|
||||||
|
if !exists('g:org_todo_keywords')
|
||||||
|
let g:org_todo_keywords = ['TODO', '|', 'DONE']
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !exists('g:org_todo_keyword_faces')
|
||||||
|
let g:org_todo_keyword_faces = []
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Enable Syntax HL: {{{2
|
||||||
|
let s:todo_headings = ''
|
||||||
|
let s:i = 1
|
||||||
|
while s:i <= g:org_heading_highlight_levels
|
||||||
|
if s:todo_headings == ''
|
||||||
|
let s:todo_headings = 'containedin=org_heading' . s:i
|
||||||
|
else
|
||||||
|
let s:todo_headings = s:todo_headings . ',org_heading' . s:i
|
||||||
|
endif
|
||||||
|
let s:i += 1
|
||||||
|
endwhile
|
||||||
|
unlet! s:i
|
||||||
|
|
||||||
|
if !exists('g:loaded_org_syntax')
|
||||||
|
let g:loaded_org_syntax = 1
|
||||||
|
|
||||||
|
function! OrgExtendHighlightingGroup(base_group, new_group, settings)
|
||||||
|
let l:base_hi = ''
|
||||||
|
redir => l:base_hi
|
||||||
|
silent execute 'highlight ' . a:base_group
|
||||||
|
redir END
|
||||||
|
let l:group_hi = substitute(split(l:base_hi, '\n')[0], '^' . a:base_group . '\s\+xxx', '', '')
|
||||||
|
execute 'highlight ' . a:new_group . l:group_hi . ' ' . a:settings
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! OrgInterpretFaces(faces)
|
||||||
|
let l:res_faces = ''
|
||||||
|
if type(a:faces) == 3
|
||||||
|
let l:style = []
|
||||||
|
for l:f in a:faces
|
||||||
|
let l:_f = [l:f]
|
||||||
|
if type(l:f) == 3
|
||||||
|
let l:_f = l:f
|
||||||
|
endif
|
||||||
|
for l:g in l:_f
|
||||||
|
if type(l:g) == 1 && l:g =~ '^:'
|
||||||
|
if l:g !~ '[\t ]'
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
let l:k_v = split(l:g)
|
||||||
|
if l:k_v[0] == ':foreground'
|
||||||
|
let l:gui_color = ''
|
||||||
|
let l:found_gui_color = 0
|
||||||
|
for l:color in split(l:k_v[1], ',')
|
||||||
|
if l:color =~ '^#'
|
||||||
|
let l:found_gui_color = 1
|
||||||
|
let l:res_faces = l:res_faces . ' guifg=' . l:color
|
||||||
|
elseif l:color != ''
|
||||||
|
let l:gui_color = l:color
|
||||||
|
let l:res_faces = l:res_faces . ' ctermfg=' . l:color
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
if ! l:found_gui_color && l:gui_color != ''
|
||||||
|
let l:res_faces = l:res_faces . ' guifg=' . l:gui_color
|
||||||
|
endif
|
||||||
|
elseif l:k_v[0] == ':background'
|
||||||
|
let l:gui_color = ''
|
||||||
|
let l:found_gui_color = 0
|
||||||
|
for l:color in split(l:k_v[1], ',')
|
||||||
|
if l:color =~ '^#'
|
||||||
|
let l:found_gui_color = 1
|
||||||
|
let l:res_faces = l:res_faces . ' guibg=' . l:color
|
||||||
|
elseif l:color != ''
|
||||||
|
let l:gui_color = l:color
|
||||||
|
let l:res_faces = l:res_faces . ' ctermbg=' . l:color
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
if ! l:found_gui_color && l:gui_color != ''
|
||||||
|
let l:res_faces = l:res_faces . ' guibg=' . l:gui_color
|
||||||
|
endif
|
||||||
|
elseif l:k_v[0] == ':weight' || l:k_v[0] == ':slant' || l:k_v[0] == ':decoration'
|
||||||
|
if index(l:style, l:k_v[1]) == -1
|
||||||
|
call add(l:style, l:k_v[1])
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
elseif type(l:g) == 1
|
||||||
|
" TODO emacs interprets the color and automatically determines
|
||||||
|
" whether it should be set as foreground or background color
|
||||||
|
let l:res_faces = l:res_faces . ' ctermfg=' . l:k_v[1] . ' guifg=' . l:k_v[1]
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
let l:s = ''
|
||||||
|
for l:i in l:style
|
||||||
|
if l:s == ''
|
||||||
|
let l:s = l:i
|
||||||
|
else
|
||||||
|
let l:s = l:s . ','. l:i
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
if l:s != ''
|
||||||
|
let l:res_faces = l:res_faces . ' term=' . l:s . ' cterm=' . l:s . ' gui=' . l:s
|
||||||
|
endif
|
||||||
|
elseif type(a:faces) == 1
|
||||||
|
" TODO emacs interprets the color and automatically determines
|
||||||
|
" whether it should be set as foreground or background color
|
||||||
|
let l:res_faces = l:res_faces . ' ctermfg=' . a:faces . ' guifg=' . a:faces
|
||||||
|
endif
|
||||||
|
return l:res_faces
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:ReadTodoKeywords(keywords, todo_headings)
|
||||||
|
let l:default_group = 'Todo'
|
||||||
|
for l:i in a:keywords
|
||||||
|
if type(l:i) == 3
|
||||||
|
call s:ReadTodoKeywords(l:i, a:todo_headings)
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
if l:i == '|'
|
||||||
|
let l:default_group = 'Question'
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
" strip access key
|
||||||
|
let l:_i = substitute(l:i, "\(.*$", "", "")
|
||||||
|
|
||||||
|
let l:group = l:default_group
|
||||||
|
for l:j in g:org_todo_keyword_faces
|
||||||
|
if l:j[0] == l:_i
|
||||||
|
let l:group = 'org_todo_keyword_face_' . l:_i
|
||||||
|
call OrgExtendHighlightingGroup(l:default_group, l:group, OrgInterpretFaces(l:j[1]))
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
silent! exec 'syntax match org_todo_keyword_' . l:_i . ' /\*\{1,\}\s\{1,\}\zs' . l:_i .'\(\s\|$\)/ ' . a:todo_headings
|
||||||
|
silent! exec 'hi def link org_todo_keyword_' . l:_i . ' ' . l:group
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:ReadTodoKeywords(g:org_todo_keywords, s:todo_headings)
|
||||||
|
unlet! s:todo_headings
|
||||||
|
|
||||||
|
" Timestamps: {{{1
|
||||||
|
"<2003-09-16 Tue>
|
||||||
|
"<2003-09-16 Sáb>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k>\)/
|
||||||
|
"<2003-09-16 Tue 12:00>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d>\)/
|
||||||
|
"<2003-09-16 Tue 12:00-12:30>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d-\d\d:\d\d>\)/
|
||||||
|
|
||||||
|
"<2003-09-16 Tue>--<2003-09-16 Tue>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k>--<\d\d\d\d-\d\d-\d\d \k\k\k>\)/
|
||||||
|
"<2003-09-16 Tue 12:00>--<2003-09-16 Tue 12:00>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d>--<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d>\)/
|
||||||
|
|
||||||
|
syn match org_timestamp /\(<%%(diary-float.\+>\)/
|
||||||
|
|
||||||
|
"[2003-09-16 Tue]
|
||||||
|
syn match org_timestamp_inactive /\(\[\d\d\d\d-\d\d-\d\d \k\k\k\]\)/
|
||||||
|
"[2003-09-16 Tue 12:00]
|
||||||
|
syn match org_timestamp_inactive /\(\[\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d\]\)/
|
||||||
|
|
||||||
|
"[2003-09-16 Tue]--[2003-09-16 Tue]
|
||||||
|
syn match org_timestamp_inactive /\(\[\d\d\d\d-\d\d-\d\d \k\k\k\]--\[\d\d\d\d-\d\d-\d\d \k\k\k\]\)/
|
||||||
|
"[2003-09-16 Tue 12:00]--[2003-09-16 Tue 12:00]
|
||||||
|
syn match org_timestamp_inactive /\(\[\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d\]--\[\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d\]\)/
|
||||||
|
|
||||||
|
syn match org_timestamp_inactive /\(\[%%(diary-float.\+\]\)/
|
||||||
|
|
||||||
|
hi def link org_timestamp PreProc
|
||||||
|
hi def link org_timestamp_inactive Comment
|
||||||
|
|
||||||
|
" Deadline And Schedule: {{{1
|
||||||
|
syn match org_deadline_scheduled /^\s*\(DEADLINE\|SCHEDULED\):/
|
||||||
|
hi def link org_deadline_scheduled PreProc
|
||||||
|
|
||||||
|
" Tables: {{{1
|
||||||
|
syn match org_table /^\s*|.*/ contains=org_timestamp,org_timestamp_inactive,hyperlink,org_table_separator,org_table_horizontal_line
|
||||||
|
syn match org_table_separator /\(^\s*|[-+]\+|\?\||\)/ contained
|
||||||
|
hi def link org_table_separator Type
|
||||||
|
|
||||||
|
" Hyperlinks: {{{1
|
||||||
|
syntax match hyperlink "\[\{2}[^][]*\(\]\[[^][]*\)\?\]\{2}" contains=hyperlinkBracketsLeft,hyperlinkURL,hyperlinkBracketsRight containedin=ALL
|
||||||
|
if (s:conceal_aggressively == 1)
|
||||||
|
syntax match hyperlinkBracketsLeft contained "\[\{2}#\?" conceal
|
||||||
|
else
|
||||||
|
syntax match hyperlinkBracketsLeft contained "\[\{2}" conceal
|
||||||
|
endif
|
||||||
|
syntax match hyperlinkURL contained "[^][]*\]\[" conceal
|
||||||
|
syntax match hyperlinkBracketsRight contained "\]\{2}" conceal
|
||||||
|
hi def link hyperlink Underlined
|
||||||
|
|
||||||
|
" Comments: {{{1
|
||||||
|
syntax match org_comment /^#.*/
|
||||||
|
hi def link org_comment Comment
|
||||||
|
|
||||||
|
" Bullet Lists: {{{1
|
||||||
|
" Ordered Lists:
|
||||||
|
" 1. list item
|
||||||
|
" 1) list item
|
||||||
|
" a. list item
|
||||||
|
" a) list item
|
||||||
|
syn match org_list_ordered "^\s*\(\a\|\d\+\)[.)]\(\s\|$\)" nextgroup=org_list_item
|
||||||
|
hi def link org_list_ordered Identifier
|
||||||
|
|
||||||
|
" Unordered Lists:
|
||||||
|
" - list item
|
||||||
|
" * list item
|
||||||
|
" + list item
|
||||||
|
" + and - don't need a whitespace prefix
|
||||||
|
syn match org_list_unordered "^\(\s*[-+]\|\s\+\*\)\(\s\|$\)" nextgroup=org_list_item
|
||||||
|
hi def link org_list_unordered Identifier
|
||||||
|
|
||||||
|
" Definition Lists:
|
||||||
|
" - Term :: expl.
|
||||||
|
" 1) Term :: expl.
|
||||||
|
syntax match org_list_def /.*\s\+::/ contained
|
||||||
|
hi def link org_list_def PreProc
|
||||||
|
|
||||||
|
syntax match org_list_item /.*$/ contained contains=org_subtask_percent,org_subtask_number,org_subtask_percent_100,org_subtask_number_all,org_list_checkbox,org_bold,org_italic,org_underline,org_code,org_verbatim,org_timestamp,org_timestamp_inactive,org_list_def
|
||||||
|
syntax match org_list_checkbox /\[[ X-]]/ contained
|
||||||
|
hi def link org_list_bullet Identifier
|
||||||
|
hi def link org_list_checkbox PreProc
|
||||||
|
|
||||||
|
" Block Delimiters: {{{1
|
||||||
|
syntax case ignore
|
||||||
|
syntax match org_block_delimiter /^#+BEGIN_.*/
|
||||||
|
syntax match org_block_delimiter /^#+END_.*/
|
||||||
|
syntax match org_key_identifier /^#+[^ ]*:/
|
||||||
|
syntax match org_title /^#+TITLE:.*/ contains=org_key_identifier
|
||||||
|
hi def link org_block_delimiter Comment
|
||||||
|
hi def link org_key_identifier Comment
|
||||||
|
hi def link org_title Title
|
||||||
|
|
||||||
|
" Block Markup: {{{1
|
||||||
|
" we consider all BEGIN/END sections as 'verbatim' blocks (inc. 'quote', 'verse', 'center')
|
||||||
|
" except 'example' and 'src' which are treated as 'code' blocks.
|
||||||
|
" Note: the non-standard '>' prefix is supported for quotation lines.
|
||||||
|
" Note: the '^:.*" rule must be defined before the ':PROPERTIES:' one below.
|
||||||
|
" TODO: http://vim.wikia.com/wiki/Different_syntax_highlighting_within_regions_of_a_file
|
||||||
|
syntax match org_verbatim /^\s*>.*/
|
||||||
|
syntax match org_code /^\s*:.*/
|
||||||
|
|
||||||
|
syntax region org_verbatim start="^\s*#+BEGIN_.*" end="^\s*#+END_.*" keepend contains=org_block_delimiter
|
||||||
|
syntax region org_code start="^\s*#+BEGIN_SRC" end="^\s*#+END_SRC" keepend contains=org_block_delimiter
|
||||||
|
syntax region org_code start="^\s*#+BEGIN_EXAMPLE" end="^\s*#+END_EXAMPLE" keepend contains=org_block_delimiter
|
||||||
|
|
||||||
|
hi def link org_code String
|
||||||
|
hi def link org_verbatim String
|
||||||
|
|
||||||
|
if (s:conceal_aggressively==1)
|
||||||
|
hi link org_border_code org_code
|
||||||
|
hi link org_border_verb org_verbatim
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Properties: {{{1
|
||||||
|
syn region Error matchgroup=org_properties_delimiter start=/^\s*:PROPERTIES:\s*$/ end=/^\s*:END:\s*$/ contains=org_property keepend
|
||||||
|
syn match org_property /^\s*:[^\t :]\+:\s\+[^\t ]/ contained contains=org_property_value
|
||||||
|
syn match org_property_value /:\s\zs.*/ contained
|
||||||
|
hi def link org_properties_delimiter PreProc
|
||||||
|
hi def link org_property Statement
|
||||||
|
hi def link org_property_value Constant
|
||||||
|
" Break down subtasks
|
||||||
|
syntax match org_subtask_number /\[\d*\/\d*]/ contained
|
||||||
|
syntax match org_subtask_percent /\[\d*%\]/ contained
|
||||||
|
syntax match org_subtask_number_all /\[\(\d\+\)\/\1\]/ contained
|
||||||
|
syntax match org_subtask_percent_100 /\[100%\]/ contained
|
||||||
|
|
||||||
|
hi def link org_subtask_number String
|
||||||
|
hi def link org_subtask_percent String
|
||||||
|
hi def link org_subtask_percent_100 Identifier
|
||||||
|
hi def link org_subtask_number_all Identifier
|
||||||
|
|
||||||
|
" Plugin SyntaxRange: {{{1
|
||||||
|
" This only works if you have SyntaxRange installed:
|
||||||
|
" https://github.com/vim-scripts/SyntaxRange
|
||||||
|
|
||||||
|
" BEGIN_SRC
|
||||||
|
if exists('g:loaded_SyntaxRange')
|
||||||
|
call SyntaxRange#Include('#+BEGIN_SRC vim', '#+END_SRC', 'vim', 'comment')
|
||||||
|
call SyntaxRange#Include('#+BEGIN_SRC python', '#+END_SRC', 'python', 'comment')
|
||||||
|
call SyntaxRange#Include('#+BEGIN_SRC c', '#+END_SRC', 'c', 'comment')
|
||||||
|
" cpp must be below c, otherwise you get c syntax hl for cpp files
|
||||||
|
call SyntaxRange#Include('#+BEGIN_SRC cpp', '#+END_SRC', 'cpp', 'comment')
|
||||||
|
call SyntaxRange#Include('#+BEGIN_SRC ruby', '#+END_SRC', 'ruby', 'comment')
|
||||||
|
" call SyntaxRange#Include('#+BEGIN_SRC lua', '#+END_SRC', 'lua', 'comment')
|
||||||
|
" call SyntaxRange#Include('#+BEGIN_SRC lisp', '#+END_SRC', 'lisp', 'comment')
|
||||||
|
|
||||||
|
" LaTeX
|
||||||
|
call SyntaxRange#Include('\\begin[.*]{.*}', '\\end{.*}', 'tex')
|
||||||
|
call SyntaxRange#Include('\\begin{.*}', '\\end{.*}', 'tex')
|
||||||
|
call SyntaxRange#Include('\\\[', '\\\]', 'tex')
|
||||||
|
endif
|
||||||
|
|
||||||
|
" vi: ft=vim:tw=80:sw=4:ts=4:fdm=marker
|
79
pack/acp/start/vim-orgmode/syntax/orgagenda.vim
Normal file
79
pack/acp/start/vim-orgmode/syntax/orgagenda.vim
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
" TODO do we really need a separate syntax file for the agenda?
|
||||||
|
" - Most of the stuff here is also in syntax.org
|
||||||
|
" - DRY!
|
||||||
|
|
||||||
|
syn match org_todo_key /\[\zs[^]]*\ze\]/
|
||||||
|
hi def link org_todo_key Identifier
|
||||||
|
|
||||||
|
let s:todo_headings = ''
|
||||||
|
let s:i = 1
|
||||||
|
while s:i <= g:org_heading_highlight_levels
|
||||||
|
if s:todo_headings == ''
|
||||||
|
let s:todo_headings = 'containedin=org_heading' . s:i
|
||||||
|
else
|
||||||
|
let s:todo_headings = s:todo_headings . ',org_heading' . s:i
|
||||||
|
endif
|
||||||
|
let s:i += 1
|
||||||
|
endwhile
|
||||||
|
unlet! s:i
|
||||||
|
|
||||||
|
if !exists('g:loaded_orgagenda_syntax')
|
||||||
|
let g:loaded_orgagenda_syntax = 1
|
||||||
|
function! s:ReadTodoKeywords(keywords, todo_headings)
|
||||||
|
let l:default_group = 'Todo'
|
||||||
|
for l:i in a:keywords
|
||||||
|
if type(l:i) == 3
|
||||||
|
call s:ReadTodoKeywords(l:i, a:todo_headings)
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
if l:i == '|'
|
||||||
|
let l:default_group = 'Question'
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
" strip access key
|
||||||
|
let l:_i = substitute(l:i, "\(.*$", "", "")
|
||||||
|
|
||||||
|
let l:group = l:default_group
|
||||||
|
for l:j in g:org_todo_keyword_faces
|
||||||
|
if l:j[0] == l:_i
|
||||||
|
let l:group = 'orgtodo_todo_keyword_face_' . l:_i
|
||||||
|
call OrgExtendHighlightingGroup(l:default_group, l:group, OrgInterpretFaces(l:j[1]))
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
silent! exec 'syntax match orgtodo_todo_keyword_' . l:_i . ' /' . l:_i .'/ ' . a:todo_headings
|
||||||
|
silent! exec 'hi def link orgtodo_todo_keyword_' . l:_i . ' ' . l:group
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:ReadTodoKeywords(g:org_todo_keywords, s:todo_headings)
|
||||||
|
unlet! s:todo_headings
|
||||||
|
|
||||||
|
" Timestamps
|
||||||
|
"<2003-09-16 Tue>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k>\)/
|
||||||
|
"<2003-09-16 Tue 12:00>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d>\)/
|
||||||
|
"<2003-09-16 Tue 12:00-12:30>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d-\d\d:\d\d>\)/
|
||||||
|
"<2003-09-16 Tue>--<2003-09-16 Tue>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k>--<\d\d\d\d-\d\d-\d\d \k\k\k>\)/
|
||||||
|
"<2003-09-16 Tue 12:00>--<2003-09-16 Tue 12:00>
|
||||||
|
syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d>--<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d>\)/
|
||||||
|
syn match org_timestamp /\(<%%(diary-float.\+>\)/
|
||||||
|
hi def link org_timestamp PreProc
|
||||||
|
|
||||||
|
" special words
|
||||||
|
syn match today /TODAY$/
|
||||||
|
hi def link today PreProc
|
||||||
|
|
||||||
|
syn match week_agenda /^Week Agenda:$/
|
||||||
|
hi def link week_agenda PreProc
|
||||||
|
|
||||||
|
" Hyperlinks
|
||||||
|
syntax match hyperlink "\[\{2}[^][]*\(\]\[[^][]*\)\?\]\{2}" contains=hyperlinkBracketsLeft,hyperlinkURL,hyperlinkBracketsRight containedin=ALL
|
||||||
|
syntax match hyperlinkBracketsLeft contained "\[\{2}" conceal
|
||||||
|
syntax match hyperlinkURL contained "[^][]*\]\[" conceal
|
||||||
|
syntax match hyperlinkBracketsRight contained "\]\{2}" conceal
|
||||||
|
hi def link hyperlink Underlined
|
47
pack/acp/start/vim-orgmode/syntax/orgtodo.vim
Normal file
47
pack/acp/start/vim-orgmode/syntax/orgtodo.vim
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
syn match org_todo_key /\[\zs[^]]*\ze\]/
|
||||||
|
hi def link org_todo_key Identifier
|
||||||
|
|
||||||
|
let s:todo_headings = ''
|
||||||
|
let s:i = 1
|
||||||
|
while s:i <= g:org_heading_highlight_levels
|
||||||
|
if s:todo_headings == ''
|
||||||
|
let s:todo_headings = 'containedin=org_heading' . s:i
|
||||||
|
else
|
||||||
|
let s:todo_headings = s:todo_headings . ',org_heading' . s:i
|
||||||
|
endif
|
||||||
|
let s:i += 1
|
||||||
|
endwhile
|
||||||
|
unlet! s:i
|
||||||
|
|
||||||
|
if !exists('g:loaded_orgtodo_syntax')
|
||||||
|
let g:loaded_orgtodo_syntax = 1
|
||||||
|
function! s:ReadTodoKeywords(keywords, todo_headings)
|
||||||
|
let l:default_group = 'Todo'
|
||||||
|
for l:i in a:keywords
|
||||||
|
if type(l:i) == 3
|
||||||
|
call s:ReadTodoKeywords(l:i, a:todo_headings)
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
if l:i == '|'
|
||||||
|
let l:default_group = 'Question'
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
" strip access key
|
||||||
|
let l:_i = substitute(l:i, "\(.*$", "", "")
|
||||||
|
|
||||||
|
let l:group = l:default_group
|
||||||
|
for l:j in g:org_todo_keyword_faces
|
||||||
|
if l:j[0] == l:_i
|
||||||
|
let l:group = 'orgtodo_todo_keyword_face_' . l:_i
|
||||||
|
call OrgExtendHighlightingGroup(l:default_group, l:group, OrgInterpretFaces(l:j[1]))
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
silent! exec 'syntax match orgtodo_todo_keyword_' . l:_i . ' /' . l:_i .'/ ' . a:todo_headings
|
||||||
|
silent! exec 'hi def link orgtodo_todo_keyword_' . l:_i . ' ' . l:group
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:ReadTodoKeywords(g:org_todo_keywords, s:todo_headings)
|
||||||
|
unlet! s:todo_headings
|
37
pack/acp/start/vim-orgmode/tests/orgmode_testfile.org
Normal file
37
pack/acp/start/vim-orgmode/tests/orgmode_testfile.org
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
* bold, italics and underline syntax matching
|
||||||
|
** Should match:
|
||||||
|
|
||||||
|
*foo* *foo*
|
||||||
|
*Really, quite long sentence*.
|
||||||
|
_foo_ _foo_
|
||||||
|
_really, quite long sentence._.
|
||||||
|
|
||||||
|
*Übermensch á* *eä* *ý€*
|
||||||
|
_Ÿ ï_
|
||||||
|
|
||||||
|
*sdf l.*
|
||||||
|
*sdfsdf ,.*
|
||||||
|
*foo_ sdf /*
|
||||||
|
/sdf sdf sdf ./
|
||||||
|
|
||||||
|
/google.com/
|
||||||
|
|
||||||
|
*[sdf]*
|
||||||
|
*a* /a/ =b= ~b~ `d`
|
||||||
|
|
||||||
|
*abc* /abc/ =bde= ~bde~ `def`
|
||||||
|
*=*a*=*
|
||||||
|
** Should not match
|
||||||
|
http://google.com/
|
||||||
|
//google.com/
|
||||||
|
* sdf* _ sdf_
|
||||||
|
*sdfsdf sdf,*
|
||||||
|
*foo *
|
||||||
|
foo_not underlined_bar
|
||||||
|
|
||||||
|
*.sdf*[
|
||||||
|
[*.sdf*
|
||||||
|
[*sdf*]
|
||||||
|
*=*a*=
|
||||||
|
|
59
pack/acp/start/vim-orgmode/tests/run_tests.py
Executable file
59
pack/acp/start/vim-orgmode/tests/run_tests.py
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import test_vimbuffer
|
||||||
|
|
||||||
|
import test_libagendafilter
|
||||||
|
import test_libcheckbox
|
||||||
|
import test_libbase
|
||||||
|
import test_libheading
|
||||||
|
import test_liborgdate
|
||||||
|
import test_liborgdate_utf8
|
||||||
|
import test_liborgdate_parsing
|
||||||
|
import test_liborgdatetime
|
||||||
|
import test_liborgtimerange
|
||||||
|
|
||||||
|
import test_plugin_date
|
||||||
|
import test_plugin_edit_structure
|
||||||
|
import test_plugin_edit_checkbox
|
||||||
|
import test_plugin_misc
|
||||||
|
import test_plugin_navigator
|
||||||
|
import test_plugin_show_hide
|
||||||
|
import test_plugin_tags_properties
|
||||||
|
import test_plugin_todo
|
||||||
|
import test_plugin_mappings
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
tests = unittest.TestSuite()
|
||||||
|
|
||||||
|
tests.addTests(test_vimbuffer.suite())
|
||||||
|
|
||||||
|
# lib
|
||||||
|
tests.addTests(test_libbase.suite())
|
||||||
|
tests.addTests(test_libcheckbox.suite())
|
||||||
|
tests.addTests(test_libagendafilter.suite())
|
||||||
|
tests.addTests(test_libheading.suite())
|
||||||
|
tests.addTests(test_liborgdate.suite())
|
||||||
|
tests.addTests(test_liborgdate_utf8.suite())
|
||||||
|
tests.addTests(test_liborgdate_parsing.suite())
|
||||||
|
tests.addTests(test_liborgdatetime.suite())
|
||||||
|
tests.addTests(test_liborgtimerange.suite())
|
||||||
|
|
||||||
|
# plugins
|
||||||
|
tests.addTests(test_plugin_date.suite())
|
||||||
|
tests.addTests(test_plugin_edit_structure.suite())
|
||||||
|
tests.addTests(test_plugin_edit_checkbox.suite())
|
||||||
|
tests.addTests(test_plugin_misc.suite())
|
||||||
|
tests.addTests(test_plugin_navigator.suite())
|
||||||
|
tests.addTests(test_plugin_show_hide.suite())
|
||||||
|
tests.addTests(test_plugin_tags_properties.suite())
|
||||||
|
tests.addTests(test_plugin_todo.suite())
|
||||||
|
tests.addTests(test_plugin_mappings.suite())
|
||||||
|
|
||||||
|
runner = unittest.TextTestRunner()
|
||||||
|
runner.run(tests)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
171
pack/acp/start/vim-orgmode/tests/test_libagendafilter.py
Normal file
171
pack/acp/start/vim-orgmode/tests/test_libagendafilter.py
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from datetime import date
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from orgmode.liborgmode.headings import Heading
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDate
|
||||||
|
from orgmode.liborgmode.agendafilter import contains_active_todo
|
||||||
|
from orgmode.liborgmode.agendafilter import contains_active_date
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDateTime
|
||||||
|
from orgmode.liborgmode.agendafilter import is_within_week
|
||||||
|
from orgmode.liborgmode.agendafilter import is_within_week_and_active_todo
|
||||||
|
from orgmode.liborgmode.agendafilter import filter_items
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
|
||||||
|
class AgendaFilterTestCase(unittest.TestCase):
|
||||||
|
u"""Tests all the functionality of the Agenda filter module."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
global counter
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0')
|
||||||
|
}
|
||||||
|
vim.current.buffer[:] = [u_encode(i) for i in u"""
|
||||||
|
* TODO Heading 1
|
||||||
|
some text
|
||||||
|
""".split(u'\n')]
|
||||||
|
|
||||||
|
def test_contains_active_todo(self):
|
||||||
|
heading = Heading(title=u'Refactor the code', todo='TODO')
|
||||||
|
self.assertTrue(contains_active_todo(heading))
|
||||||
|
|
||||||
|
heading = Heading(title=u'Refactor the code', todo='DONE')
|
||||||
|
self.assertFalse(contains_active_todo(heading))
|
||||||
|
|
||||||
|
heading = Heading(title=u'Refactor the code', todo=None)
|
||||||
|
self.assertFalse(contains_active_todo(heading))
|
||||||
|
|
||||||
|
def test_contains_active_date(self):
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=None)
|
||||||
|
self.assertFalse(contains_active_date(heading))
|
||||||
|
|
||||||
|
odate = OrgDate(True, 2011, 11, 1)
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
self.assertTrue(contains_active_date(heading))
|
||||||
|
|
||||||
|
def test_is_within_week_with_orgdate(self):
|
||||||
|
# to far in the future
|
||||||
|
tmpdate = date.today() + timedelta(days=8)
|
||||||
|
odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
self.assertFalse(is_within_week(heading))
|
||||||
|
|
||||||
|
# within a week
|
||||||
|
tmpdate = date.today() + timedelta(days=5)
|
||||||
|
odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
self.assertTrue(is_within_week(heading))
|
||||||
|
|
||||||
|
# in the past
|
||||||
|
tmpdate = date.today() - timedelta(days=105)
|
||||||
|
odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
self.assertTrue(is_within_week(heading))
|
||||||
|
|
||||||
|
def test_is_within_week_with_orgdatetime(self):
|
||||||
|
# to far in the future
|
||||||
|
tmp = date.today() + timedelta(days=1000)
|
||||||
|
odate = OrgDateTime(True, tmp.year, tmp.month, tmp.day, 10, 10)
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
self.assertFalse(is_within_week(heading))
|
||||||
|
|
||||||
|
# within a week
|
||||||
|
tmpdate = date.today() + timedelta(days=5)
|
||||||
|
odate = OrgDateTime(True, tmpdate.year, tmpdate.month, tmpdate.day, 1, 0)
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
self.assertTrue(is_within_week(heading))
|
||||||
|
|
||||||
|
# in the past
|
||||||
|
tmpdate = date.today() - timedelta(days=5)
|
||||||
|
odate = OrgDateTime(True, tmpdate.year, tmpdate.month, tmpdate.day, 1, 0)
|
||||||
|
heading = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
self.assertTrue(is_within_week(heading))
|
||||||
|
|
||||||
|
def test_filter_items(self):
|
||||||
|
# only headings with date and todo should be returned
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = \
|
||||||
|
[u_encode(u'TODO'), u_encode(u'STARTED'), u_encode(u'|'), u_encode(u'DONE')]
|
||||||
|
tmpdate = date.today()
|
||||||
|
odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
|
||||||
|
tmp_head = Heading(title=u'Refactor the code', todo=u'TODO', active_date=odate)
|
||||||
|
tmp_head_01 = Heading(title=u'Refactor the code', todo=u'STARTED', active_date=odate)
|
||||||
|
# TODO add more tests
|
||||||
|
headings = [tmp_head, tmp_head_01]
|
||||||
|
filtered = list(filter_items(headings,
|
||||||
|
[contains_active_date, contains_active_todo]))
|
||||||
|
|
||||||
|
self.assertEqual(len(filtered), 2)
|
||||||
|
self.assertEqual(filtered, headings)
|
||||||
|
|
||||||
|
# try a longer list
|
||||||
|
headings = headings * 3
|
||||||
|
filtered = list(filter_items(headings,
|
||||||
|
[contains_active_date, contains_active_todo]))
|
||||||
|
|
||||||
|
self.assertEqual(len(filtered), 6)
|
||||||
|
self.assertEqual(filtered, headings)
|
||||||
|
|
||||||
|
# date does not contain all needed fields thus gets ignored
|
||||||
|
tmpdate = date.today()
|
||||||
|
odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
|
||||||
|
tmp_head = Heading(title=u'Refactor the code', active_date=odate)
|
||||||
|
headings = [tmp_head]
|
||||||
|
filtered = list(filter_items(headings, [contains_active_date,
|
||||||
|
contains_active_todo]))
|
||||||
|
self.assertEqual([], filtered)
|
||||||
|
|
||||||
|
def test_filter_items_with_some_todos_and_dates(self):
|
||||||
|
u"""
|
||||||
|
Only the headings with todo and dates should be retunrned.
|
||||||
|
"""
|
||||||
|
tmp = [u"* TODO OrgMode Demo und Tests"
|
||||||
|
u"<2011-08-22 Mon>"]
|
||||||
|
headings = [Heading.parse_heading_from_data(tmp, [u'TODO'])]
|
||||||
|
filtered = list(filter_items(headings,
|
||||||
|
[is_within_week_and_active_todo]))
|
||||||
|
self.assertEqual(len(filtered), 1)
|
||||||
|
self.assertEqual(headings, filtered)
|
||||||
|
|
||||||
|
tmp = [Heading.parse_heading_from_data([u"** DONE something <2011-08-10 Wed>"], [u'TODO']),
|
||||||
|
Heading.parse_heading_from_data([u"*** TODO rsitenaoritns more <2011-08-25 Thu>"], [u'TODO']),
|
||||||
|
Heading.parse_heading_from_data([u"*** DONE some more <2011-08-25 Thu>"], [u'TODO']),
|
||||||
|
Heading.parse_heading_from_data([u"*** TODO some more <2011-08-25 Thu>"], [u'TODO']),
|
||||||
|
Heading.parse_heading_from_data([u"** DONE something2 <2011-08-10 Wed>"], [u'TODO'])
|
||||||
|
]
|
||||||
|
for h in tmp:
|
||||||
|
headings.append(h)
|
||||||
|
|
||||||
|
filtered = list(filter_items(headings,
|
||||||
|
[is_within_week_and_active_todo]))
|
||||||
|
self.assertEqual(len(filtered), 3)
|
||||||
|
self.assertEqual(filtered, [headings[0], headings[2], headings[4]])
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(AgendaFilterTestCase)
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
34
pack/acp/start/vim-orgmode/tests/test_libbase.py
Normal file
34
pack/acp/start/vim-orgmode/tests/test_libbase.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
from orgmode.liborgmode.base import Direction, get_domobj_range
|
||||||
|
from orgmode.liborgmode.headings import Heading
|
||||||
|
|
||||||
|
|
||||||
|
class LibBaseTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.case1 = """
|
||||||
|
* head1
|
||||||
|
heading body
|
||||||
|
for testing
|
||||||
|
* head2
|
||||||
|
** head3
|
||||||
|
""".split("\n")
|
||||||
|
|
||||||
|
def test_base_functions(self):
|
||||||
|
# direction FORWARD
|
||||||
|
(start, end) = get_domobj_range(content=self.case1, position=1, identify_fun=Heading.identify_heading)
|
||||||
|
self.assertEqual((start, end), (1, 3))
|
||||||
|
(start, end) = get_domobj_range(content=self.case1, position=3, direction=Direction.BACKWARD, \
|
||||||
|
identify_fun=Heading.identify_heading)
|
||||||
|
self.assertEqual((start, end), (1, 3))
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(
|
||||||
|
LibBaseTestCase)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
132
pack/acp/start/vim-orgmode/tests/test_libcheckbox.py
Normal file
132
pack/acp/start/vim-orgmode/tests/test_libcheckbox.py
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import vim
|
||||||
|
from orgmode.liborgmode.checkboxes import Checkbox
|
||||||
|
from orgmode._vim import ORGMODE
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
def set_vim_buffer(buf=None, cursor=(2, 0), bufnr=0):
|
||||||
|
if buf is None:
|
||||||
|
buf = []
|
||||||
|
vim.current.buffer[:] = buf
|
||||||
|
vim.current.window.cursor = cursor
|
||||||
|
vim.current.buffer.number = bufnr
|
||||||
|
|
||||||
|
|
||||||
|
class CheckboxTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
counter = 0
|
||||||
|
vim.CMDHISTORY = []
|
||||||
|
vim.CMDRESULTS = {}
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_improve_split_heading")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_improve_split_heading")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u'&ts'): u_encode(u'8'),
|
||||||
|
u_encode(u'exists("g:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0')}
|
||||||
|
|
||||||
|
self.c1 = """
|
||||||
|
* heading1 [/]
|
||||||
|
- [-] checkbox1 [%]
|
||||||
|
- [X] checkbox2
|
||||||
|
- [ ] checkbox3
|
||||||
|
- [X] checkbox4
|
||||||
|
""".split("\n")
|
||||||
|
|
||||||
|
self.c2 = """
|
||||||
|
* heading1
|
||||||
|
- [ ] checkbox1
|
||||||
|
- [ ] checkbox2
|
||||||
|
- [ ] checkbox3
|
||||||
|
- [ ] checkbox4
|
||||||
|
- [ ] checkbox5
|
||||||
|
- [ ] checkbox6
|
||||||
|
""".split("\n")
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
# test initialize Checkbox
|
||||||
|
c = Checkbox(level=1, title="checkbox1")
|
||||||
|
self.assertEqual(str(c), " - [ ] checkbox1")
|
||||||
|
c = Checkbox(level=3, title="checkbox2", status="[X]")
|
||||||
|
self.assertEqual(str(c), " - [X] checkbox2")
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
bufnr = 1
|
||||||
|
set_vim_buffer(buf=self.c1, bufnr=bufnr)
|
||||||
|
h = ORGMODE.get_document(bufnr=bufnr).current_heading()
|
||||||
|
h.init_checkboxes()
|
||||||
|
|
||||||
|
c = h.current_checkbox(position=2)
|
||||||
|
self.assertEqual(str(c), self.c1[2])
|
||||||
|
self.assertFalse(c.are_children_all(Checkbox.STATUS_ON))
|
||||||
|
self.assertTrue(c.is_child_one(Checkbox.STATUS_OFF))
|
||||||
|
self.assertFalse(c.are_siblings_all(Checkbox.STATUS_ON))
|
||||||
|
|
||||||
|
for child in c.all_children():
|
||||||
|
pass
|
||||||
|
for sibling in c.all_siblings():
|
||||||
|
pass
|
||||||
|
c = h.current_checkbox(position=3)
|
||||||
|
new_checkbox = c.copy()
|
||||||
|
self.assertEqual(str(c), self.c1[3])
|
||||||
|
c.get_parent_list()
|
||||||
|
c.get_index_in_parent_list()
|
||||||
|
|
||||||
|
def test_identify(self):
|
||||||
|
# test identify_checkbox
|
||||||
|
self.assertEqual(Checkbox.identify_checkbox(self.c1[2]), 2)
|
||||||
|
self.assertEqual(Checkbox.identify_checkbox(self.c1[3]), 8)
|
||||||
|
# check for corner case
|
||||||
|
self.assertEqual(Checkbox.identify_checkbox(" - [ ]"), 1)
|
||||||
|
|
||||||
|
def test_toggle(self):
|
||||||
|
bufnr = 2
|
||||||
|
# test init_checkboxes
|
||||||
|
set_vim_buffer(buf=self.c1, bufnr=bufnr)
|
||||||
|
h = ORGMODE.get_document(bufnr=bufnr).current_heading()
|
||||||
|
h.init_checkboxes()
|
||||||
|
|
||||||
|
# toggle checkbox
|
||||||
|
c = h.current_checkbox(position=4)
|
||||||
|
c.toggle()
|
||||||
|
self.assertEqual(str(c), " - [X] checkbox3")
|
||||||
|
c.toggle()
|
||||||
|
self.assertEqual(str(c), " - [ ] checkbox3")
|
||||||
|
|
||||||
|
(total, on) = c.all_siblings_status()
|
||||||
|
self.assertEqual((total, on), (2, 1))
|
||||||
|
|
||||||
|
def test_subtasks(self):
|
||||||
|
bufnr = 3
|
||||||
|
set_vim_buffer(buf=self.c1, bufnr=bufnr)
|
||||||
|
h = ORGMODE.get_document(bufnr=bufnr).current_heading()
|
||||||
|
h.init_checkboxes()
|
||||||
|
c = h.current_checkbox(position=3)
|
||||||
|
c.toggle()
|
||||||
|
c = h.current_checkbox(position=2)
|
||||||
|
(total, on) = c.all_siblings_status()
|
||||||
|
c.update_subtasks(total=total, on=on)
|
||||||
|
self.assertEqual(str(c), " - [-] checkbox1 [50%]")
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(CheckboxTestCase)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
156
pack/acp/start/vim-orgmode/tests/test_libheading.py
Normal file
156
pack/acp/start/vim-orgmode/tests/test_libheading.py
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
from orgmode.liborgmode.headings import Heading
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDate
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDateTime
|
||||||
|
|
||||||
|
|
||||||
|
class TestHeadingRecognizeDatesInHeading(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.allowed_todo_states = ["TODO"]
|
||||||
|
|
||||||
|
tmp = ["* This heading is earlier <2011-08-24 Wed>"]
|
||||||
|
self.h1 = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
|
||||||
|
|
||||||
|
tmp = ["* This heading is later <2011-08-25 Thu>"]
|
||||||
|
self.h2 = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
|
||||||
|
|
||||||
|
tmp = ["* This heading is later <2011-08-25 Thu 10:20>"]
|
||||||
|
self.h2_datetime = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
|
||||||
|
|
||||||
|
tmp = ["* This heading is later <2011-08-26 Fri 10:20>"]
|
||||||
|
self.h3 = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
|
||||||
|
|
||||||
|
tmp = ["* This heading has no date and should be later than the rest"]
|
||||||
|
self.h_no_date = Heading.parse_heading_from_data(tmp,
|
||||||
|
self.allowed_todo_states)
|
||||||
|
|
||||||
|
def test_heading_parsing_no_date(self):
|
||||||
|
"""""
|
||||||
|
'text' doesn't contain any valid date.
|
||||||
|
"""
|
||||||
|
text = ["* TODO This is a test :hallo:"]
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertEqual(None, h.active_date)
|
||||||
|
|
||||||
|
text = ["* TODO This is a test <2011-08-25>"]
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertEqual(None, h.active_date)
|
||||||
|
|
||||||
|
text = ["* TODO This is a test <2011-08-25 Wednesday>"]
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertEqual(None, h.active_date)
|
||||||
|
|
||||||
|
text = ["* TODO This is a test <20110825>"]
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertEqual(None, h.active_date)
|
||||||
|
|
||||||
|
def test_heading_parsing_with_date(self):
|
||||||
|
"""""
|
||||||
|
'text' does contain valid dates.
|
||||||
|
"""
|
||||||
|
# orgdate
|
||||||
|
text = ["* TODO This is a test <2011-08-24 Wed> :hallo:"]
|
||||||
|
odate = OrgDate(True, 2011, 8, 24)
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertEqual(odate, h.active_date)
|
||||||
|
|
||||||
|
# orgdatetime
|
||||||
|
text = ["* TODO This is a test <2011-08-25 Thu 10:10> :hallo:"]
|
||||||
|
odate = OrgDateTime(True, 2011, 8, 25, 10, 10)
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertEqual(odate, h.active_date)
|
||||||
|
|
||||||
|
def test_heading_parsing_with_date_and_body(self):
|
||||||
|
"""""
|
||||||
|
'text' contains valid dates (in the body).
|
||||||
|
"""
|
||||||
|
# orgdatetime
|
||||||
|
text = ["* TODO This is a test <2011-08-25 Thu 10:10> :hallo:",
|
||||||
|
"some body text",
|
||||||
|
"some body text"]
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertTrue(isinstance(h.active_date, OrgDateTime))
|
||||||
|
self.assertEqual("<2011-08-25 Thu 10:10>", str(h.active_date))
|
||||||
|
|
||||||
|
text = ["* TODO This is a test :hallo:",
|
||||||
|
"some body text",
|
||||||
|
"some body text<2011-08-25 Thu 10:10>"]
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
self.assertTrue(isinstance(h.active_date, OrgDateTime))
|
||||||
|
self.assertEqual("<2011-08-25 Thu 10:10>", str(h.active_date))
|
||||||
|
|
||||||
|
text = ["* TODO This is a test :hallo:",
|
||||||
|
"some body text <2011-08-24 Wed>",
|
||||||
|
"some body text<2011-08-25 Thu 10:10>"]
|
||||||
|
h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
|
||||||
|
odate = OrgDate(True, 2011, 8, 24)
|
||||||
|
self.assertEqual(odate, h.active_date)
|
||||||
|
|
||||||
|
def test_less_than_for_dates_in_heading(self):
|
||||||
|
self.assertTrue(self.h1 < self.h2)
|
||||||
|
self.assertTrue(self.h1 < self.h3)
|
||||||
|
self.assertTrue(self.h1 < self.h_no_date)
|
||||||
|
self.assertTrue(self.h2 < self.h_no_date)
|
||||||
|
self.assertTrue(self.h2 < self.h3)
|
||||||
|
self.assertTrue(self.h3 < self.h_no_date)
|
||||||
|
|
||||||
|
self.assertFalse(self.h2 < self.h1)
|
||||||
|
self.assertFalse(self.h3 < self.h2)
|
||||||
|
|
||||||
|
def test_less_equal_for_dates_in_heading(self):
|
||||||
|
self.assertTrue(self.h1 <= self.h2)
|
||||||
|
self.assertTrue(self.h1 <= self.h_no_date)
|
||||||
|
self.assertTrue(self.h2 <= self.h_no_date)
|
||||||
|
self.assertTrue(self.h2 <= self.h2_datetime)
|
||||||
|
self.assertTrue(self.h2 <= self.h3)
|
||||||
|
|
||||||
|
def test_greate_than_for_dates_in_heading(self):
|
||||||
|
self.assertTrue(self.h2 > self.h1)
|
||||||
|
self.assertTrue(self.h_no_date > self.h1)
|
||||||
|
self.assertTrue(self.h_no_date > self.h2)
|
||||||
|
|
||||||
|
self.assertFalse(self.h2 > self.h2_datetime)
|
||||||
|
|
||||||
|
def test_greate_equal_for_dates_in_heading(self):
|
||||||
|
self.assertTrue(self.h2 >= self.h1)
|
||||||
|
self.assertTrue(self.h_no_date >= self.h1)
|
||||||
|
self.assertTrue(self.h_no_date >= self.h2)
|
||||||
|
self.assertTrue(self.h2 >= self.h2_datetime)
|
||||||
|
|
||||||
|
def test_sorting_of_headings(self):
|
||||||
|
"""Headings should be sortable."""
|
||||||
|
self.assertEqual([self.h1, self.h2], sorted([self.h2, self.h1]))
|
||||||
|
|
||||||
|
self.assertEqual([self.h1, self.h2_datetime],
|
||||||
|
sorted([self.h2_datetime, self.h1]))
|
||||||
|
|
||||||
|
self.assertEqual([self.h2_datetime, self.h2],
|
||||||
|
sorted([self.h2_datetime, self.h2]))
|
||||||
|
|
||||||
|
self.assertEqual([self.h1, self.h2], sorted([self.h1, self.h2]))
|
||||||
|
|
||||||
|
self.assertEqual([self.h1, self.h_no_date],
|
||||||
|
sorted([self.h1, self.h_no_date]))
|
||||||
|
|
||||||
|
self.assertEqual([self.h1, self.h_no_date],
|
||||||
|
sorted([self.h_no_date, self.h1]))
|
||||||
|
|
||||||
|
self.assertEqual([self.h1, self.h2, self.h_no_date],
|
||||||
|
sorted([self.h2, self.h_no_date, self.h1]))
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[self.h1, self.h2_datetime, self.h2, self.h3, self.h_no_date],
|
||||||
|
sorted([self.h2_datetime, self.h3, self.h2, self.h_no_date, self.h1]))
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(
|
||||||
|
TestHeadingRecognizeDatesInHeading)
|
||||||
|
|
||||||
|
# vim: set noexpandtab:
|
53
pack/acp/start/vim-orgmode/tests/test_liborgdate.py
Normal file
53
pack/acp/start/vim-orgmode/tests/test_liborgdate.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDate
|
||||||
|
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
class OrgDateTestCase(unittest.TestCase):
|
||||||
|
u"""
|
||||||
|
Tests all the functionality of the OrgDate
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.date = date(2011, 8, 29)
|
||||||
|
self.year = 2011
|
||||||
|
self.month = 8
|
||||||
|
self.day = 29
|
||||||
|
self.text = u'<2011-08-29 Mon>'
|
||||||
|
self.textinactive = u'[2011-08-29 Mon]'
|
||||||
|
|
||||||
|
def test_OrgDate_ctor_active(self):
|
||||||
|
u"""OrdDate should be created."""
|
||||||
|
today = date.today()
|
||||||
|
od = OrgDate(True, today.year, today.month, today.day)
|
||||||
|
self.assertTrue(isinstance(od, OrgDate))
|
||||||
|
self.assertTrue(od.active)
|
||||||
|
|
||||||
|
def test_OrgDate_ctor_inactive(self):
|
||||||
|
u"""OrdDate should be created."""
|
||||||
|
today = date.today()
|
||||||
|
od = OrgDate(False, today.year, today.month, today.day)
|
||||||
|
self.assertTrue(isinstance(od, OrgDate))
|
||||||
|
self.assertFalse(od.active)
|
||||||
|
|
||||||
|
def test_OrdDate_str_active(self):
|
||||||
|
u"""Representation of OrgDates"""
|
||||||
|
od = OrgDate(True, self.year, self.month, self.day)
|
||||||
|
self.assertEqual(self.text, unicode(od))
|
||||||
|
|
||||||
|
def test_OrdDate_str_inactive(self):
|
||||||
|
od = OrgDate(False, self.year, self.month, self.day)
|
||||||
|
self.assertEqual(self.textinactive, unicode(od))
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(OrgDateTestCase)
|
||||||
|
|
||||||
|
# vi: noexpandtab
|
248
pack/acp/start/vim-orgmode/tests/test_liborgdate_parsing.py
Normal file
248
pack/acp/start/vim-orgmode/tests/test_liborgdate_parsing.py
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
from orgmode.liborgmode.orgdate import get_orgdate
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDate
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDateTime
|
||||||
|
from orgmode.liborgmode.orgdate import OrgTimeRange
|
||||||
|
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
class OrgDateParsingTestCase(unittest.TestCase):
|
||||||
|
u"""
|
||||||
|
Tests the functionality of the parsing function of OrgDate.
|
||||||
|
|
||||||
|
Mostly function get_orgdate().
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.text = u'<2011-08-29 Mon>'
|
||||||
|
self.textinactive = u'[2011-08-29 Mon]'
|
||||||
|
|
||||||
|
def test_get_orgdate_parsing_active(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should recognize all orgdates in a given text
|
||||||
|
"""
|
||||||
|
result = get_orgdate(self.text)
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDate))
|
||||||
|
self.assertTrue(isinstance(get_orgdate(u"<2011-08-30 Tue>"), OrgDate))
|
||||||
|
self.assertEqual(get_orgdate(u"<2011-08-30 Tue>").year, 2011)
|
||||||
|
self.assertEqual(get_orgdate(u"<2011-08-30 Tue>").month, 8)
|
||||||
|
self.assertEqual(get_orgdate(u"<2011-08-30 Tue>").day, 30)
|
||||||
|
self.assertTrue(get_orgdate(u"<2011-08-30 Tue>").active)
|
||||||
|
|
||||||
|
datestr = u"This date <2011-08-30 Tue> is embedded"
|
||||||
|
self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_orgdatetime_parsing_active(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should recognize all orgdatetimes in a given text
|
||||||
|
"""
|
||||||
|
result = get_orgdate(u"<2011-09-12 Mon 10:20>")
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
self.assertEqual(result.year, 2011)
|
||||||
|
self.assertEqual(result.month, 9)
|
||||||
|
self.assertEqual(result.day, 12)
|
||||||
|
self.assertEqual(result.hour, 10)
|
||||||
|
self.assertEqual(result.minute, 20)
|
||||||
|
self.assertTrue(result.active)
|
||||||
|
|
||||||
|
result = get_orgdate(u"some datetime <2011-09-12 Mon 10:20> stuff")
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_orgtimerange_parsing_active(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should recognize all orgtimeranges in a given text
|
||||||
|
"""
|
||||||
|
daterangestr = u"<2011-09-12 Mon>--<2011-09-13 Tue>"
|
||||||
|
result = get_orgdate(daterangestr)
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgTimeRange))
|
||||||
|
self.assertEqual(unicode(result), daterangestr)
|
||||||
|
self.assertTrue(result.active)
|
||||||
|
|
||||||
|
daterangestr = u"<2011-09-12 Mon 10:20>--<2011-09-13 Tue 13:20>"
|
||||||
|
result = get_orgdate(daterangestr)
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgTimeRange))
|
||||||
|
self.assertEqual(unicode(result), daterangestr)
|
||||||
|
self.assertTrue(result.active)
|
||||||
|
|
||||||
|
daterangestr = u"<2011-09-12 Mon 10:20-13:20>"
|
||||||
|
result = get_orgdate(daterangestr)
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgTimeRange))
|
||||||
|
self.assertEqual(unicode(result), daterangestr)
|
||||||
|
self.assertTrue(result.active)
|
||||||
|
|
||||||
|
def test_get_orgdate_parsing_inactive(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should recognize all inactive orgdates in a given text
|
||||||
|
"""
|
||||||
|
result = get_orgdate(self.textinactive)
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDate))
|
||||||
|
self.assertTrue(isinstance(get_orgdate(u"[2011-08-30 Tue]"), OrgDate))
|
||||||
|
self.assertEqual(get_orgdate(u"[2011-08-30 Tue]").year, 2011)
|
||||||
|
self.assertEqual(get_orgdate(u"[2011-08-30 Tue]").month, 8)
|
||||||
|
self.assertEqual(get_orgdate(u"[2011-08-30 Tue]").day, 30)
|
||||||
|
self.assertFalse(get_orgdate(u"[2011-08-30 Tue]").active)
|
||||||
|
|
||||||
|
datestr = u"This date [2011-08-30 Tue] is embedded"
|
||||||
|
self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
|
||||||
|
|
||||||
|
def test_get_orgdatetime_parsing_passive(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should recognize all orgdatetimes in a given text
|
||||||
|
"""
|
||||||
|
result = get_orgdate(u"[2011-09-12 Mon 10:20]")
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
self.assertEqual(result.year, 2011)
|
||||||
|
self.assertEqual(result.month, 9)
|
||||||
|
self.assertEqual(result.day, 12)
|
||||||
|
self.assertEqual(result.hour, 10)
|
||||||
|
self.assertEqual(result.minute, 20)
|
||||||
|
self.assertFalse(result.active)
|
||||||
|
|
||||||
|
result = get_orgdate(u"some datetime [2011-09-12 Mon 10:20] stuff")
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
|
||||||
|
def test_get_orgdate_parsing_with_list_of_texts(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should return the first date in the list.
|
||||||
|
"""
|
||||||
|
datelist = [u"<2011-08-29 Mon>"]
|
||||||
|
result = get_orgdate(datelist)
|
||||||
|
self.assertNotEquals(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDate))
|
||||||
|
self.assertEqual(result.year, 2011)
|
||||||
|
self.assertEqual(result.month, 8)
|
||||||
|
self.assertEqual(result.day, 29)
|
||||||
|
|
||||||
|
datelist = [u"<2011-08-29 Mon>",
|
||||||
|
u"<2012-03-30 Fri>"]
|
||||||
|
result = get_orgdate(datelist)
|
||||||
|
self.assertNotEquals(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDate))
|
||||||
|
self.assertEqual(result.year, 2011)
|
||||||
|
self.assertEqual(result.month, 8)
|
||||||
|
self.assertEqual(result.day, 29)
|
||||||
|
|
||||||
|
datelist = [u"some <2011-08-29 Mon>text",
|
||||||
|
u"<2012-03-30 Fri> is here"]
|
||||||
|
result = get_orgdate(datelist)
|
||||||
|
self.assertNotEquals(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDate))
|
||||||
|
self.assertEqual(result.year, 2011)
|
||||||
|
self.assertEqual(result.month, 8)
|
||||||
|
self.assertEqual(result.day, 29)
|
||||||
|
|
||||||
|
datelist = [u"here is no date",
|
||||||
|
u"some <2011-08-29 Mon>text",
|
||||||
|
u"<2012-03-30 Fri> is here"]
|
||||||
|
result = get_orgdate(datelist)
|
||||||
|
self.assertNotEquals(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDate))
|
||||||
|
self.assertEqual(result.year, 2011)
|
||||||
|
self.assertEqual(result.month, 8)
|
||||||
|
self.assertEqual(result.day, 29)
|
||||||
|
|
||||||
|
datelist = [u"here is no date",
|
||||||
|
u"some <2011-08-29 Mon 20:10> text",
|
||||||
|
u"<2012-03-30 Fri> is here"]
|
||||||
|
result = get_orgdate(datelist)
|
||||||
|
self.assertNotEquals(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
self.assertEqual(result.year, 2011)
|
||||||
|
self.assertEqual(result.month, 8)
|
||||||
|
self.assertEqual(result.day, 29)
|
||||||
|
self.assertEqual(result.hour, 20)
|
||||||
|
self.assertEqual(result.minute, 10)
|
||||||
|
|
||||||
|
def test_get_orgdate_parsing_with_invalid_input(self):
|
||||||
|
self.assertEquals(get_orgdate(u"NONSENSE"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"No D<2011- Date 08-29 Mon>"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"2011-08-r9 Mon]"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"<2011-08-29 Mon"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"<2011-08-29 Mon]"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"2011-08-29 Mon"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"2011-08-29"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"2011-08-29 mon"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"<2011-08-29 mon>"), None)
|
||||||
|
|
||||||
|
self.assertEquals(get_orgdate(u"wrong date embedded <2011-08-29 mon>"), None)
|
||||||
|
self.assertEquals(get_orgdate(u"wrong date <2011-08-29 mon>embedded "), None)
|
||||||
|
|
||||||
|
def test_get_orgdate_parsing_with_invalid_dates(self):
|
||||||
|
u"""
|
||||||
|
Something like <2011-14-29 Mon> (invalid dates, they don't exist)
|
||||||
|
should not be parsed
|
||||||
|
"""
|
||||||
|
datestr = u"<2011-14-30 Tue>"
|
||||||
|
self.assertEqual(get_orgdate(datestr), None)
|
||||||
|
|
||||||
|
datestr = u"<2012-03-40 Tue>"
|
||||||
|
self.assertEqual(get_orgdate(datestr), None)
|
||||||
|
|
||||||
|
datestr = u"<2012-03-40 Tue 24:70>"
|
||||||
|
self.assertEqual(get_orgdate(datestr), None)
|
||||||
|
|
||||||
|
def test_get_orgdate_parsing_with_utf8(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should recognize all orgdates within a given utf-8 text
|
||||||
|
"""
|
||||||
|
result = get_orgdate(u'<2016-05-07 Sáb>')
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDate))
|
||||||
|
self.assertEqual(result.year, 2016)
|
||||||
|
self.assertEqual(result.month, 5)
|
||||||
|
self.assertEqual(result.day, 7)
|
||||||
|
self.assertTrue(result.active)
|
||||||
|
|
||||||
|
datestr = u"This date <2016-05-07 Sáb> is embedded"
|
||||||
|
self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
|
||||||
|
|
||||||
|
result = get_orgdate(u'[2016-05-07 Sáb]')
|
||||||
|
self.assertFalse(result.active)
|
||||||
|
|
||||||
|
datestr = u"This date [2016-05-07 Sáb] is embedded"
|
||||||
|
self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
|
||||||
|
|
||||||
|
def test_get_orgdatetime_parsing_with_utf8(self):
|
||||||
|
u"""
|
||||||
|
get_orgdate should recognize all orgdatetimes in a given utf-8 text
|
||||||
|
"""
|
||||||
|
result = get_orgdate(u"<2016-05-07 Sáb 10:20>")
|
||||||
|
self.assertNotEqual(result, None)
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
self.assertEqual(result.year, 2016)
|
||||||
|
self.assertEqual(result.month, 5)
|
||||||
|
self.assertEqual(result.day, 7)
|
||||||
|
self.assertEqual(result.hour, 10)
|
||||||
|
self.assertEqual(result.minute, 20)
|
||||||
|
self.assertTrue(result.active)
|
||||||
|
|
||||||
|
result = get_orgdate(u"some datetime <2016-05-07 Sáb 10:20> stuff")
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
|
||||||
|
result = get_orgdate(u"[2016-05-07 Sáb 10:20]")
|
||||||
|
self.assertFalse(result.active)
|
||||||
|
|
||||||
|
result = get_orgdate(u"some datetime [2016-05-07 Sáb 10:20] stuff")
|
||||||
|
self.assertTrue(isinstance(result, OrgDateTime))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(OrgDateParsingTestCase)
|
||||||
|
|
||||||
|
# vim: noexpandtab
|
52
pack/acp/start/vim-orgmode/tests/test_liborgdate_utf8.py
Normal file
52
pack/acp/start/vim-orgmode/tests/test_liborgdate_utf8.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import locale
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDate
|
||||||
|
|
||||||
|
class OrgDateUtf8TestCase(unittest.TestCase):
|
||||||
|
u"""
|
||||||
|
Tests OrgDate with utf-8 enabled locales
|
||||||
|
"""
|
||||||
|
LOCALE_LOCK = threading.Lock()
|
||||||
|
UTF8_LOCALE = "pt_BR.utf-8"
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def setlocale(self, name):
|
||||||
|
with self.LOCALE_LOCK:
|
||||||
|
saved = locale.setlocale(locale.LC_ALL)
|
||||||
|
try:
|
||||||
|
yield locale.setlocale(locale.LC_ALL, name)
|
||||||
|
finally:
|
||||||
|
locale.setlocale(locale.LC_ALL, saved)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.year = 2016
|
||||||
|
self.month = 5
|
||||||
|
self.day = 7
|
||||||
|
self.text = u'<2016-05-07 Sáb>'
|
||||||
|
self.textinactive = u'[2016-05-07 Sáb]'
|
||||||
|
|
||||||
|
def test_OrdDate_str_unicode_active(self):
|
||||||
|
with self.setlocale(self.UTF8_LOCALE):
|
||||||
|
od = OrgDate(True, self.year, self.month, self.day)
|
||||||
|
self.assertEqual(self.text, unicode(od))
|
||||||
|
|
||||||
|
def test_OrdDate_str_unicode_inactive(self):
|
||||||
|
with self.setlocale(self.UTF8_LOCALE):
|
||||||
|
od = OrgDate(False, self.year, self.month, self.day)
|
||||||
|
self.assertEqual(self.textinactive, unicode(od))
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(OrgDateUtf8TestCase)
|
||||||
|
|
||||||
|
# vi: noexpandtab
|
50
pack/acp/start/vim-orgmode/tests/test_liborgdatetime.py
Normal file
50
pack/acp/start/vim-orgmode/tests/test_liborgdatetime.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
from orgmode.liborgmode.orgdate import OrgDateTime
|
||||||
|
|
||||||
|
from orgmode.py3compat.unicode_compatibility import *
|
||||||
|
|
||||||
|
class OrgDateTimeTestCase(unittest.TestCase):
|
||||||
|
u"""
|
||||||
|
Tests all the functionality of the OrgDateTime
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_OrgDateTime_ctor_active(self):
|
||||||
|
u"""OrdDateTime should be created."""
|
||||||
|
today = datetime.today()
|
||||||
|
odt = OrgDateTime(True, today.year, today.month, today.day, today.hour,
|
||||||
|
today.minute)
|
||||||
|
self.assertTrue(isinstance(odt, OrgDateTime))
|
||||||
|
self.assertTrue(odt.active)
|
||||||
|
|
||||||
|
def test_OrgDateTime_ctor_inactive(self):
|
||||||
|
u"""OrdDateTime should be created."""
|
||||||
|
today = datetime.today()
|
||||||
|
odt = OrgDateTime(False, today.year, today.month, today.day, today.hour,
|
||||||
|
today.minute)
|
||||||
|
self.assertTrue(isinstance(odt, OrgDateTime))
|
||||||
|
self.assertFalse(odt.active)
|
||||||
|
|
||||||
|
def test_OrdDateTime_str_active(self):
|
||||||
|
u"""Representation of OrgDateTime"""
|
||||||
|
t = 2011, 9, 8, 10, 20
|
||||||
|
odt = OrgDateTime(False, t[0], t[1], t[2], t[3], t[4])
|
||||||
|
self.assertEqual(u"[2011-09-08 Thu 10:20]", unicode(odt))
|
||||||
|
|
||||||
|
def test_OrdDateTime_str_inactive(self):
|
||||||
|
u"""Representation of OrgDateTime"""
|
||||||
|
t = 2011, 9, 8, 10, 20
|
||||||
|
odt = OrgDateTime(True, t[0], t[1], t[2], t[3], t[4])
|
||||||
|
self.assertEqual(u"<2011-09-08 Thu 10:20>", unicode(odt))
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(OrgDateTimeTestCase)
|
||||||
|
|
||||||
|
|
||||||
|
# vim: noexpandtab
|
86
pack/acp/start/vim-orgmode/tests/test_liborgtimerange.py
Normal file
86
pack/acp/start/vim-orgmode/tests/test_liborgtimerange.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from datetime import date
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
from orgmode.liborgmode.orgdate import OrgTimeRange
|
||||||
|
|
||||||
|
|
||||||
|
class OrgTimeRangeTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.date = date(2011, 8, 29)
|
||||||
|
self.year = 2011
|
||||||
|
self.month = 8
|
||||||
|
self.day = 29
|
||||||
|
self.text = '<2011-08-29 Mon>'
|
||||||
|
self.textinactive = '[2011-08-29 Mon]'
|
||||||
|
|
||||||
|
def test_OrgTimeRange_ctor_active(self):
|
||||||
|
u"""
|
||||||
|
timerange should be created.
|
||||||
|
"""
|
||||||
|
start = date(2011, 9 , 12)
|
||||||
|
end = date(2011, 9 , 13)
|
||||||
|
timerange = OrgTimeRange(True, start, end)
|
||||||
|
self.assertTrue(isinstance(timerange, OrgTimeRange))
|
||||||
|
self.assertTrue(timerange.active)
|
||||||
|
|
||||||
|
def test_OrgTimeRange_ctor_inactive(self):
|
||||||
|
u"""
|
||||||
|
timerange should be created.
|
||||||
|
"""
|
||||||
|
start = date(2011, 9 , 12)
|
||||||
|
end = date(2011, 9 , 13)
|
||||||
|
timerange = OrgTimeRange(False, start, end)
|
||||||
|
self.assertTrue(isinstance(timerange, OrgTimeRange))
|
||||||
|
self.assertFalse(timerange.active)
|
||||||
|
|
||||||
|
def test_OrdDate_str_active(self):
|
||||||
|
u"""Representation of OrgDates"""
|
||||||
|
start = date(2011, 9 , 12)
|
||||||
|
end = date(2011, 9 , 13)
|
||||||
|
timerange = OrgTimeRange(True, start, end)
|
||||||
|
expected = "<2011-09-12 Mon>--<2011-09-13 Tue>"
|
||||||
|
self.assertEqual(str(timerange), expected)
|
||||||
|
|
||||||
|
start = datetime(2011, 9 , 12, 20, 00)
|
||||||
|
end = datetime(2011, 9 , 13, 21, 59)
|
||||||
|
timerange = OrgTimeRange(True, start, end)
|
||||||
|
expected = "<2011-09-12 Mon 20:00>--<2011-09-13 Tue 21:59>"
|
||||||
|
self.assertEqual(str(timerange), expected)
|
||||||
|
|
||||||
|
start = datetime(2011, 9 , 12, 20, 00)
|
||||||
|
end = datetime(2011, 9 , 12, 21, 00)
|
||||||
|
timerange = OrgTimeRange(True, start, end)
|
||||||
|
expected = "<2011-09-12 Mon 20:00-21:00>"
|
||||||
|
self.assertEqual(str(timerange), expected)
|
||||||
|
|
||||||
|
def test_OrdDate_str_inactive(self):
|
||||||
|
u"""Representation of OrgDates"""
|
||||||
|
start = date(2011, 9 , 12)
|
||||||
|
end = date(2011, 9 , 13)
|
||||||
|
timerange = OrgTimeRange(False, start, end)
|
||||||
|
expected = "[2011-09-12 Mon]--[2011-09-13 Tue]"
|
||||||
|
self.assertEqual(str(timerange), expected)
|
||||||
|
|
||||||
|
start = datetime(2011, 9 , 12, 20, 00)
|
||||||
|
end = datetime(2011, 9 , 13, 21, 59)
|
||||||
|
timerange = OrgTimeRange(False, start, end)
|
||||||
|
expected = "[2011-09-12 Mon 20:00]--[2011-09-13 Tue 21:59]"
|
||||||
|
self.assertEqual(str(timerange), expected)
|
||||||
|
|
||||||
|
start = datetime(2011, 9 , 12, 20, 00)
|
||||||
|
end = datetime(2011, 9 , 12, 21, 00)
|
||||||
|
timerange = OrgTimeRange(False, start, end)
|
||||||
|
expected = "[2011-09-12 Mon 20:00-21:00]"
|
||||||
|
self.assertEqual(str(timerange), expected)
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(OrgTimeRangeTestCase)
|
||||||
|
|
||||||
|
# vim: noexpandtab
|
174
pack/acp/start/vim-orgmode/tests/test_plugin_date.py
Normal file
174
pack/acp/start/vim-orgmode/tests/test_plugin_date.py
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from orgmode.plugins.Date import Date
|
||||||
|
|
||||||
|
|
||||||
|
class DateTestCase(unittest.TestCase):
|
||||||
|
u"""Tests all the functionality of the Date plugin.
|
||||||
|
|
||||||
|
Also see:
|
||||||
|
http://orgmode.org/manual/The-date_002ftime-prompt.html#The-date_002ftime-prompt
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.d = date(2011, 5, 22)
|
||||||
|
|
||||||
|
def test_modify_time_with_None(self):
|
||||||
|
# no modification should happen
|
||||||
|
res = Date._modify_time(self.d, None)
|
||||||
|
self.assertEquals(self.d, res)
|
||||||
|
|
||||||
|
def test_modify_time_with_dot(self):
|
||||||
|
# no modification should happen
|
||||||
|
res = Date._modify_time(self.d, u'.')
|
||||||
|
self.assertEquals(self.d, res)
|
||||||
|
|
||||||
|
def test_modify_time_with_given_relative_days(self):
|
||||||
|
# modifier and expected result
|
||||||
|
test_data = [(u'+0d', self.d),
|
||||||
|
(u'+1d', date(2011, 5, 23)),
|
||||||
|
(u'+2d', date(2011, 5, 24)),
|
||||||
|
(u'+7d', date(2011, 5, 29)),
|
||||||
|
(u'+9d', date(2011, 5, 31)),
|
||||||
|
(u'+10d', date(2011, 6, 1)),
|
||||||
|
(u'7d', self.d)] # wrong format: plus is missing
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(self.d, modifier))
|
||||||
|
|
||||||
|
def test_modify_time_with_given_relative_days_without_d(self):
|
||||||
|
# modifier and expected result
|
||||||
|
test_data = [(u'+0', self.d),
|
||||||
|
(u'+1', date(2011, 5, 23)),
|
||||||
|
(u'+2', date(2011, 5, 24)),
|
||||||
|
(u'+7', date(2011, 5, 29)),
|
||||||
|
(u'+9', date(2011, 5, 31)),
|
||||||
|
(u'+10', date(2011, 6, 1))]
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
result = Date._modify_time(self.d, modifier)
|
||||||
|
self.assertEquals(expected, result)
|
||||||
|
|
||||||
|
def test_modify_time_with_given_relative_weeks(self):
|
||||||
|
# modifier and expected result
|
||||||
|
test_data = [(u'+1w', date(2011, 5, 29)),
|
||||||
|
(u'+2w', date(2011, 6, 5)),
|
||||||
|
(u'+3w', date(2011, 6, 12)),
|
||||||
|
(u'+3w', date(2011, 6, 12)),
|
||||||
|
(u'+0w', self.d),
|
||||||
|
(u'3w', self.d), # wrong format
|
||||||
|
(u'+w', self.d)] # wrong format
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(self.d, modifier))
|
||||||
|
|
||||||
|
def test_modify_time_with_given_relative_months(self):
|
||||||
|
test_data = [(u'+0m', self.d),
|
||||||
|
(u'+1m', date(2011, 6, 22)),
|
||||||
|
(u'+2m', date(2011, 7, 22))]
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(self.d, modifier))
|
||||||
|
|
||||||
|
def test_modify_time_with_given_relative_years(self):
|
||||||
|
test_data = [(u'+1y', date(2012, 5, 22)),
|
||||||
|
(u'+10y', date(2021, 5, 22)),
|
||||||
|
(u'+0y', self.d)]
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(self.d, modifier))
|
||||||
|
|
||||||
|
|
||||||
|
def test_modify_time_with_given_weekday(self):
|
||||||
|
# use custom day instead of self.d to ease testing
|
||||||
|
cust_day = date(2011, 5, 25) # it's a Wednesday
|
||||||
|
#print(cust_day.weekday()) # 2
|
||||||
|
test_data = [(u'Thu', date(2011, 5, 26)),
|
||||||
|
(u'thu', date(2011, 5, 26)),
|
||||||
|
(u'tHU', date(2011, 5, 26)),
|
||||||
|
(u'THU', date(2011, 5, 26)),
|
||||||
|
(u'Fri', date(2011, 5, 27)),
|
||||||
|
(u'sat', date(2011, 5, 28)),
|
||||||
|
(u'sun', date(2011, 5, 29)),
|
||||||
|
(u'mon', date(2011, 5, 30)),
|
||||||
|
(u'tue', date(2011, 5, 31)),
|
||||||
|
(u'wed', date(2011, 6, 1))]
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(cust_day, modifier))
|
||||||
|
|
||||||
|
def test_modify_time_with_month_and_day(self):
|
||||||
|
cust_date = date(2006, 6, 13)
|
||||||
|
test_data = [(u'sep 15', date(2006, 9, 15)),
|
||||||
|
(u'Sep 15', date(2006, 9, 15)),
|
||||||
|
(u'SEP 15', date(2006, 9, 15)),
|
||||||
|
(u'feb 15', date(2007, 2, 15)),
|
||||||
|
(u'jan 1', date(2007, 1, 1)),
|
||||||
|
(u'7/5', date(2006, 7, 5)),
|
||||||
|
(u'2/5', date(2007, 2, 5)),]
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(cust_date, modifier))
|
||||||
|
|
||||||
|
def test_modify_time_with_time(self):
|
||||||
|
cust_date = date(2006, 6, 13)
|
||||||
|
test_data = [(u'12:45', datetime(2006, 6, 13, 12, 45)),
|
||||||
|
(u'1:45', datetime(2006, 6, 13, 1, 45)),
|
||||||
|
(u'1:05', datetime(2006, 6, 13, 1, 5)),]
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
res = Date._modify_time(cust_date, modifier)
|
||||||
|
self.assertTrue(isinstance(res, datetime))
|
||||||
|
self.assertEquals(expected, res)
|
||||||
|
|
||||||
|
def test_modify_time_with_full_dates(self):
|
||||||
|
result = Date._modify_time(self.d, u'2011-01-12')
|
||||||
|
expected = date(2011, 1, 12)
|
||||||
|
self.assertEquals(expected, result)
|
||||||
|
|
||||||
|
reults = Date._modify_time(self.d, u'2015-03-12')
|
||||||
|
expected = date(2015, 3, 12)
|
||||||
|
self.assertEquals(expected, reults)
|
||||||
|
|
||||||
|
cust_date = date(2006, 6, 13)
|
||||||
|
test_data = [(u'3-2-5', date(2003, 2, 5)),
|
||||||
|
(u'12-2-28', date(2012, 2, 28)),
|
||||||
|
(u'2/5/3', date(2003, 2, 5)),
|
||||||
|
(u'sep 12 9', date(2009, 9, 12)),
|
||||||
|
(u'jan 2 99', date(2099, 1, 2)),]
|
||||||
|
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(cust_date, modifier))
|
||||||
|
|
||||||
|
def test_modify_time_with_only_days(self):
|
||||||
|
cust_date = date(2006, 6, 13)
|
||||||
|
test_data = [(u'14', date(2006, 6, 14)),
|
||||||
|
(u'12', date(2006, 7, 12)),
|
||||||
|
(u'1', date(2006, 7, 1)),
|
||||||
|
(u'29', date(2006, 6, 29)),]
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
self.assertEquals(expected, Date._modify_time(cust_date, modifier))
|
||||||
|
|
||||||
|
def test_modify_time_with_day_and_time(self):
|
||||||
|
cust_date = date(2006, 6, 13)
|
||||||
|
test_data = [(u'+1 10:20', datetime(2006, 6, 14, 10, 20)),
|
||||||
|
(u'+1w 10:20', datetime(2006, 6, 20, 10, 20)),
|
||||||
|
(u'+2 10:30', datetime(2006, 6, 15, 10, 30)),
|
||||||
|
(u'+2d 10:30', datetime(2006, 6, 15, 10, 30))]
|
||||||
|
for modifier, expected in test_data:
|
||||||
|
result = Date._modify_time(cust_date, modifier)
|
||||||
|
self.assertEquals(expected, result)
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(DateTestCase)
|
||||||
|
|
||||||
|
# vi: noexpandtab
|
241
pack/acp/start/vim-orgmode/tests/test_plugin_edit_checkbox.py
Normal file
241
pack/acp/start/vim-orgmode/tests/test_plugin_edit_checkbox.py
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
PLUGIN_NAME = u'EditCheckbox'
|
||||||
|
|
||||||
|
bufnr = 10
|
||||||
|
|
||||||
|
def set_vim_buffer(buf=None, cursor=(2, 0), bufnr=0):
|
||||||
|
if buf is None:
|
||||||
|
buf = []
|
||||||
|
vim.current.buffer[:] = buf
|
||||||
|
vim.current.window.cursor = cursor
|
||||||
|
vim.current.buffer.number = bufnr
|
||||||
|
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
class EditCheckboxTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
if PLUGIN_NAME not in ORGMODE.plugins:
|
||||||
|
ORGMODE.register_plugin(PLUGIN_NAME)
|
||||||
|
self.editcheckbox = ORGMODE.plugins[PLUGIN_NAME]
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_improve_split_heading")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_improve_split_heading")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u'&ts'): u_encode(u'8'),
|
||||||
|
u_encode(u'exists("g:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0'),
|
||||||
|
# jump to insert mode after adding heading/checkbox
|
||||||
|
u_encode(u'exists("g:org_prefer_insert_mode")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_prefer_insert_mode")'): u_encode(u'0')}
|
||||||
|
|
||||||
|
self.c1 = u"""
|
||||||
|
* heading1 [%]
|
||||||
|
- [ ] checkbox1 [/]
|
||||||
|
- [ ] checkbox2
|
||||||
|
- [ ] checkbox3
|
||||||
|
- [ ] checkbox4
|
||||||
|
- [ ] checkbox5
|
||||||
|
- [ ] checkbox6
|
||||||
|
- [ ] checkbox7
|
||||||
|
- [ ] checkbox8
|
||||||
|
""".split(u'\n')
|
||||||
|
|
||||||
|
self.c2 = u"""
|
||||||
|
* a checkbox list [%]
|
||||||
|
- checkbox [0%]
|
||||||
|
- [ ] test1
|
||||||
|
- [ ] test2
|
||||||
|
- [ ] test3
|
||||||
|
""".split(u'\n')
|
||||||
|
|
||||||
|
self.c3 = u"""
|
||||||
|
* heading
|
||||||
|
1. [ ] another main task [%]
|
||||||
|
- [ ] sub task 1
|
||||||
|
- [ ] sub task 2
|
||||||
|
2. [ ] another main task
|
||||||
|
""".split(u'\n')
|
||||||
|
|
||||||
|
self.c4 = u"""
|
||||||
|
* heading
|
||||||
|
""".split(u'\n')
|
||||||
|
|
||||||
|
self.c5 = u"""
|
||||||
|
* heading1
|
||||||
|
1. item
|
||||||
|
9. item
|
||||||
|
}. item
|
||||||
|
a. item
|
||||||
|
z. item
|
||||||
|
A. item
|
||||||
|
Z. item
|
||||||
|
aa. item
|
||||||
|
""".split("\n")
|
||||||
|
|
||||||
|
def test_toggle(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
# test on self.c1
|
||||||
|
set_vim_buffer(buf=self.c1, cursor=(6, 0), bufnr=bufnr)
|
||||||
|
# update_checkboxes_status
|
||||||
|
self.editcheckbox.update_checkboxes_status()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u"* heading1 [0%]")
|
||||||
|
# toggle
|
||||||
|
self.editcheckbox.toggle()
|
||||||
|
self.assertEqual(vim.current.buffer[5], u" - [X] checkbox4")
|
||||||
|
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c1, cursor=(9, 0), bufnr=bufnr)
|
||||||
|
# toggle and check checkbox status
|
||||||
|
self.editcheckbox.toggle()
|
||||||
|
self.assertEqual(vim.current.buffer[8], u" - [X] checkbox7")
|
||||||
|
self.assertEqual(vim.current.buffer[7], u" - [-] checkbox6")
|
||||||
|
self.assertEqual(vim.current.buffer[6], u" - [-] checkbox5")
|
||||||
|
|
||||||
|
# new_checkbox
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c1, cursor=(9, 0), bufnr=bufnr)
|
||||||
|
vim.current.window.cursor = (9, 0)
|
||||||
|
self.assertEqual(vim.current.buffer[9], u' - [ ] checkbox8')
|
||||||
|
self.editcheckbox.new_checkbox(below=True)
|
||||||
|
# vim's buffer behave just opposite to Python's list when inserting a
|
||||||
|
# new item. The new entry is appended in vim put prepended in Python!
|
||||||
|
self.assertEqual(vim.current.buffer[10], u' - [ ] checkbox8')
|
||||||
|
self.assertEqual(vim.current.buffer[9], u' - [ ] ')
|
||||||
|
self.editcheckbox.update_checkboxes_status()
|
||||||
|
|
||||||
|
def test_no_status_checkbox(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
# test on self.c2
|
||||||
|
set_vim_buffer(buf=self.c2, bufnr=bufnr)
|
||||||
|
self.assertEqual(vim.current.buffer[2], u" - checkbox [0%]")
|
||||||
|
# toggle
|
||||||
|
vim.current.window.cursor = (4, 0)
|
||||||
|
self.editcheckbox.toggle()
|
||||||
|
self.assertEqual(vim.current.buffer[3], u" - [X] test1")
|
||||||
|
|
||||||
|
# self.editcheckbox.update_checkboxes_status()
|
||||||
|
# see if the no status checkbox update its status
|
||||||
|
self.assertEqual(vim.current.buffer[2], u" - checkbox [33%]")
|
||||||
|
|
||||||
|
def test_number_list(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c3, bufnr=bufnr)
|
||||||
|
vim.current.window.cursor = (6, 0)
|
||||||
|
self.editcheckbox.toggle()
|
||||||
|
self.assertEqual(vim.current.buffer[5], u" 2. [X] another main task")
|
||||||
|
|
||||||
|
def test_new_checkbox(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c4, bufnr=bufnr)
|
||||||
|
vim.current.window.cursor = (2, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=True)
|
||||||
|
self.assertEqual(vim.current.buffer[2], u" - [ ] ")
|
||||||
|
|
||||||
|
def test_item_decrement(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c5, bufnr=bufnr)
|
||||||
|
|
||||||
|
vim.current.window.cursor = (3, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=False, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[2], u" 0. ")
|
||||||
|
self.assertEqual(vim.current.buffer[3], u" 1. item")
|
||||||
|
|
||||||
|
vim.current.window.cursor = (3, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=False, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[1], u"* heading1")
|
||||||
|
self.assertEqual(vim.current.buffer[2], u" 0. ")
|
||||||
|
self.assertEqual(vim.current.buffer[3], u" 1. item")
|
||||||
|
|
||||||
|
vim.current.window.cursor = (5, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=False, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[4], u" 8. ")
|
||||||
|
self.assertEqual(vim.current.buffer[5], u" 9. item")
|
||||||
|
|
||||||
|
vim.current.window.cursor = (8, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=False, plain=True)
|
||||||
|
# no further decrement than a
|
||||||
|
self.assertEqual(vim.current.buffer[6], u" }. item")
|
||||||
|
self.assertEqual(vim.current.buffer[7], u" a. item")
|
||||||
|
self.assertEqual(vim.current.buffer[8], u" z. item")
|
||||||
|
|
||||||
|
def test_item_decrementA(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c5, bufnr=bufnr)
|
||||||
|
vim.current.window.cursor = (8, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=False, plain=True)
|
||||||
|
# decrement from A to z
|
||||||
|
self.assertEqual(vim.current.buffer[7], u" z. ")
|
||||||
|
self.assertEqual(vim.current.buffer[8], u" A. item")
|
||||||
|
|
||||||
|
def test_item_increment(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c5, bufnr=bufnr)
|
||||||
|
|
||||||
|
vim.current.window.cursor = (3, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=True, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[2], u" 1. item")
|
||||||
|
self.assertEqual(vim.current.buffer[3], u" 2. ")
|
||||||
|
|
||||||
|
vim.current.window.cursor = (5, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=True, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[4], u" 9. item")
|
||||||
|
self.assertEqual(vim.current.buffer[5], u" }. item")
|
||||||
|
self.assertEqual(vim.current.buffer[6], u" 10. ")
|
||||||
|
|
||||||
|
def test_item_incrementz(self):
|
||||||
|
global bufnr
|
||||||
|
bufnr += 1
|
||||||
|
set_vim_buffer(buf=self.c5, bufnr=bufnr)
|
||||||
|
|
||||||
|
vim.current.window.cursor = (6, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=True, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[5], u" a. item")
|
||||||
|
self.assertEqual(vim.current.buffer[6], u" b. ")
|
||||||
|
|
||||||
|
vim.current.window.cursor = (8, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=True, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[7], u" z. item")
|
||||||
|
self.assertEqual(vim.current.buffer[8], u" A. ")
|
||||||
|
|
||||||
|
vim.current.window.cursor = (11, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=True, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[10], u" Z. item")
|
||||||
|
self.assertEqual(vim.current.buffer[11], u" aa. item")
|
||||||
|
self.assertEqual(vim.current.buffer[12], u"")
|
||||||
|
|
||||||
|
vim.current.window.cursor = (12, 1)
|
||||||
|
self.editcheckbox.new_checkbox(below=True, plain=True)
|
||||||
|
self.assertEqual(vim.current.buffer[11], u" aa. item")
|
||||||
|
self.assertEqual(vim.current.buffer[12], u"")
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(EditCheckboxTestCase)
|
||||||
|
|
||||||
|
# vim: set noexpandtab
|
387
pack/acp/start/vim-orgmode/tests/test_plugin_edit_structure.py
Normal file
387
pack/acp/start/vim-orgmode/tests/test_plugin_edit_structure.py
Normal file
|
@ -0,0 +1,387 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
class EditStructureTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
global counter
|
||||||
|
counter += 1
|
||||||
|
vim.CMDHISTORY = []
|
||||||
|
vim.CMDRESULTS = {}
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_improve_split_heading")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_improve_split_heading")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u'&ts'): u_encode(u'8'),
|
||||||
|
u_encode(u'exists("g:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0'),
|
||||||
|
# jump to insert mode after adding heading/checkbox
|
||||||
|
u_encode(u'exists("g:org_prefer_insert_mode")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_prefer_insert_mode")'): u_encode(u'0')}
|
||||||
|
if not u'EditStructure' in ORGMODE.plugins:
|
||||||
|
ORGMODE.register_plugin(u'EditStructure')
|
||||||
|
self.editstructure = ORGMODE.plugins[u'EditStructure']
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
*** Überschrift 1.2.1
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n')]
|
||||||
|
|
||||||
|
def test_new_heading_below_normal_behavior(self):
|
||||||
|
vim.current.window.cursor = (1, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True), None)
|
||||||
|
self.assertEqual(vim.current.buffer[0], u_encode(u'* '))
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
|
||||||
|
def test_new_heading_above_normal_behavior(self):
|
||||||
|
vim.current.window.cursor = (1, 1)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=False), None)
|
||||||
|
self.assertEqual(vim.current.buffer[0], u_encode(u'* '))
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
|
||||||
|
def test_new_heading_below(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.current.buffer[5] = u_encode(u'** Überschrift 1.1 :Tag:')
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=False), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 6gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[4], u_encode(u'Bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'* '))
|
||||||
|
self.assertEqual(vim.current.buffer[6], u_encode(u'** Überschrift 1.1 :Tag:'))
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
def test_new_heading_below_insert_mode(self):
|
||||||
|
vim.current.window.cursor = (2, 1)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 3gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[2], u_encode(u'* Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'Bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[6], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
def test_new_heading_below_split_text_at_the_end(self):
|
||||||
|
vim.current.buffer[1] = u_encode(u'* Überschriftx1')
|
||||||
|
vim.current.window.cursor = (2, 14)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 3gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[2], u_encode(u'* '))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'Bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[6], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
def test_new_heading_below_split_text_at_the_end_insert_parts(self):
|
||||||
|
vim.current.window.cursor = (2, 14)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 3gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[2], u_encode(u'* 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'Bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[6], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
def test_new_heading_below_in_the_middle(self):
|
||||||
|
vim.current.window.cursor = (10, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 13gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[11], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'** '))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
|
||||||
|
def test_new_heading_below_in_the_middle2(self):
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 16gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[14], u_encode(u'Bla Bla bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'**** '))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
|
||||||
|
def test_new_heading_below_in_the_middle3(self):
|
||||||
|
vim.current.window.cursor = (16, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 17gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** '))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
def test_new_heading_below_at_the_end(self):
|
||||||
|
vim.current.window.cursor = (18, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 21gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[19], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[20], u_encode(u'* '))
|
||||||
|
self.assertEqual(len(vim.current.buffer), 21)
|
||||||
|
|
||||||
|
def test_new_heading_above(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=False, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 2gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[0], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* '))
|
||||||
|
self.assertEqual(vim.current.buffer[2], u_encode(u'* Überschrift 1'))
|
||||||
|
|
||||||
|
def test_new_heading_above_in_the_middle(self):
|
||||||
|
vim.current.window.cursor = (10, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=False, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 10gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[8], u_encode(u'Bla Bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[9], u_encode(u'** '))
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'** Überschrift 1.2'))
|
||||||
|
|
||||||
|
def test_new_heading_above_in_the_middle2(self):
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=False, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 13gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[11], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'**** '))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
|
||||||
|
def test_new_heading_above_in_the_middle3(self):
|
||||||
|
vim.current.window.cursor = (16, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=False, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 16gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[14], u_encode(u'Bla Bla bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'*** '))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
|
||||||
|
def test_new_heading_above_at_the_end(self):
|
||||||
|
vim.current.window.cursor = (18, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=False, insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 18gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'* Überschrift 2'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* '))
|
||||||
|
self.assertEqual(vim.current.buffer[18], u_encode(u'* Überschrift 3'))
|
||||||
|
|
||||||
|
def test_new_heading_below_split_heading_title(self):
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1 :Tag:
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
*** Überschrift 1.2.1
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n')]
|
||||||
|
vim.current.window.cursor = (2, 6)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.current.buffer[0], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Über :Tag:'))
|
||||||
|
self.assertEqual(vim.current.buffer[2], u_encode(u'* schrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[3], u_encode(u'Text 1'))
|
||||||
|
|
||||||
|
def test_new_heading_below_split_heading_title_with_todo(self):
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* TODO Überschrift 1 :Tag:
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
*** Überschrift 1.2.1
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n')]
|
||||||
|
vim.current.window.cursor = (2, 5)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(insert_mode=True), None)
|
||||||
|
self.assertEqual(vim.current.buffer[0], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* TODO :Tag:'))
|
||||||
|
self.assertEqual(vim.current.buffer[2], u_encode(u'* Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[3], u_encode(u'Text 1'))
|
||||||
|
|
||||||
|
def test_demote_heading(self):
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.demote_heading(), None)
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'Text 3'))
|
||||||
|
self.assertEqual(vim.current.buffer[11], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'***** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u''))
|
||||||
|
# actually the indentation comes through vim, just the heading is updated
|
||||||
|
self.assertEqual(vim.current.buffer[14], u_encode(u'Bla Bla bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (13, 1))
|
||||||
|
|
||||||
|
def test_demote_newly_created_level_one_heading(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True), None)
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'* '))
|
||||||
|
self.assertEqual(vim.current.buffer[6], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (6, 2)
|
||||||
|
self.assertNotEqual(self.editstructure.demote_heading(), None)
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'** '))
|
||||||
|
self.assertEqual(vim.current.buffer[6], u_encode(u'*** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'*** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'***** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'**** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
def test_demote_newly_created_level_two_heading(self):
|
||||||
|
vim.current.window.cursor = (10, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.new_heading(below=True), None)
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[9], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'** '))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (13, 3)
|
||||||
|
self.assertNotEqual(self.editstructure.demote_heading(including_children=False, on_heading=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'exe "normal 13gg"|startinsert!'))
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[9], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'*** '))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u'**** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[17], u_encode(u'* Überschrift 2'))
|
||||||
|
|
||||||
|
def test_demote_last_heading(self):
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3""".split('\n')]
|
||||||
|
vim.current.window.cursor = (3, 0)
|
||||||
|
h = ORGMODE.get_document().current_heading()
|
||||||
|
self.assertNotEqual(self.editstructure.demote_heading(), None)
|
||||||
|
self.assertEqual(h.end, 2)
|
||||||
|
self.assertFalse(vim.CMDHISTORY)
|
||||||
|
self.assertEqual(vim.current.buffer[2], u_encode(u'** Überschrift 3'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (3, 1))
|
||||||
|
|
||||||
|
def test_promote_heading(self):
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.promote_heading(), None)
|
||||||
|
self.assertEqual(vim.current.buffer[10], u_encode(u'Text 3'))
|
||||||
|
self.assertEqual(vim.current.buffer[11], u_encode(u''))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'*** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[13], u_encode(u''))
|
||||||
|
# actually the indentation comes through vim, just the heading is updated
|
||||||
|
self.assertEqual(vim.current.buffer[14], u_encode(u'Bla Bla bla bla'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'*** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (13, -1))
|
||||||
|
|
||||||
|
def test_promote_level_one_heading(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.assertEqual(self.editstructure.promote_heading(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 0)
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_demote_parent_heading(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.demote_heading(), None)
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'** Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'*** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[9], u_encode(u'*** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'***** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'**** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'* Überschrift 2'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 1))
|
||||||
|
|
||||||
|
def test_promote_parent_heading(self):
|
||||||
|
vim.current.window.cursor = (10, 0)
|
||||||
|
self.assertNotEqual(self.editstructure.promote_heading(), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal 10ggV16gg='))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[9], u_encode(u'* Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'*** Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'* Überschrift 2'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, -1))
|
||||||
|
|
||||||
|
# run tests with count
|
||||||
|
def test_demote_parent_heading_count(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u"v:count"] = u_encode(u'3')
|
||||||
|
self.assertNotEqual(self.editstructure.demote_heading(), None)
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'**** Überschrift 1'))
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'***** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[9], u_encode(u'***** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'******* Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'****** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'* Überschrift 2'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'* Überschrift 2'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 3))
|
||||||
|
|
||||||
|
def test_promote_parent_heading(self):
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
vim.EVALRESULTS[u"v:count"] = u_encode(u'3')
|
||||||
|
self.assertNotEqual(self.editstructure.promote_heading(), None)
|
||||||
|
self.assertEqual(vim.current.buffer[5], u_encode(u'** Überschrift 1.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[9], u_encode(u'** Überschrift 1.2'))
|
||||||
|
self.assertEqual(vim.current.buffer[12], u_encode(u'* Überschrift 1.2.1.falsch'))
|
||||||
|
self.assertEqual(vim.current.buffer[15], u_encode(u'** Überschrift 1.2.1'))
|
||||||
|
self.assertEqual(vim.current.buffer[16], u_encode(u'* Überschrift 2'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (13, -3))
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(EditStructureTestCase)
|
68
pack/acp/start/vim-orgmode/tests/test_plugin_mappings.py
Normal file
68
pack/acp/start/vim-orgmode/tests/test_plugin_mappings.py
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import orgmode.settings
|
||||||
|
from orgmode.exceptions import PluginError
|
||||||
|
from orgmode._vim import ORGMODE
|
||||||
|
from orgmode.keybinding import MODE_ALL, Plug
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
ORG_PLUGINS = ['ShowHide', '|', 'Navigator', 'EditStructure', '|', 'Hyperlinks', '|', 'Todo', 'TagsProperties', 'Date', 'Agenda', 'Misc', '|', 'Export']
|
||||||
|
|
||||||
|
|
||||||
|
class MappingTestCase(unittest.TestCase):
|
||||||
|
u"""Tests all plugins for overlapping mappings."""
|
||||||
|
def test_non_overlapping_plug_mappings(self):
|
||||||
|
def find_overlapping_mappings(kb, all_keybindings):
|
||||||
|
found_overlapping_mapping = False
|
||||||
|
for tkb in all_keybindings:
|
||||||
|
if kb.mode == tkb.mode or MODE_ALL in (kb.mode, tkb.mode):
|
||||||
|
if isinstance(kb._action, Plug) and isinstance(tkb._action, Plug):
|
||||||
|
akb = kb.action
|
||||||
|
atkb = tkb.action
|
||||||
|
if (akb.startswith(atkb) or atkb.startswith(akb)) and akb != atkb:
|
||||||
|
print(u'\nERROR: Found overlapping mapping: %s (%s), %s (%s)' % (kb.key, akb, tkb.key, atkb))
|
||||||
|
found_overlapping_mapping = True
|
||||||
|
|
||||||
|
if all_keybindings:
|
||||||
|
res = find_overlapping_mappings(all_keybindings[0], all_keybindings[1:])
|
||||||
|
if not found_overlapping_mapping:
|
||||||
|
return res
|
||||||
|
return found_overlapping_mapping
|
||||||
|
|
||||||
|
if self.keybindings:
|
||||||
|
self.assertFalse(find_overlapping_mappings(self.keybindings[0], self.keybindings[1:]))
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.keybindings = []
|
||||||
|
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
u'exists("g:org_debug")': 0,
|
||||||
|
u'exists("b:org_debug")': 0,
|
||||||
|
u'exists("*repeat#set()")': 0,
|
||||||
|
u'b:changedtick': 0,
|
||||||
|
u_encode(u'exists("b:org_plugins")'): 0,
|
||||||
|
u_encode(u'exists("g:org_plugins")'): 1,
|
||||||
|
u_encode(u'g:org_plugins'): ORG_PLUGINS,
|
||||||
|
}
|
||||||
|
for plugin in filter(lambda p: p != '|', ORG_PLUGINS):
|
||||||
|
try:
|
||||||
|
ORGMODE.register_plugin(plugin)
|
||||||
|
except PluginError:
|
||||||
|
pass
|
||||||
|
if plugin in ORGMODE._plugins:
|
||||||
|
self.keybindings.extend(ORGMODE._plugins[plugin].keybindings)
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(MappingTestCase)
|
||||||
|
|
||||||
|
# vi: noexpandtab
|
164
pack/acp/start/vim-orgmode/tests/test_plugin_misc.py
Normal file
164
pack/acp/start/vim-orgmode/tests/test_plugin_misc.py
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import indent_orgmode, fold_orgmode, ORGMODE
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
ORGMODE.debug = True
|
||||||
|
|
||||||
|
START = True
|
||||||
|
END = False
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
class MiscTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
global counter
|
||||||
|
counter += 1
|
||||||
|
vim.CMDHISTORY = []
|
||||||
|
vim.CMDRESULTS = {}
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u"v:lnum"): u_encode(u'0')}
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
*** Überschrift 1.2.1
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n') ]
|
||||||
|
|
||||||
|
def test_indent_noheading(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (1, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'1')
|
||||||
|
indent_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 0)
|
||||||
|
|
||||||
|
def test_indent_heading(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'2')
|
||||||
|
indent_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 0)
|
||||||
|
|
||||||
|
def test_indent_heading_middle(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (3, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'3')
|
||||||
|
indent_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:indent_level = 2'))
|
||||||
|
|
||||||
|
def test_indent_heading_middle2(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (4, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'4')
|
||||||
|
indent_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:indent_level = 2'))
|
||||||
|
|
||||||
|
def test_indent_heading_end(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (5, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'5')
|
||||||
|
indent_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:indent_level = 2'))
|
||||||
|
|
||||||
|
def test_fold_heading_start(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'2')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">1"'))
|
||||||
|
|
||||||
|
def test_fold_heading_middle(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (3, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'3')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 1'))
|
||||||
|
|
||||||
|
def test_fold_heading_end(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (5, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'5')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 1'))
|
||||||
|
|
||||||
|
def test_fold_heading_end_of_last_child(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (16, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'16')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
# which is also end of the parent heading <1
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">3"'))
|
||||||
|
|
||||||
|
def test_fold_heading_end_of_last_child_next_heading(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (17, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'17')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">1"'))
|
||||||
|
|
||||||
|
def test_fold_middle_subheading(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'13')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">4"'))
|
||||||
|
|
||||||
|
def test_fold_middle_subheading2(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (14, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'14')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 4'))
|
||||||
|
|
||||||
|
def test_fold_middle_subheading3(self):
|
||||||
|
# test first heading
|
||||||
|
vim.current.window.cursor = (15, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'15')
|
||||||
|
fold_orgmode()
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 4'))
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(MiscTestCase)
|
633
pack/acp/start/vim-orgmode/tests/test_plugin_navigator.py
Normal file
633
pack/acp/start/vim-orgmode/tests/test_plugin_navigator.py
Normal file
|
@ -0,0 +1,633 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
START = True
|
||||||
|
END = False
|
||||||
|
|
||||||
|
def set_visual_selection(visualmode, line_start, line_end, col_start=1,
|
||||||
|
col_end=1, cursor_pos=START):
|
||||||
|
|
||||||
|
if visualmode not in (u'', u'V', u'v'):
|
||||||
|
raise ValueError(u'Illegal value for visualmode, must be in , V, v')
|
||||||
|
|
||||||
|
vim.EVALRESULTS['visualmode()'] = visualmode
|
||||||
|
|
||||||
|
# getpos results [bufnum, lnum, col, off]
|
||||||
|
vim.EVALRESULTS['getpos("\'<")'] = ('', '%d' % line_start, '%d' %
|
||||||
|
col_start, '')
|
||||||
|
vim.EVALRESULTS['getpos("\'>")'] = ('', '%d' % line_end, '%d' %
|
||||||
|
col_end, '')
|
||||||
|
if cursor_pos == START:
|
||||||
|
vim.current.window.cursor = (line_start, col_start)
|
||||||
|
else:
|
||||||
|
vim.current.window.cursor = (line_end, col_end)
|
||||||
|
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
class NavigatorTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
global counter
|
||||||
|
counter += 1
|
||||||
|
vim.CMDHISTORY = []
|
||||||
|
vim.CMDRESULTS = {}
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0'),
|
||||||
|
}
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
*** Überschrift 1.2.1
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n') ]
|
||||||
|
|
||||||
|
if not u'Navigator' in ORGMODE.plugins:
|
||||||
|
ORGMODE.register_plugin(u'Navigator')
|
||||||
|
self.navigator = ORGMODE.plugins[u'Navigator']
|
||||||
|
|
||||||
|
def test_movement(self):
|
||||||
|
# test movement outside any heading
|
||||||
|
vim.current.window.cursor = (1, 0)
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (1, 0))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
|
||||||
|
def test_forward_movement(self):
|
||||||
|
# test forward movement
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (6, 3))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 3))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (13, 5))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (16, 4))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (17, 2))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (18, 2))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (18, 2))
|
||||||
|
|
||||||
|
## don't move cursor if last heading is already focussed
|
||||||
|
vim.current.window.cursor = (19, 6)
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (19, 6))
|
||||||
|
|
||||||
|
## test movement with count
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'-1')
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (6, 3))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'0')
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (6, 3))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'1')
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (6, 3))
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'3')
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (16, 4))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (18, 2))
|
||||||
|
self.navigator.next(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (18, 2))
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'0')
|
||||||
|
|
||||||
|
def test_backward_movement(self):
|
||||||
|
# test backward movement
|
||||||
|
vim.current.window.cursor = (19, 6)
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (18, 2))
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (17, 2))
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (16, 4))
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (13, 5))
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 3))
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (6, 3))
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
|
||||||
|
## test movement with count
|
||||||
|
vim.current.window.cursor = (19, 6)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'-1')
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (18, 2))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (19, 6)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'0')
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (18, 2))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (19, 6)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'3')
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (16, 4))
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'4')
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'4')
|
||||||
|
self.navigator.previous(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
|
||||||
|
def test_parent_movement(self):
|
||||||
|
# test movement to parent
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.assertEqual(self.navigator.parent(mode=u'normal'), None)
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (3, 4)
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (3, 4))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (16, 4)
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 3))
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (15, 6)
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 3))
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
|
||||||
|
## test movement with count
|
||||||
|
vim.current.window.cursor = (16, 4)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'-1')
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 3))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (16, 4)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'0')
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 3))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (16, 4)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'1')
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 3))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (16, 4)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'2')
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
|
||||||
|
vim.current.window.cursor = (16, 4)
|
||||||
|
vim.EVALRESULTS[u_encode(u"v:count")] = u_encode(u'3')
|
||||||
|
self.navigator.parent(mode=u'normal')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 2))
|
||||||
|
|
||||||
|
def test_next_parent_movement(self):
|
||||||
|
# test movement to parent
|
||||||
|
vim.current.window.cursor = (6, 0)
|
||||||
|
self.assertNotEqual(self.navigator.parent_next_sibling(mode=u'normal'), None)
|
||||||
|
self.assertEqual(vim.current.window.cursor, (17, 2))
|
||||||
|
|
||||||
|
def test_forward_movement_visual(self):
|
||||||
|
# selection start: <<
|
||||||
|
# selection end: >>
|
||||||
|
# cursor poistion: |
|
||||||
|
|
||||||
|
# << text
|
||||||
|
# text| >>
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 2, 4, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV5gg'))
|
||||||
|
|
||||||
|
# << text
|
||||||
|
# text
|
||||||
|
# text| >>
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 2, 5, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV9gg'))
|
||||||
|
|
||||||
|
# << text
|
||||||
|
# x. heading
|
||||||
|
# text| >>
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 12, 14, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV15gg'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 12, 15, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV16gg'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 12, 16, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV17gg'))
|
||||||
|
|
||||||
|
# << text
|
||||||
|
# text
|
||||||
|
# text| >>
|
||||||
|
# heading
|
||||||
|
# EOF
|
||||||
|
set_visual_selection(u'V', 15, 17, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 15ggV20gg'))
|
||||||
|
|
||||||
|
# << text >>
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 1, 1, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 1ggV5gg'))
|
||||||
|
|
||||||
|
# << heading >>
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 2, 2, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV5gg'))
|
||||||
|
|
||||||
|
# << text >>
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 1, 1, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 1ggV5gg'))
|
||||||
|
|
||||||
|
# << |text
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 1, 8, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV8ggo'))
|
||||||
|
|
||||||
|
# << |heading
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 2, 8, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 6ggV8ggo'))
|
||||||
|
|
||||||
|
# << |heading
|
||||||
|
# text >>
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 6, 8, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 8ggV9gg'))
|
||||||
|
|
||||||
|
# << |x. heading
|
||||||
|
# text >>
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 13, 15, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 15ggV15gg'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 13, 16, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16ggV16ggo'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 16, 16, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16ggV17gg'))
|
||||||
|
|
||||||
|
# << |x. heading
|
||||||
|
# text >>
|
||||||
|
# heading
|
||||||
|
# EOF
|
||||||
|
set_visual_selection(u'V', 17, 17, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 17ggV20gg'))
|
||||||
|
|
||||||
|
# << |heading
|
||||||
|
# text>>
|
||||||
|
# text
|
||||||
|
# EOF
|
||||||
|
set_visual_selection(u'V', 18, 19, cursor_pos=START)
|
||||||
|
self.assertEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 19ggV20gg'))
|
||||||
|
|
||||||
|
# << heading
|
||||||
|
# text|>>
|
||||||
|
# text
|
||||||
|
# EOF
|
||||||
|
set_visual_selection(u'V', 18, 19, cursor_pos=END)
|
||||||
|
self.assertEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 18ggV20gg'))
|
||||||
|
|
||||||
|
# << heading
|
||||||
|
# text|>>
|
||||||
|
# EOF
|
||||||
|
set_visual_selection(u'V', 18, 20, cursor_pos=END)
|
||||||
|
self.assertEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 18ggV20gg'))
|
||||||
|
|
||||||
|
# << |heading
|
||||||
|
# text>>
|
||||||
|
# EOF
|
||||||
|
set_visual_selection(u'V', 20, 20, cursor_pos=START)
|
||||||
|
self.assertEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 20ggV20gg'))
|
||||||
|
|
||||||
|
def test_forward_movement_visual_to_the_end_of_the_file(self):
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
test
|
||||||
|
""".split(u'\n') ]
|
||||||
|
# << |heading
|
||||||
|
# text>>
|
||||||
|
# EOF
|
||||||
|
set_visual_selection(u'V', 15, 15, cursor_pos=START)
|
||||||
|
self.assertEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 15ggV17gg'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 15, 17, cursor_pos=END)
|
||||||
|
self.assertEqual(self.navigator.next(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 15ggV17gg'))
|
||||||
|
|
||||||
|
def test_backward_movement_visual(self):
|
||||||
|
# selection start: <<
|
||||||
|
# selection end: >>
|
||||||
|
# cursor poistion: |
|
||||||
|
|
||||||
|
# << text | >>
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 1, 1, cursor_pos=START)
|
||||||
|
self.assertEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! gv'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 1, 1, cursor_pos=END)
|
||||||
|
self.assertEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! gv'))
|
||||||
|
|
||||||
|
# << heading| >>
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
set_visual_selection(u'V', 2, 2, cursor_pos=START)
|
||||||
|
self.assertEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV2ggo'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 2, 2, cursor_pos=END)
|
||||||
|
self.assertEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV2ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# << |text
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 3, 5, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV5ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# << text
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 3, 5, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV3ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# << text
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 8, 9, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 6ggV8ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# x. heading
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 12, 14, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV12gg'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 12, 15, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV12gg'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << |text
|
||||||
|
# x. heading
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 12, 15, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 10ggV15ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# x. heading| >>
|
||||||
|
set_visual_selection(u'V', 12, 13, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV12gg'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# x. heading| >>
|
||||||
|
set_visual_selection(u'V', 12, 16, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV15gg'))
|
||||||
|
|
||||||
|
# << text
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# heading| >>
|
||||||
|
set_visual_selection(u'V', 15, 17, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 15ggV16gg'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << |text
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 4, 8, cursor_pos=START)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV8ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 4, 8, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 4ggV5gg'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 4, 5, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV4ggo'))
|
||||||
|
|
||||||
|
# BOF
|
||||||
|
# << |heading
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 2, 8, cursor_pos=START)
|
||||||
|
self.assertEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV8ggo'))
|
||||||
|
|
||||||
|
# BOF
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 3, 4, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV3ggo'))
|
||||||
|
|
||||||
|
# BOF
|
||||||
|
# << heading
|
||||||
|
# text
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 2, 4, cursor_pos=END)
|
||||||
|
self.assertNotEqual(self.navigator.previous(mode=u'visual'), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV2ggo'))
|
||||||
|
|
||||||
|
# << text
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# x. heading
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 8, 14, cursor_pos=END)
|
||||||
|
self.navigator.previous(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 8ggV12gg'))
|
||||||
|
|
||||||
|
def test_parent_movement_visual(self):
|
||||||
|
# selection start: <<
|
||||||
|
# selection end: >>
|
||||||
|
# cursor poistion: |
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text|
|
||||||
|
# text
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 4, 8, cursor_pos=START)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! gv'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text|
|
||||||
|
# text
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 6, 8, cursor_pos=START)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV8ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# text
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 6, 8, cursor_pos=END)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 6ggV5gg'))
|
||||||
|
|
||||||
|
# << |heading
|
||||||
|
# text
|
||||||
|
# text
|
||||||
|
# text >>
|
||||||
|
set_visual_selection(u'V', 2, 8, cursor_pos=START)
|
||||||
|
self.assertEqual(self.navigator.parent(mode=u'visual'), None)
|
||||||
|
|
||||||
|
# << heading
|
||||||
|
# text
|
||||||
|
# heading
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 2, 8, cursor_pos=END)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV5gg'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 7, 8, cursor_pos=START)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV8ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 12, 13, cursor_pos=END)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 12ggV12gg'))
|
||||||
|
|
||||||
|
set_visual_selection(u'V', 10, 12, cursor_pos=START)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggV12ggo'))
|
||||||
|
|
||||||
|
# heading
|
||||||
|
# << text
|
||||||
|
# text
|
||||||
|
# heading| >>
|
||||||
|
set_visual_selection(u'V', 11, 17, cursor_pos=END)
|
||||||
|
self.assertEqual(self.navigator.parent(mode=u'visual'), None)
|
||||||
|
|
||||||
|
# << text
|
||||||
|
# heading
|
||||||
|
# text
|
||||||
|
# x. heading
|
||||||
|
# text| >>
|
||||||
|
set_visual_selection(u'V', 8, 14, cursor_pos=END)
|
||||||
|
self.navigator.parent(mode=u'visual')
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 8ggV12gg'))
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(NavigatorTestCase)
|
385
pack/acp/start/vim-orgmode/tests/test_plugin_show_hide.py
Normal file
385
pack/acp/start/vim-orgmode/tests/test_plugin_show_hide.py
Normal file
|
@ -0,0 +1,385 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import ORGMODE
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
class ShowHideTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
global counter
|
||||||
|
counter += 1
|
||||||
|
vim.CMDHISTORY = []
|
||||||
|
vim.CMDRESULTS = {}
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0')}
|
||||||
|
if not u'ShowHide' in ORGMODE.plugins:
|
||||||
|
ORGMODE.register_plugin(u'ShowHide')
|
||||||
|
self.showhide = ORGMODE.plugins[u'ShowHide']
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
*** Überschrift 1.2.1
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n') ]
|
||||||
|
|
||||||
|
def test_no_heading_toggle_folding(self):
|
||||||
|
vim.current.window.cursor = (1, 0)
|
||||||
|
self.assertEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(vim.EVALHISTORY[-1], u_encode(u'feedkeys("<Tab>", "n")'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (1, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_first_heading_with_no_children(self):
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n') ]
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'2'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(7)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 1zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_close_one(self):
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 2)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'13,15foldclose!'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (13, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_one(self):
|
||||||
|
vim.current.window.cursor = (10, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'10'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 1zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_close_multiple_all_open(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'2,16foldclose!'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_all_closed(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'2'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 1zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_first_level_open(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'6'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'10'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 2)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'normal! 6gg1zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 10gg1zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_second_level_half_open(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'10'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 4)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-4], u_encode(u'normal! 6gg2zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-3], u_encode(u'normal! 10gg2zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'normal! 13gg2zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16gg2zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_other_second_level_half_open(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'6'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 4)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-4], u_encode(u'normal! 6gg2zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-3], u_encode(u'normal! 10gg2zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'normal! 13gg2zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16gg2zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_third_level_half_open(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 4)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-4], u_encode(u'normal! 6gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-3], u_encode(u'normal! 10gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'normal! 13gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16gg3zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_other_third_level_half_open(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 4)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-4], u_encode(u'normal! 6gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-3], u_encode(u'normal! 10gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'normal! 13gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16gg3zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_other_third_level_half_open_second_level_half_closed(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'6'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 4)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-4], u_encode(u'normal! 6gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-3], u_encode(u'normal! 10gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'normal! 13gg3zo'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16gg3zo'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_no_heading_toggle_folding_reverse(self):
|
||||||
|
vim.current.window.cursor = (1, 0)
|
||||||
|
self.assertEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(vim.EVALHISTORY[-1], u_encode(u'feedkeys("<Tab>", "n")'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (1, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_first_heading_with_no_children_reverse(self):
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n') ]
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'2'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(7)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'2,5foldopen!'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_close_one_reverse(self):
|
||||||
|
vim.current.window.cursor = (13, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 13ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (13, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_one_reverse(self):
|
||||||
|
vim.current.window.cursor = (10, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'10'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'10,16foldopen!'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (10, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_close_multiple_all_open_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 2)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-2], u_encode(u'normal! 13ggzc'))
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_all_closed_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'2'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'2,16foldopen!'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_first_level_open_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'6'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'10'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 2ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_second_level_half_open_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'10'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 6ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_other_second_level_half_open_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'6'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 10ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_third_level_half_open_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'16'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 13ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_other_third_level_half_open_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def test_toggle_folding_open_multiple_other_third_level_half_open_second_level_half_closed_reverse(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS.update({
|
||||||
|
u_encode(u'foldclosed(2)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(6)'): u_encode(u'6'),
|
||||||
|
u_encode(u'foldclosed(10)'): u_encode(u'-1'),
|
||||||
|
u_encode(u'foldclosed(13)'): u_encode(u'13'),
|
||||||
|
u_encode(u'foldclosed(16)'): u_encode(u'-1'),
|
||||||
|
})
|
||||||
|
self.assertNotEqual(self.showhide.toggle_folding(reverse=True), None)
|
||||||
|
self.assertEqual(len(vim.CMDHISTORY), 1)
|
||||||
|
self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'normal! 16ggzc'))
|
||||||
|
self.assertEqual(vim.current.window.cursor, (2, 0))
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(ShowHideTestCase)
|
177
pack/acp/start/vim-orgmode/tests/test_plugin_tags_properties.py
Normal file
177
pack/acp/start/vim-orgmode/tests/test_plugin_tags_properties.py
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode._vim import indent_orgmode, fold_orgmode, ORGMODE
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
ORGMODE.debug = True
|
||||||
|
|
||||||
|
START = True
|
||||||
|
END = False
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
class TagsPropertiesTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
global counter
|
||||||
|
counter += 1
|
||||||
|
vim.CMDHISTORY = []
|
||||||
|
vim.CMDRESULTS = {}
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'&ts'): u_encode(u'6'),
|
||||||
|
u_encode(u'exists("b:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("g:org_tag_column")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): (u_encode(u'%d' % counter)),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0')}
|
||||||
|
if not u'TagsProperties' in ORGMODE.plugins:
|
||||||
|
ORGMODE.register_plugin(u'TagsProperties')
|
||||||
|
self.tagsproperties = ORGMODE.plugins[u'TagsProperties']
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Überschrift 1
|
||||||
|
Text 1
|
||||||
|
|
||||||
|
Bla bla
|
||||||
|
** Überschrift 1.1
|
||||||
|
Text 2
|
||||||
|
|
||||||
|
Bla Bla bla
|
||||||
|
** Überschrift 1.2
|
||||||
|
Text 3
|
||||||
|
|
||||||
|
**** Überschrift 1.2.1.falsch
|
||||||
|
|
||||||
|
Bla Bla bla bla
|
||||||
|
*** Überschrift 1.2.1
|
||||||
|
* Überschrift 2
|
||||||
|
* Überschrift 3
|
||||||
|
asdf sdf
|
||||||
|
""".split(u'\n') ]
|
||||||
|
|
||||||
|
def test_new_property(self):
|
||||||
|
u""" TODO: Docstring for test_new_property
|
||||||
|
|
||||||
|
:returns: TODO
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_set_tags(self):
|
||||||
|
# set first tag
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
|
||||||
|
|
||||||
|
# set second tag
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", ":hello:", "customlist,Org_complete_tags")')] = u_encode(u':hello:world:')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
|
||||||
|
def test_parse_tags_no_colons_single_tag(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
|
||||||
|
|
||||||
|
def test_parse_tags_no_colons_multiple_tags(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello:world')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
|
||||||
|
def test_parse_tags_single_colon_left_single_tag(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
|
||||||
|
|
||||||
|
def test_parse_tags_single_colon_left_multiple_tags(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:world')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
|
||||||
|
def test_parse_tags_single_colon_right_single_tag(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello:')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
|
||||||
|
|
||||||
|
def test_parse_tags_single_colon_right_multiple_tags(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello:world:')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
|
||||||
|
def test_filter_empty_tags(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'::hello::')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
|
||||||
|
|
||||||
|
def test_delete_tags(self):
|
||||||
|
# set up
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:world:')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
|
||||||
|
# delete second of two tags
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", ":hello:world:", "customlist,Org_complete_tags")')] = u_encode(u':hello:')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
|
||||||
|
|
||||||
|
# delete last tag
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", ":hello:", "customlist,Org_complete_tags")')] = u_encode(u'')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
|
||||||
|
def test_realign_tags_noop(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.tagsproperties.realign_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
|
||||||
|
def test_realign_tags_remove_spaces(self):
|
||||||
|
# remove spaces in multiple locations
|
||||||
|
vim.current.buffer[1] = u_encode(u'* Überschrift 1 ')
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.tagsproperties.realign_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
|
||||||
|
# remove tabs and spaces in multiple locations
|
||||||
|
vim.current.buffer[1] = u_encode(u'*\t \tÜberschrift 1 \t')
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
self.tagsproperties.realign_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
|
||||||
|
|
||||||
|
def test_realign_tags(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:world:')
|
||||||
|
self.tagsproperties.set_tags()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
|
||||||
|
d = ORGMODE.get_document()
|
||||||
|
heading = d.find_current_heading()
|
||||||
|
self.assertEqual(str(heading), u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
self.tagsproperties.realign_tags()
|
||||||
|
heading = d.find_current_heading()
|
||||||
|
self.assertEqual(str(heading), u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(TagsPropertiesTestCase)
|
424
pack/acp/start/vim-orgmode/tests/test_plugin_todo.py
Normal file
424
pack/acp/start/vim-orgmode/tests/test_plugin_todo.py
Normal file
|
@ -0,0 +1,424 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
sys.path.append(u'../ftplugin')
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from orgmode.liborgmode.base import Direction
|
||||||
|
from orgmode.vimbuffer import VimBuffer
|
||||||
|
from orgmode.plugins.Todo import Todo
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
from orgmode.py3compat.encode_compatibility import *
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
|
||||||
|
class TodoTestCase(unittest.TestCase):
|
||||||
|
u"""Tests all the functionality of the TODO module."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# set content of the buffer
|
||||||
|
global counter
|
||||||
|
counter += 1
|
||||||
|
vim.EVALHISTORY = []
|
||||||
|
vim.EVALRESULTS = {
|
||||||
|
# no org_todo_keywords for b
|
||||||
|
u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
|
||||||
|
# global values for org_todo_keywords
|
||||||
|
u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
|
||||||
|
u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
|
||||||
|
u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
|
||||||
|
u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
|
||||||
|
u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
|
||||||
|
u_encode(u"v:count"): u_encode(u'0')
|
||||||
|
}
|
||||||
|
|
||||||
|
vim.current.buffer[:] = [ u_encode(i) for i in u"""
|
||||||
|
* Heading 1
|
||||||
|
** Text 1
|
||||||
|
*** Text 2
|
||||||
|
* Text 1
|
||||||
|
** Text 1
|
||||||
|
some text that is
|
||||||
|
no heading
|
||||||
|
|
||||||
|
""".split(u'\n') ]
|
||||||
|
|
||||||
|
# toggle
|
||||||
|
def test_toggle_todo_with_no_heading(self):
|
||||||
|
# nothing should happen
|
||||||
|
vim.current.window.cursor = (1, 0)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[0], u'')
|
||||||
|
# and repeat it -> it should not change
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[0], u'')
|
||||||
|
|
||||||
|
def test_todo_toggle_NOTODO(self):
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
vim.current.buffer[1] = u_encode(u'** NOTODO Überschrift 1.1')
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u_encode(u'** TODO NOTODO Überschrift 1.1'))
|
||||||
|
|
||||||
|
def test_toggle_todo_in_heading_with_no_todo_state_different_levels(self):
|
||||||
|
# level 1
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* TODO Heading 1')
|
||||||
|
self.assertEqual((2, 0), vim.current.window.cursor)
|
||||||
|
|
||||||
|
# level 2
|
||||||
|
vim.current.window.cursor = (3, 0)
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[2], u'** TODO Text 1')
|
||||||
|
|
||||||
|
# level 2
|
||||||
|
vim.current.window.cursor = (4, 4)
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[3], u'*** TODO Text 2')
|
||||||
|
self.assertEqual((4, 9), vim.current.window.cursor)
|
||||||
|
|
||||||
|
def test_circle_through_todo_states(self):
|
||||||
|
# * Heading 1 -->
|
||||||
|
# * TODO Heading 1 -->
|
||||||
|
# * DONE Heading 1 -->
|
||||||
|
# * Heading 1 -->
|
||||||
|
# * TODO Heading 1 -->
|
||||||
|
# * DONE Heading 1
|
||||||
|
vim.current.window.cursor = (2, 6)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* TODO Heading 1')
|
||||||
|
self.assertEqual((2, 11), vim.current.window.cursor)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* DONE Heading 1')
|
||||||
|
self.assertEqual((2, 11), vim.current.window.cursor)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* Heading 1')
|
||||||
|
self.assertEqual((2, 6), vim.current.window.cursor)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* TODO Heading 1')
|
||||||
|
self.assertEqual((2, 11), vim.current.window.cursor)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* DONE Heading 1')
|
||||||
|
self.assertEqual((2, 11), vim.current.window.cursor)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* Heading 1')
|
||||||
|
self.assertEqual((2, 6), vim.current.window.cursor)
|
||||||
|
|
||||||
|
def test_circle_through_todo_states_with_more_states(self):
|
||||||
|
# * Heading 1 -->
|
||||||
|
# * TODO Heading 1 -->
|
||||||
|
# * STARTED Heading 1 -->
|
||||||
|
# * DONE Heading 1 -->
|
||||||
|
# * Heading 1 -->
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'STARTED'), u_encode(u'DONE'),
|
||||||
|
u_encode(u'|')]
|
||||||
|
vim.current.window.cursor = (2, 0)
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* TODO Heading 1')
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* STARTED Heading 1')
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* DONE Heading 1')
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[1], u'* Heading 1')
|
||||||
|
|
||||||
|
def test_toggle_todo_with_cursor_in_text_not_heading(self):
|
||||||
|
# nothing should happen
|
||||||
|
vim.current.window.cursor = (7, 0)
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[5], u'** TODO Text 1')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (7, 0))
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[5], u'** DONE Text 1')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (7, 0))
|
||||||
|
|
||||||
|
Todo.toggle_todo_state()
|
||||||
|
self.assertEqual(vim.current.buffer[5], u'** Text 1')
|
||||||
|
self.assertEqual(vim.current.window.cursor, (7, 0))
|
||||||
|
|
||||||
|
# get_states
|
||||||
|
def test_get_states_without_seperator(self):
|
||||||
|
u"""The last element in the todostates shouold be used as DONE-state when no sperator is given"""
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo, expected_done = [u'TODO'], [u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'INPROGRESS'), u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo = [u'TODO', u'INPROGRESS']
|
||||||
|
expected_done = [u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'INPROGRESS'),
|
||||||
|
u_encode(u'DUMMY'), u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo = [u'TODO', u'INPROGRESS', u'DUMMY']
|
||||||
|
expected_done = [u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
def test_get_states_with_seperator(self):
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo = [u'TODO']
|
||||||
|
expected_done = [u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'INPROGRESS'), u_encode(u'|'),
|
||||||
|
u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo = [u'TODO', u'INPROGRESS']
|
||||||
|
expected_done = [u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'INPROGRESS'),
|
||||||
|
u_encode(u'DUMMY'), u_encode(u'|'), u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo = [u'TODO', u'INPROGRESS', u'DUMMY']
|
||||||
|
expected_done = [u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'INPROGRESS'),
|
||||||
|
u_encode(u'DUMMY'), u_encode(u'|'), u_encode(u'DELEGATED'), u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo =[u'TODO', u'INPROGRESS', u'DUMMY']
|
||||||
|
expected_done = [u'DELEGATED', u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONEX'),
|
||||||
|
u_encode(u'DUMMY'), u_encode(u'DELEGATED'), u_encode(u'DONE')]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo = [u'TODO']
|
||||||
|
expected_done = [u'DONEX', u'DUMMY', u'DELEGATED', u'DONE']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = [[u_encode(u'TODO(t)'), u_encode(u'|'), u_encode(u'DONEX')],
|
||||||
|
[u_encode(u'DUMMY'), u_encode(u'DELEGATED'), u_encode(u'DONE')]]
|
||||||
|
states_todo, states_done = VimBuffer().get_todo_states()[0]
|
||||||
|
expected_todo = [u'TODO']
|
||||||
|
expected_done = [u'DONEX']
|
||||||
|
self.assertEqual(states_todo, expected_todo)
|
||||||
|
self.assertEqual(states_done, expected_done)
|
||||||
|
|
||||||
|
# get_next_state
|
||||||
|
def test_get_next_state_with_no_current_state(self):
|
||||||
|
states = [((u'TODO', ), (u'DONE', ))]
|
||||||
|
current_state = u''
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'TODO')
|
||||||
|
|
||||||
|
states = [((u'TODO', u'NEXT'), (u'DELEGATED', u'DONE'))]
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'TODO')
|
||||||
|
|
||||||
|
states = [((u'NEXT', ), (u'DELEGATED', u'DONE'))]
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'NEXT')
|
||||||
|
|
||||||
|
def test_get_next_state_backward_with_no_current_state(self):
|
||||||
|
states = [((u'TODO', ), (u'DONE', ))]
|
||||||
|
current_state = u''
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD), u'DONE')
|
||||||
|
|
||||||
|
states = [((u'TODO', u'NEXT'), (u'DELEGATED', u'DONE'))]
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD), u'DONE')
|
||||||
|
|
||||||
|
states = [((u'NEXT', ), (u'DELEGATED', u'DONE'))]
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD), u'DONE')
|
||||||
|
|
||||||
|
def test_get_next_state_with_invalid_current_state(self):
|
||||||
|
states = [((u'TODO', ), (u'DONE', ))]
|
||||||
|
current_state = u'STI'
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'TODO')
|
||||||
|
|
||||||
|
states = [((u'TODO', u'NEXT'), (u'DELEGATED', u'DONE'))]
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'TODO')
|
||||||
|
|
||||||
|
states = [((u'NEXT', ), (u'DELEGATED', u'DONE'))]
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'NEXT')
|
||||||
|
|
||||||
|
def test_get_next_state_backward_with_invalid_current_state(self):
|
||||||
|
states = [((u'TODO', ), (u'DONE', ))]
|
||||||
|
current_state = u'STI'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'DONE')
|
||||||
|
|
||||||
|
states = [((u'TODO', u'NEXT'), (u'DELEGATED', u'DONE'))]
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'DONE')
|
||||||
|
|
||||||
|
states = [((u'NEXT', ), (u'DELEGATED', u'DONE'))]
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'DONE')
|
||||||
|
|
||||||
|
def test_get_next_state_with_current_state_equals_todo_state(self):
|
||||||
|
states = [((u'TODO', u'NEXT', u'NOW'), (u'DELEGATED', u'DONE'))]
|
||||||
|
current_state = u'TODO'
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'NEXT')
|
||||||
|
|
||||||
|
current_state = u'NEXT'
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'NOW')
|
||||||
|
|
||||||
|
def test_get_next_state_backward_with_current_state_equals_todo_state(self):
|
||||||
|
states = [((u'TODO', u'NEXT', u'NOW'), (u'DELEGATED', u'DONE'))]
|
||||||
|
current_state = u'TODO'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, None)
|
||||||
|
|
||||||
|
def test_get_next_state_backward_misc(self):
|
||||||
|
states = [((u'TODO', u'NEXT', u'NOW'), (u'DELEGATED', u'DONE'))]
|
||||||
|
current_state = u'DONE'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'DELEGATED')
|
||||||
|
|
||||||
|
current_state = u'DELEGATED'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'NOW')
|
||||||
|
|
||||||
|
current_state = u'NOW'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'NEXT')
|
||||||
|
|
||||||
|
current_state = u'NEXT'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'TODO')
|
||||||
|
|
||||||
|
current_state = u'TODO'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, None)
|
||||||
|
|
||||||
|
current_state = None
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'DONE')
|
||||||
|
|
||||||
|
def test_get_next_state_with_jump_from_todo_to_done(self):
|
||||||
|
states = [((u'TODO', u'NEXT', u'NOW'), (u'DELEGATED', u'DONE'))]
|
||||||
|
current_state = u'NOW'
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), u'DELEGATED')
|
||||||
|
|
||||||
|
def test_get_next_state_with_jump_from_done_to_todo(self):
|
||||||
|
states = [((u'TODO', u'NEXT', u'NOW'), (u'DELEGATED', u'DONE'))]
|
||||||
|
current_state = u'DONE'
|
||||||
|
self.assertEquals(Todo._get_next_state(current_state, states), None)
|
||||||
|
|
||||||
|
def test_get_next_state_in_current_sequence(self):
|
||||||
|
states = [((u'TODO', u'NEXT', u'NOW'), (u'DELEGATED', u'DONE')), ((u'QA', ), (u'RELEASED', ))]
|
||||||
|
current_state = u'QA'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD)
|
||||||
|
self.assertEquals(result, u'RELEASED')
|
||||||
|
|
||||||
|
def test_get_next_state_in_current_sequence_with_access_keys(self):
|
||||||
|
states = [((u'TODO(t)', u'NEXT(n)', u'NOW(w)'), (u'DELEGATED(g)', u'DONE(d)')), ((u'QA(q)', ), (u'RELEASED(r)', ))]
|
||||||
|
current_state = u'QA'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD)
|
||||||
|
self.assertEquals(result, u'RELEASED')
|
||||||
|
|
||||||
|
current_state = u'NEXT'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD)
|
||||||
|
self.assertEquals(result, u'NOW')
|
||||||
|
|
||||||
|
current_state = u'TODO'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, None)
|
||||||
|
|
||||||
|
current_state = None
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD)
|
||||||
|
self.assertEquals(result, u'RELEASED')
|
||||||
|
|
||||||
|
def test_get_next_keyword_sequence(self):
|
||||||
|
states = [((u'TODO(t)', u'NEXT(n)', u'NOW(w)'), (u'DELEGATED(g)', u'DONE(d)')), ((u'QA(q)', ), (u'RELEASED(r)', ))]
|
||||||
|
current_state = None
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD, next_set=True)
|
||||||
|
self.assertEquals(result, u'TODO')
|
||||||
|
|
||||||
|
current_state = None
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD, next_set=True)
|
||||||
|
self.assertEquals(result, u'QA')
|
||||||
|
|
||||||
|
current_state = u'TODO'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD, next_set=True)
|
||||||
|
self.assertEquals(result, None)
|
||||||
|
|
||||||
|
current_state = u'TODO'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD, next_set=True)
|
||||||
|
self.assertEquals(result, u'QA')
|
||||||
|
|
||||||
|
current_state = u'NOW'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD, next_set=True)
|
||||||
|
self.assertEquals(result, u'QA')
|
||||||
|
|
||||||
|
current_state = u'DELEGATED'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD, next_set=True)
|
||||||
|
self.assertEquals(result, u'QA')
|
||||||
|
|
||||||
|
current_state = u'QA'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD, next_set=True)
|
||||||
|
self.assertEquals(result, u'TODO')
|
||||||
|
|
||||||
|
current_state = u'QA'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD, next_set=True)
|
||||||
|
self.assertEquals(result, None)
|
||||||
|
|
||||||
|
current_state = u'RELEASED'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.FORWARD, next_set=True)
|
||||||
|
self.assertEquals(result, None)
|
||||||
|
|
||||||
|
current_state = u'RELEASED'
|
||||||
|
result = Todo._get_next_state(current_state, states,
|
||||||
|
Direction.BACKWARD, next_set=True)
|
||||||
|
self.assertEquals(result, u'TODO')
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
return unittest.TestLoader().loadTestsFromTestCase(TodoTestCase)
|
||||||
|
|
||||||
|
# vi: noexpandtab
|
1257
pack/acp/start/vim-orgmode/tests/test_vimbuffer.py
Normal file
1257
pack/acp/start/vim-orgmode/tests/test_vimbuffer.py
Normal file
File diff suppressed because it is too large
Load diff
88
pack/acp/start/vim-orgmode/tests/vim.py
Normal file
88
pack/acp/start/vim-orgmode/tests/vim.py
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
class VimWindow(object):
|
||||||
|
u""" Docstring for VimWindow """
|
||||||
|
|
||||||
|
def __init__(self, test):
|
||||||
|
object.__init__(self)
|
||||||
|
self._test = test
|
||||||
|
self.cursor = (1, 0)
|
||||||
|
|
||||||
|
def buffer():
|
||||||
|
def fget(self):
|
||||||
|
return self._test.buffer
|
||||||
|
|
||||||
|
def fset(self, value):
|
||||||
|
self._test.buffer = value
|
||||||
|
return locals()
|
||||||
|
buffer = property(**buffer())
|
||||||
|
|
||||||
|
|
||||||
|
class VimBuffer(list):
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
self.number = 0
|
||||||
|
if iterable is not None:
|
||||||
|
list.__init__(self, iterable)
|
||||||
|
else:
|
||||||
|
list.__init__(self)
|
||||||
|
|
||||||
|
def append(self, o):
|
||||||
|
u"""
|
||||||
|
mimic the specific behavior of vim.current.buffer
|
||||||
|
"""
|
||||||
|
if isinstance(o, list) or isinstance(o, tuple):
|
||||||
|
for i in o:
|
||||||
|
list.append(self, i)
|
||||||
|
else:
|
||||||
|
list.append(self, o)
|
||||||
|
|
||||||
|
|
||||||
|
class VimTest(object):
|
||||||
|
u""" Replacement for vim API """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
object.__init__(self)
|
||||||
|
self._buffer = VimBuffer()
|
||||||
|
self.window = VimWindow(self)
|
||||||
|
|
||||||
|
def buffer():
|
||||||
|
def fget(self):
|
||||||
|
return self._buffer
|
||||||
|
|
||||||
|
def fset(self, value):
|
||||||
|
self._buffer = VimBuffer(value)
|
||||||
|
return locals()
|
||||||
|
buffer = property(**buffer())
|
||||||
|
|
||||||
|
|
||||||
|
EVALHISTORY = []
|
||||||
|
EVALRESULTS = {
|
||||||
|
u'exists("g:org_debug")': 0,
|
||||||
|
u'exists("b:org_debug")': 0,
|
||||||
|
u'exists("*repeat#set()")': 0,
|
||||||
|
u'exists("b:org_plugins")': 0,
|
||||||
|
u'exists("g:org_plugins")': 0,
|
||||||
|
u'b:changedtick': 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def eval(cmd):
|
||||||
|
u""" evaluate command
|
||||||
|
|
||||||
|
:returns: results stored in EVALRESULTS
|
||||||
|
"""
|
||||||
|
EVALHISTORY.append(cmd)
|
||||||
|
return EVALRESULTS.get(cmd, None)
|
||||||
|
|
||||||
|
|
||||||
|
CMDHISTORY = []
|
||||||
|
CMDRESULTS = {}
|
||||||
|
|
||||||
|
|
||||||
|
def command(cmd):
|
||||||
|
CMDHISTORY.append(cmd)
|
||||||
|
return CMDRESULTS.get(cmd, None)
|
||||||
|
|
||||||
|
|
||||||
|
current = VimTest()
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue