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/rust.vim](https://github.com/rust-lang/rust.vim)
|
||||
* [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-speeddating](https://github.com/tpope/vim-speeddating)
|
||||
* [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