├── .gitignore
├── .pylintrc
├── .travis.yml
├── CHANGELOG.org
├── LICENSE
├── Makefile
├── README.org
├── doc
└── orgguide.txt
├── examples
├── mylife.gif
├── mylife.org
├── mylife.png
└── plugins
│ └── PluginExample.py
├── ftdetect
└── org.vim
├── ftplugin
├── org.cnf
├── org.vim
└── orgmode
│ ├── __init__.py
│ ├── _vim.py
│ ├── docs
│ ├── Makefile
│ ├── conf.py
│ ├── index.rst
│ ├── make.bat
│ ├── orgmode.liborgmode.rst
│ ├── orgmode.plugins.rst
│ ├── orgmode.py3compat.rst
│ └── orgmode.rst
│ ├── exceptions.py
│ ├── keybinding.py
│ ├── liborgmode
│ ├── __init__.py
│ ├── agenda.py
│ ├── agendafilter.py
│ ├── base.py
│ ├── checkboxes.py
│ ├── documents.py
│ ├── dom_obj.py
│ ├── headings.py
│ └── orgdate.py
│ ├── menu.py
│ ├── plugins
│ ├── Agenda.py
│ ├── Date.py
│ ├── EditCheckbox.py
│ ├── EditStructure.py
│ ├── Export.py
│ ├── Hyperlinks.py
│ ├── LoggingWork.py
│ ├── Misc.py
│ ├── Navigator.py
│ ├── ShowHide.py
│ ├── TagsProperties.py
│ ├── Todo.py
│ └── __init__.py
│ ├── py3compat
│ ├── __init__.py
│ ├── encode_compatibility.py
│ ├── py_py3_string.py
│ ├── unicode_compatibility.py
│ └── xrange_compatibility.py
│ ├── settings.py
│ └── vimbuffer.py
├── indent
└── org.vim
├── syntax
├── org.vim
├── orgagenda.vim
└── orgtodo.vim
└── tests
├── orgmode_testfile.org
├── run_tests.py
├── test_libagendafilter.py
├── test_libbase.py
├── test_libcheckbox.py
├── test_libheading.py
├── test_liborgdate.py
├── test_liborgdate_parsing.py
├── test_liborgdate_utf8.py
├── test_liborgdatetime.py
├── test_liborgtimerange.py
├── test_plugin_date.py
├── test_plugin_edit_checkbox.py
├── test_plugin_edit_structure.py
├── test_plugin_mappings.py
├── test_plugin_misc.py
├── test_plugin_navigator.py
├── test_plugin_show_hide.py
├── test_plugin_tags_properties.py
├── test_plugin_todo.py
├── test_vimbuffer.py
└── vim.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.swp
3 | tags
4 | .ropeproject
5 | .cover*
6 | cover*
7 |
--------------------------------------------------------------------------------
/.pylintrc:
--------------------------------------------------------------------------------
1 | [MASTER]
2 |
3 | # Specify a configuration file.
4 | #rcfile=
5 |
6 | # Python code to execute, usually for sys.path manipulation such as
7 | # pygtk.require().
8 | init-hook=sys.path.append(os.path.abspath('ftplugin'))
9 |
10 | # Profiled execution.
11 | profile=no
12 |
13 | # Add files or directories to the blacklist. They should be base names, not
14 | # paths.
15 | ignore=.git
16 |
17 | # Pickle collected data for later comparisons.
18 | persistent=yes
19 |
20 | # List of plugins (as comma separated values of python modules names) to load,
21 | # usually to register additional checkers.
22 | load-plugins=
23 |
24 |
25 | [MESSAGES CONTROL]
26 |
27 | # Enable the message, report, category or checker with the given id(s). You can
28 | # either give multiple identifier separated by comma (,) or put this option
29 | # multiple time.
30 | #enable=
31 |
32 | # Disable the message, report, category or checker with the given id(s). You
33 | # can either give multiple identifier separated by comma (,) or put this option
34 | # multiple time (only on the command line, not in the configuration file where
35 | # it should appear only once).
36 | #disable=
37 |
38 | [REPORTS]
39 |
40 | # Set the output format. Available formats are text, parseable, colorized, msvs
41 | # (visual studio) and html
42 | output-format=parseable
43 |
44 | # Include message's id in output
45 | include-ids=no
46 |
47 | # Put messages in a separate file for each module / package specified on the
48 | # command line instead of printing them on stdout. Reports (if any) will be
49 | # written in a file name "pylint_global.[txt|html]".
50 | files-output=no
51 |
52 | # Tells whether to display a full report or only the messages
53 | reports=yes
54 |
55 | # Python expression which should return a note less than 10 (10 is the highest
56 | # note). You have access to the variables errors warning, statement which
57 | # respectively contain the number of errors / warnings messages and the total
58 | # number of statements analyzed. This is used by the global evaluation report
59 | # (RP0004).
60 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
61 |
62 | # Add a comment according to your evaluation note. This is used by the global
63 | # evaluation report (RP0004).
64 | comment=no
65 |
66 |
67 | [TYPECHECK]
68 |
69 | # Tells whether missing members accessed in mixin class should be ignored. A
70 | # mixin class is detected if its name ends with "mixin" (case insensitive).
71 | ignore-mixin-members=yes
72 |
73 | # List of classes names for which member attributes should not be checked
74 | # (useful for classes with attributes dynamically set).
75 | ignored-classes=SQLObject
76 |
77 | # When zope mode is activated, add a predefined set of Zope acquired attributes
78 | # to generated-members.
79 | zope=no
80 |
81 | # List of members which are set dynamically and missed by pylint inference
82 | # system, and so shouldn't trigger E0201 when accessed. Python regular
83 | # expressions are accepted.
84 | generated-members=REQUEST,acl_users,aq_parent
85 |
86 |
87 | [BASIC]
88 |
89 | # Required attributes for module, separated by a comma
90 | required-attributes=
91 |
92 | # List of builtins function names that should not be used, separated by a comma
93 | bad-functions=map,filter,apply,input
94 |
95 | # Regular expression which should only match correct module names
96 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
97 |
98 | # Regular expression which should only match correct module level names
99 | const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
100 |
101 | # Regular expression which should only match correct class names
102 | class-rgx=[A-Z_][a-zA-Z0-9]+$
103 |
104 | # Regular expression which should only match correct function names
105 | function-rgx=[a-z_][a-z0-9_]{2,30}$
106 |
107 | # Regular expression which should only match correct method names
108 | method-rgx=[a-z_][a-z0-9_]{2,30}$
109 |
110 | # Regular expression which should only match correct instance attribute names
111 | attr-rgx=[a-z_][a-z0-9_]{2,30}$
112 |
113 | # Regular expression which should only match correct argument names
114 | argument-rgx=[a-z_][a-z0-9_]{2,30}$
115 |
116 | # Regular expression which should only match correct variable names
117 | variable-rgx=[a-z_][a-z0-9_]{2,30}$
118 |
119 | # Regular expression which should only match correct list comprehension /
120 | # generator expression variable names
121 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
122 |
123 | # Good variable names which should always be accepted, separated by a comma
124 | good-names=i,j,k,ex,Run,_
125 |
126 | # Bad variable names which should always be refused, separated by a comma
127 | bad-names=foo,bar,baz,toto,tutu,tata
128 |
129 | # Regular expression which should only match functions or classes name which do
130 | # not require a docstring
131 | no-docstring-rgx=__.*__
132 |
133 |
134 | [MISCELLANEOUS]
135 |
136 | # List of note tags to take in consideration, separated by a comma.
137 | notes=FIXME,XXX,TODO
138 |
139 |
140 | [VARIABLES]
141 |
142 | # Tells whether we should check for unused import in __init__ files.
143 | init-import=no
144 |
145 | # A regular expression matching the beginning of the name of dummy variables
146 | # (i.e. not used).
147 | dummy-variables-rgx=_|dummy
148 |
149 | # List of additional names supposed to be defined in builtins. Remember that
150 | # you should avoid to define new builtins when possible.
151 | additional-builtins=
152 |
153 |
154 | [SIMILARITIES]
155 |
156 | # Minimum lines number of a similarity.
157 | min-similarity-lines=4
158 |
159 | # Ignore comments when computing similarities.
160 | ignore-comments=yes
161 |
162 | # Ignore docstrings when computing similarities.
163 | ignore-docstrings=yes
164 |
165 |
166 | [FORMAT]
167 |
168 | # Maximum number of characters on a single line.
169 | max-line-length=800
170 |
171 | # Maximum number of lines in a module
172 | max-module-lines=1000
173 |
174 |
175 | [CLASSES]
176 |
177 | # List of interface methods to ignore, separated by a comma. This is used for
178 | # instance to not check methods defines in Zope's Interface base class.
179 | ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
180 |
181 | # List of method names used to declare (i.e. assign) instance attributes.
182 | defining-attr-methods=__init__,__new__,setUp
183 |
184 |
185 | [IMPORTS]
186 |
187 | # Deprecated modules which should not be used, separated by a comma
188 | deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
189 |
190 | # Create a graph of every (i.e. internal and external) dependencies in the
191 | # given file (report RP0402 must not be disabled)
192 | import-graph=
193 |
194 | # Create a graph of external dependencies in the given file (report RP0402 must
195 | # not be disabled)
196 | ext-import-graph=
197 |
198 | # Create a graph of internal dependencies in the given file (report RP0402 must
199 | # not be disabled)
200 | int-import-graph=
201 |
202 |
203 | [DESIGN]
204 |
205 | # Maximum number of arguments for function / method
206 | max-args=5
207 |
208 | # Argument names that match this expression will be ignored. Default to name
209 | # with leading underscore
210 | ignored-argument-names=_.*
211 |
212 | # Maximum number of locals for function / method body
213 | max-locals=15
214 |
215 | # Maximum number of return / yield for function / method body
216 | max-returns=6
217 |
218 | # Maximum number of branch for function / method body
219 | max-branchs=12
220 |
221 | # Maximum number of statements in function / method body
222 | max-statements=50
223 |
224 | # Maximum number of parents for a class (see R0901).
225 | max-parents=7
226 |
227 | # Maximum number of attributes for a class (see R0902).
228 | max-attributes=7
229 |
230 | # Minimum number of public methods for a class (see R0903).
231 | min-public-methods=2
232 |
233 | # Maximum number of public methods for a class (see R0904).
234 | max-public-methods=20
235 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 |
3 | before_install:
4 | - sudo apt-get update && sudo apt-get --reinstall install -qq language-pack-pt
5 |
6 | python:
7 | - "2.7"
8 | - "3.4"
9 | - "3.5"
10 | - "3.6"
11 | - "3.7"
12 | - "3.8"
13 | - "3.9"
14 | - "3.10"
15 | - "3.11"
16 | - "3.12"
17 |
18 | install:
19 | - pip install coverage
20 | - pip install codecov
21 |
22 | script:
23 | - cd tests
24 | - nosetests --with-coverage .
25 |
26 | after_success:
27 | - codecov
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ---------------------------------------------------------------------
2 | All source code is licensed under the terms of the following license:
3 | ---------------------------------------------------------------------
4 |
5 | Copyright (C) 2010,2011 Jan Christoph Ebersbach
6 |
7 | http://www.e-jc.de/
8 |
9 | All rights reserved.
10 |
11 | The source code of this program is made available under the terms of the
12 | GNU Affero General Public License version 3 (GNU AGPL V3) as published
13 | by the Free Software Foundation.
14 |
15 | Binary versions of this program provided by Univention to you as well as
16 | other copyrighted, protected or trademarked materials like Logos,
17 | graphics, fonts, specific documentations and configurations,
18 | cryptographic keys etc. are subject to a license agreement between you
19 | and Univention and not subject to the GNU AGPL V3.
20 |
21 | In the case you use this program under the terms of the GNU AGPL V3, the
22 | program is provided in the hope that it will be useful, but WITHOUT ANY
23 | WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
25 | License for more details.
26 |
27 | You should have received a copy of the GNU Affero General Public License
28 | with the Debian GNU/Linux or Univention distribution in file
29 | /usr/share/common-licenses/AGPL-3; if not, see
30 | .
31 |
32 |
33 | --------------------------------------------------------------------
34 | All documentation found in the directories doc and documentation are
35 | licensed under the terms of the following license:
36 | --------------------------------------------------------------------
37 |
38 | doc/org.txt
39 | Copyright (C) 2010,2011 Jan Christoph Ebersbach
40 |
41 | doc/orgguide.txt
42 | documentation/emacs_orgguide.org
43 | documentation/emacs_orgguide.texi
44 | Copyright (C) 2010 Free Software Foundation
45 |
46 | Permission is granted to copy, distribute and/or modify this document
47 | under the terms of the GNU Free Documentation License, Version 1.3 or
48 | any later version published by the Free Software Foundation; with no
49 | Invariant Sections, with the Front-Cover texts being “A GNU Manual,” and
50 | with the Back-Cover Texts as in (a) below. A copy of the license is
51 | included in the section entitled “GNU Free Documentation License.”
52 |
53 | (a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
54 | modify this GNU manual. Buying copies from the FSF supports it in
55 | developing GNU and promoting software freedom.”
56 |
57 | This document is part of a collection distributed under the GNU Free
58 | Documentation License. If you want to distribute this document
59 | separately from the collection, you can do so by adding a copy of the
60 | license to the document, as described in section 6 of the license.
61 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PLUGIN = orgmode
2 | PREFIX = /usr/local
3 | VIMDIR = $(PREFIX)/share/vim
4 |
5 | all: build
6 |
7 | build:
8 |
9 | # install plugin at destination
10 | install: doc indent ftdetect ftplugin syntax
11 | for i in doc indent ftdetect ftplugin syntax; do \
12 | 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 \
13 | install -m 0755 -d $(DESTDIR)$(VIMDIR)/$$(dirname "$$f"); \
14 | install -m 0644 $$f $(DESTDIR)$(VIMDIR)/$$f; \
15 | done; \
16 | done
17 |
18 | # cleanup
19 | clean: documentation
20 | @find . -name \*.pyc -o -name \*.py,cover -exec rm {} \;
21 | @rm -rf ${PLUGIN}.vmb ${PLUGIN}.vmb.gz tmp files
22 | cd $< && $(MAKE) $@
23 |
24 | # generate the vim ball package
25 | ${PLUGIN}.vmb: check build_vmb.vim clean
26 | $(MAKE) DESTDIR=$(PWD)/tmp VIMDIR= install
27 | find tmp -type f | sed -e 's/^tmp\///' > files
28 | cp build_vmb.vim tmp
29 | cd tmp && vim --cmd 'let g:plugin_name="${PLUGIN}"' -s build_vmb.vim
30 | [ -e tmp/${PLUGIN}.vba ] && mv tmp/${PLUGIN}.vba tmp/$@ || true
31 | mv tmp/$@ .
32 |
33 | ${PLUGIN}.vmb.gz: ${PLUGIN}.vmb
34 | @rm -f ${PLUGIN}.vmb.gz
35 | gzip $<
36 |
37 | vmb: ${PLUGIN}.vmb
38 |
39 | vmb.gz: ${PLUGIN}.vmb.gz
40 |
41 | ${PLUGIN}.vba: ${PLUGIN}.vmb
42 | mv $< $@
43 |
44 | ${PLUGIN}.vba.gz: ${PLUGIN}.vba
45 | @rm -f ${PLUGIN}.vba.gz
46 | gzip $<
47 |
48 | vba: ${PLUGIN}.vba
49 |
50 | vba.gz: ${PLUGIN}.vba.gz
51 |
52 | # run unit tests
53 | test: check
54 |
55 | check: tests/run_tests.py
56 | cd tests && python2 run_tests.py
57 |
58 | # generate documentation
59 | docs: documentation
60 | cd $< && $(MAKE)
61 |
62 | # generate a test coverage report for all python files
63 | coverage:
64 | @echo ">>> Coverage depends on the package python-nose and python-coverage, make sure they are installed!"
65 | cd tests && nosetests2 --with-coverage --cover-html .
66 |
67 | # run a static code checker
68 | lint:
69 | @echo ">>> Lint depends on the package pylint make sure it's installed!"
70 | pylint --rcfile .pylintrc --disable=C0301,C0103,C0111,C0322,C0323,C0324,W0703,W0612,W0603 orgmode
71 |
72 | lintall:
73 | @echo ">>> Lint depends on the package pylint make sure it's installed!"
74 | pylint --rcfile .pylintrc orgmode
75 |
76 | # install vim-orgmode in the .vim/bundle directory for test purposes
77 | VIMPLUGINDIR = $(HOME)/.vim/bundle/orgmode
78 |
79 | installvmb: ${PLUGIN}.vmb install_vmb.vim
80 | rm -rvf ${VIMPLUGINDIR}
81 | mkdir -p "${VIMPLUGINDIR}"
82 | vim --cmd "let g:installdir='${VIMPLUGINDIR}'" -s install_vmb.vim $<
83 | @echo "Plugin was installed in ${VIMPLUGINDIR}. Make sure you are using a plugin loader like pathegon, otherwise the ${PLUGIN} might not work properly."
84 |
85 | installvba: ${PLUGIN}.vba install_vba.vim
86 | rm -rvf ${VIMPLUGINDIR}
87 | mkdir -p "${VIMPLUGINDIR}"
88 | vim --cmd "let g:installdir='${VIMPLUGINDIR}'" -s install_vba.vim $<
89 | @echo "Plugin was installed in ${VIMPLUGINDIR}. Make sure you are using a plugin loader like pathegon, otherwise the ${PLUGIN} might not work properly."
90 |
91 | .PHONY: all build test check install clean vmb vmb.gz docs installvmb
92 |
--------------------------------------------------------------------------------
/README.org:
--------------------------------------------------------------------------------
1 | * Vim-OrgMode
2 |
3 | #+ATTR_HTML: title="Join the chat at https://gitter.im/jceb/vim-orgmode"
4 | [[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]]
5 | [[https://travis-ci.org/jceb/vim-orgmode][file:https://travis-ci.org/jceb/vim-orgmode.svg]]
6 | [[https://codecov.io/gh/jceb/vim-orgmode][file:https://codecov.io/gh/jceb/vim-orgmode/branch/master/graph/badge.svg]]
7 |
8 | Text outlining and task management for Vim based on [[http://orgmode.org/][Emacs' Org-Mode]].
9 |
10 | The idea for this plugin was born by listening to the
11 | [[http://twit.tv/floss136][Floss Weekly podcast]] introducing Emacs Org-Mode.
12 | Org-Mode has a lot of strong features like folding, views (sparse tree) and
13 | scheduling of tasks. These are completed by hyperlinks, tags, todo states,
14 | priorities aso.
15 |
16 | vim-orgmode aims at providing the same functionality for Vim.
17 |
18 | [[https://github.com/jceb/vim-orgmode/blob/master/examples/mylife.org][file:examples/mylife.gif]]
19 |
20 | ** Features
21 | Currently vim-orgmode does not support all orgmode features but is quite
22 | usable. Short list of the already supported features:
23 |
24 | - Syntax highlighting
25 | - Cycle visibility of headings (folding)
26 | - Navigate between headings
27 | - Edit the structure of the document: add, move, promote, denote headings
28 | and more
29 | - Hyperlinks within vim-orgmode and outside (files, webpages, etc.)
30 | - TODO list management
31 | - Tags for headings
32 | - Lists in alphanumeric and bullet item notation and checkbox support
33 | - Basic date handling
34 | - Export to other formats (via Emacs' Org-Mode)
35 |
36 | * Installation and Usage
37 | Installation and usage instructions are found in the file [[doc/orgguide.txt][doc/orgguide.txt]].
38 |
39 | * License
40 | Information about the license is found in file [[LICENSE]].
41 |
42 | * Changelog
43 | All changes are found in file [[https://github.com/jceb/vim-orgmode/blob/master/CHANGELOG.org][CHANGELOG.org]]
44 |
--------------------------------------------------------------------------------
/examples/mylife.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jceb/vim-orgmode/83982349e45e6d27d186ad82050f86c3233a16f0/examples/mylife.gif
--------------------------------------------------------------------------------
/examples/mylife.org:
--------------------------------------------------------------------------------
1 | * My Life in plain text
2 | - [X] birth
3 | - [-] life [50%]
4 | - [X] use vim
5 | - [ ] get everything else done
6 | * Write minutes of last meeting <2014-08-08 Fri> :work:
7 | ** DONE John said
8 | this
9 | ** TODO Mary said
10 | that
11 | ** WAITING What did Mark say?
12 | [[http://example.com/here/is/the/recording][1st recording]]
13 | [[http://example.com/here/is/the/recording][2nd recording]]
14 | * Some folding headline 1 :one:
15 | ** Folded
16 | *** Even more folded
17 | * Some folding headline 2
18 | ** Folded :two:
19 | *** Even more folded
20 | * Some folding headline 3
21 | ** Folded
22 | *** Even more folded :three:
23 | * Some folding headline 4
24 | ** Folded
25 | *** Even more folded
26 | completely unfolded
27 |
--------------------------------------------------------------------------------
/examples/mylife.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jceb/vim-orgmode/83982349e45e6d27d186ad82050f86c3233a16f0/examples/mylife.png
--------------------------------------------------------------------------------
/examples/plugins/PluginExample.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from orgmode import echo, echom, echoe, ORGMODE, apply_count, repeat
4 | from orgmode.menu import Submenu, Separator, ActionEntry
5 | from orgmode.keybinding import Keybinding, Plug, Command
6 |
7 | import vim
8 |
9 |
10 | class Example(object):
11 | u"""
12 | Example plugin.
13 |
14 | TODO: Extend this doc!
15 | """
16 |
17 | def __init__(self):
18 | u""" Initialize plugin """
19 | object.__init__(self)
20 | # menu entries this plugin should create
21 | self.menu = ORGMODE.orgmenu + Submenu(u'Example')
22 |
23 | # key bindings for this plugin
24 | # key bindings are also registered through the menu so only additional
25 | # bindings should be put in this variable
26 | self.keybindings = []
27 |
28 | # commands for this plugin
29 | self.commands = []
30 |
31 | @classmethod
32 | def action(cls):
33 | u"""
34 | Some kind of action.
35 |
36 | :returns: TODO
37 | """
38 | pass
39 |
40 | def register(self):
41 | u"""
42 | Registration of the plugin.
43 |
44 | Key bindings and other initialization should be done here.
45 | """
46 | # an Action menu entry which binds "keybinding" to action ":action"
47 | self.commands.append(Command(u'OrgActionCommand',
48 | u':py ORGMODE.plugins["Example"].action()'))
49 | self.keybindings.append(Keybinding(u'keybinding',
50 | Plug(u'OrgAction', self.commands[-1])))
51 | self.menu + ActionEntry(u'&Action', self.keybindings[-1])
52 |
--------------------------------------------------------------------------------
/ftdetect/org.vim:
--------------------------------------------------------------------------------
1 | autocmd BufNewFile,BufRead *.org setfiletype org
2 | "autocmd BufNewFile,BufReadPost org:todo* setfiletype orgtodo
3 |
--------------------------------------------------------------------------------
/ftplugin/org.cnf:
--------------------------------------------------------------------------------
1 | --langdef=org
2 | --langmap=org:.org
3 | --regex-org=/^(\*+)[[:space:]]+(.*)([[:space:]]+:[^\t ]*:)?$/\1 \2/s,sections/
4 | --regex-org=/\[\[([^][]+)\]\]/\1/h,hyperlinks/
5 | --regex-org=/\[\[[^][]+\]\[([^][]+)\]\]/\1/h,hyperlinks/
6 |
--------------------------------------------------------------------------------
/ftplugin/org.vim:
--------------------------------------------------------------------------------
1 | " org.vim -- Text outlining and task management for Vim based on Emacs' Org-Mode
2 | " @Author : Jan Christoph Ebersbach (jceb@e-jc.de)
3 | " @License : AGPL3 (see http://www.gnu.org/licenses/agpl.txt)
4 | " @Created : 2010-10-03
5 | " @Last Modified: Tue 13. Sep 2011 20:52:57 +0200 CEST
6 | " @Revision : 0.4
7 | " vi: ft=vim:tw=80:sw=4:ts=4:fdm=marker
8 |
9 | if v:version > 702
10 | if has('python3')
11 | let s:py_version = 'python3 '
12 | let s:py_env = 'python3 << EOF'
13 | elseif has('python')
14 | let s:py_version = 'python '
15 | let s:py_env = 'python << EOF'
16 | else
17 | echoerr "Unable to start orgmode. Orgmode depends on Vim >= 7.3 with Python support complied in."
18 | finish
19 | endif
20 | else
21 | echoerr "Unable to start orgmode. Orgmode depends on Vim >= 7.3 with Python support complied in."
22 | finish
23 | endif
24 |
25 | " Init buffer for file {{{1
26 | if ! exists('b:did_ftplugin')
27 | " default emacs settings
28 | setlocal comments=fb:*,b:#,fb:-
29 | setlocal commentstring=#\ %s
30 | setlocal conceallevel=2 concealcursor=nc
31 | " original emacs settings are: setlocal tabstop=6 shiftwidth=6, but because
32 | " of checkbox indentation the following settings are used:
33 | setlocal tabstop=6 shiftwidth=6
34 | if exists('g:org_tag_column')
35 | exe 'setlocal textwidth='.g:org_tag_column
36 | else
37 | setlocal textwidth=77
38 | endif
39 |
40 | " expand tab for counting level of checkbox
41 | setlocal expandtab
42 |
43 | " enable % for angle brackets < >
44 | setlocal matchpairs+=<:>
45 |
46 | " register keybindings if they don't have been registered before
47 | if exists("g:loaded_org")
48 | exe s:py_version . 'ORGMODE.register_keybindings()'
49 | endif
50 | endif
51 |
52 | " Load orgmode just once {{{1
53 | if &cp || exists("g:loaded_org")
54 | finish
55 | endif
56 | let g:loaded_org = 1
57 |
58 | " Default org plugins that will be loaded (in the given order) {{{2
59 | if ! exists('g:org_plugins') && ! exists('b:org_plugins')
60 | let g:org_plugins = ['ShowHide', '|', 'Navigator', 'EditStructure', 'EditCheckbox', '|', 'Hyperlinks', '|', 'Todo', 'TagsProperties', 'Date', 'Agenda', 'Misc', '|', 'Export']
61 | endif
62 |
63 | " Default org plugin settings {{{2
64 | " What does this do?
65 | if ! exists('g:org_syntax_highlight_leading_stars') && ! exists('b:org_syntax_highlight_leading_stars')
66 | let g:org_syntax_highlight_leading_stars = 1
67 | endif
68 |
69 | " setting to conceal aggresively
70 | if ! exists('g:org_aggressive_conceal') && ! exists('b:org_aggressive_conceal')
71 | let g:org_aggressive_conceal = 0
72 | endif
73 |
74 | " Defined in separate plugins
75 | " Adding Behavior preference:
76 | " 1: go into insert-mode when new heading/checkbox/plainlist added
77 | " 0: retain original mode when new heading/checkbox/plainlist added
78 | if ! exists('g:org_prefer_insert_mode') && ! exists('b:org_prefer_insert_mode')
79 | let g:org_prefer_insert_mode = 1
80 | endif
81 |
82 | " Menu and document handling {{{1
83 | function! OrgRegisterMenu()
84 | exe s:py_version . 'ORGMODE.register_menu()'
85 | endfunction
86 |
87 | function! OrgUnregisterMenu()
88 | exe s:py_version . 'ORGMODE.unregister_menu()'
89 | endfunction
90 |
91 | function! OrgDeleteUnusedDocument(bufnr)
92 | exe s:py_env
93 | b = int(vim.eval('a:bufnr'))
94 | if b in ORGMODE._documents:
95 | del ORGMODE._documents[b]
96 | EOF
97 | endfunction
98 |
99 | " show and hide Org menu depending on the filetype
100 | augroup orgmode
101 | au BufEnter * :if &filetype == "org" | call OrgRegisterMenu() | endif
102 | au BufLeave * :if &filetype == "org" | call OrgUnregisterMenu() | endif
103 | au BufDelete * :call OrgDeleteUnusedDocument(expand(''))
104 | augroup END
105 |
106 | " Start orgmode {{{1
107 | " Expand our path
108 | exec s:py_env
109 | import glob, vim, os, sys
110 |
111 | for p in vim.eval("&runtimepath").split(','):
112 | dname = os.path.join(p, "ftplugin")
113 | matches = glob.glob(dname)
114 | for match in matches:
115 | if os.path.exists(os.path.join(match, "orgmode")):
116 | if match not in sys.path:
117 | sys.path.append(match)
118 | break
119 |
120 | from orgmode._vim import ORGMODE, insert_at_cursor, get_user_input, date_to_str
121 | ORGMODE.start()
122 |
123 | import datetime
124 | EOF
125 |
126 | " 3rd Party Plugin Integration {{{1
127 | " * Repeat {{{2
128 | try
129 | call repeat#set()
130 | catch
131 | endtry
132 |
133 | " * Tagbar {{{2
134 | let g:tagbar_type_org = {
135 | \ 'ctagstype' : 'org',
136 | \ 'kinds' : [
137 | \ 's:sections',
138 | \ 'h:hyperlinks',
139 | \ ],
140 | \ 'sort' : 0,
141 | \ 'deffile' : expand(':p:h') . '/org.cnf'
142 | \ }
143 |
144 | " * Taglist {{{2
145 | if exists('g:Tlist_Ctags_Cmd')
146 | " Pass parameters to taglist
147 | let g:tlist_org_settings = 'org;s:section;h:hyperlinks'
148 | let g:Tlist_Ctags_Cmd .= ' --options=' . expand(':p:h') . '/org.cnf '
149 | endif
150 |
151 | " * Calendar.vim {{{2
152 | fun CalendarAction(day, month, year, week, dir)
153 | exe s:py_version . "selected_date = " . printf("datetime.date(%d, %d, %d)", a:year, a:month, a:day)
154 | exe s:py_version . "org_timestamp = '" . g:org_timestamp_template . "' % date_to_str(selected_date)"
155 |
156 | " get_user_input
157 | exe s:py_version . "modifier = get_user_input(org_timestamp)"
158 | " change date according to user input
159 | exe s:py_version . "newdate = Date._modify_time(selected_date, modifier)"
160 | exe s:py_version . "newdate = date_to_str(newdate)"
161 | " close Calendar
162 | exe "q"
163 | " goto previous window
164 | exe "wincmd p"
165 | exe s:py_version . "timestamp = '" . g:org_timestamp_template . "' % newdate"
166 | exe s:py_version . "if modifier != None: insert_at_cursor(timestamp)"
167 | " restore calendar_action
168 | let g:calendar_action = g:org_calendar_action_backup
169 | endf
170 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # User-friendly check for sphinx-build
11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12 | $(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/)
13 | endif
14 |
15 | # Internal variables.
16 | PAPEROPT_a4 = -D latex_paper_size=a4
17 | PAPEROPT_letter = -D latex_paper_size=letter
18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
19 | # the i18n builder cannot share the environment and doctrees with the others
20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
21 |
22 | .PHONY: help
23 | help:
24 | @echo "Please use \`make ' where is one of"
25 | @echo " html to make standalone HTML files"
26 | @echo " dirhtml to make HTML files named index.html in directories"
27 | @echo " singlehtml to make a single large HTML file"
28 | @echo " pickle to make pickle files"
29 | @echo " json to make JSON files"
30 | @echo " htmlhelp to make HTML files and a HTML help project"
31 | @echo " qthelp to make HTML files and a qthelp project"
32 | @echo " applehelp to make an Apple Help Book"
33 | @echo " devhelp to make HTML files and a Devhelp project"
34 | @echo " epub to make an epub"
35 | @echo " epub3 to make an epub3"
36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
37 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
39 | @echo " text to make text files"
40 | @echo " man to make manual pages"
41 | @echo " texinfo to make Texinfo files"
42 | @echo " info to make Texinfo files and run them through makeinfo"
43 | @echo " gettext to make PO message catalogs"
44 | @echo " changes to make an overview of all changed/added/deprecated items"
45 | @echo " xml to make Docutils-native XML files"
46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes"
47 | @echo " linkcheck to check all external links for integrity"
48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
49 | @echo " coverage to run coverage check of the documentation (if enabled)"
50 | @echo " dummy to check syntax errors of document sources"
51 |
52 | .PHONY: clean
53 | clean:
54 | rm -rf $(BUILDDIR)/*
55 |
56 | .PHONY: html
57 | html:
58 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
59 | @echo
60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
61 |
62 | .PHONY: dirhtml
63 | dirhtml:
64 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
65 | @echo
66 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
67 |
68 | .PHONY: singlehtml
69 | singlehtml:
70 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
71 | @echo
72 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
73 |
74 | .PHONY: pickle
75 | pickle:
76 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
77 | @echo
78 | @echo "Build finished; now you can process the pickle files."
79 |
80 | .PHONY: json
81 | json:
82 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
83 | @echo
84 | @echo "Build finished; now you can process the JSON files."
85 |
86 | .PHONY: htmlhelp
87 | htmlhelp:
88 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
89 | @echo
90 | @echo "Build finished; now you can run HTML Help Workshop with the" \
91 | ".hhp project file in $(BUILDDIR)/htmlhelp."
92 |
93 | .PHONY: qthelp
94 | qthelp:
95 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
96 | @echo
97 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
98 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
99 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/orgmode.qhcp"
100 | @echo "To view the help file:"
101 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/orgmode.qhc"
102 |
103 | .PHONY: applehelp
104 | applehelp:
105 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
106 | @echo
107 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
108 | @echo "N.B. You won't be able to view it unless you put it in" \
109 | "~/Library/Documentation/Help or install it in your application" \
110 | "bundle."
111 |
112 | .PHONY: devhelp
113 | devhelp:
114 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
115 | @echo
116 | @echo "Build finished."
117 | @echo "To view the help file:"
118 | @echo "# mkdir -p $$HOME/.local/share/devhelp/orgmode"
119 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/orgmode"
120 | @echo "# devhelp"
121 |
122 | .PHONY: epub
123 | epub:
124 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
125 | @echo
126 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
127 |
128 | .PHONY: epub3
129 | epub3:
130 | $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
131 | @echo
132 | @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
133 |
134 | .PHONY: latex
135 | latex:
136 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
137 | @echo
138 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
139 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
140 | "(use \`make latexpdf' here to do that automatically)."
141 |
142 | .PHONY: latexpdf
143 | latexpdf:
144 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
145 | @echo "Running LaTeX files through pdflatex..."
146 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
147 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
148 |
149 | .PHONY: latexpdfja
150 | latexpdfja:
151 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
152 | @echo "Running LaTeX files through platex and dvipdfmx..."
153 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
154 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
155 |
156 | .PHONY: text
157 | text:
158 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
159 | @echo
160 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
161 |
162 | .PHONY: man
163 | man:
164 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
165 | @echo
166 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
167 |
168 | .PHONY: texinfo
169 | texinfo:
170 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
171 | @echo
172 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
173 | @echo "Run \`make' in that directory to run these through makeinfo" \
174 | "(use \`make info' here to do that automatically)."
175 |
176 | .PHONY: info
177 | info:
178 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
179 | @echo "Running Texinfo files through makeinfo..."
180 | make -C $(BUILDDIR)/texinfo info
181 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
182 |
183 | .PHONY: gettext
184 | gettext:
185 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
186 | @echo
187 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
188 |
189 | .PHONY: changes
190 | changes:
191 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
192 | @echo
193 | @echo "The overview file is in $(BUILDDIR)/changes."
194 |
195 | .PHONY: linkcheck
196 | linkcheck:
197 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
198 | @echo
199 | @echo "Link check complete; look for any errors in the above output " \
200 | "or in $(BUILDDIR)/linkcheck/output.txt."
201 |
202 | .PHONY: doctest
203 | doctest:
204 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
205 | @echo "Testing of doctests in the sources finished, look at the " \
206 | "results in $(BUILDDIR)/doctest/output.txt."
207 |
208 | .PHONY: coverage
209 | coverage:
210 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
211 | @echo "Testing of coverage in the sources finished, look at the " \
212 | "results in $(BUILDDIR)/coverage/python.txt."
213 |
214 | .PHONY: xml
215 | xml:
216 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
217 | @echo
218 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
219 |
220 | .PHONY: pseudoxml
221 | pseudoxml:
222 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
223 | @echo
224 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
225 |
226 | .PHONY: dummy
227 | dummy:
228 | $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
229 | @echo
230 | @echo "Build finished. Dummy builder generates no files."
231 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. orgmode documentation master file, created by
2 | sphinx-quickstart on Sat May 21 16:35:00 2016.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to orgmode's documentation!
7 | ===================================
8 |
9 | Contents:
10 |
11 | .. toctree::
12 | :maxdepth: 4
13 |
14 | orgmode
15 |
16 |
17 | Indices and tables
18 | ==================
19 |
20 | * :ref:`genindex`
21 | * :ref:`modindex`
22 | * :ref:`search`
23 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Command file for Sphinx documentation
4 |
5 | if "%SPHINXBUILD%" == "" (
6 | set SPHINXBUILD=sphinx-build
7 | )
8 | set BUILDDIR=_build
9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
10 | set I18NSPHINXOPTS=%SPHINXOPTS% .
11 | if NOT "%PAPER%" == "" (
12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
14 | )
15 |
16 | if "%1" == "" goto help
17 |
18 | if "%1" == "help" (
19 | :help
20 | echo.Please use `make ^` where ^ is one of
21 | echo. html to make standalone HTML files
22 | echo. dirhtml to make HTML files named index.html in directories
23 | echo. singlehtml to make a single large HTML file
24 | echo. pickle to make pickle files
25 | echo. json to make JSON files
26 | echo. htmlhelp to make HTML files and a HTML help project
27 | echo. qthelp to make HTML files and a qthelp project
28 | echo. devhelp to make HTML files and a Devhelp project
29 | echo. epub to make an epub
30 | echo. epub3 to make an epub3
31 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
32 | echo. text to make text files
33 | echo. man to make manual pages
34 | echo. texinfo to make Texinfo files
35 | echo. gettext to make PO message catalogs
36 | echo. changes to make an overview over all changed/added/deprecated items
37 | echo. xml to make Docutils-native XML files
38 | echo. pseudoxml to make pseudoxml-XML files for display purposes
39 | echo. linkcheck to check all external links for integrity
40 | echo. doctest to run all doctests embedded in the documentation if enabled
41 | echo. coverage to run coverage check of the documentation if enabled
42 | echo. dummy to check syntax errors of document sources
43 | goto end
44 | )
45 |
46 | if "%1" == "clean" (
47 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
48 | del /q /s %BUILDDIR%\*
49 | goto end
50 | )
51 |
52 |
53 | REM Check if sphinx-build is available and fallback to Python version if any
54 | %SPHINXBUILD% 1>NUL 2>NUL
55 | if errorlevel 9009 goto sphinx_python
56 | goto sphinx_ok
57 |
58 | :sphinx_python
59 |
60 | set SPHINXBUILD=python -m sphinx.__init__
61 | %SPHINXBUILD% 2> nul
62 | if errorlevel 9009 (
63 | echo.
64 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
65 | echo.installed, then set the SPHINXBUILD environment variable to point
66 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
67 | echo.may add the Sphinx directory to PATH.
68 | echo.
69 | echo.If you don't have Sphinx installed, grab it from
70 | echo.http://sphinx-doc.org/
71 | exit /b 1
72 | )
73 |
74 | :sphinx_ok
75 |
76 |
77 | if "%1" == "html" (
78 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
79 | if errorlevel 1 exit /b 1
80 | echo.
81 | echo.Build finished. The HTML pages are in %BUILDDIR%/html.
82 | goto end
83 | )
84 |
85 | if "%1" == "dirhtml" (
86 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
87 | if errorlevel 1 exit /b 1
88 | echo.
89 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
90 | goto end
91 | )
92 |
93 | if "%1" == "singlehtml" (
94 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
95 | if errorlevel 1 exit /b 1
96 | echo.
97 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
98 | goto end
99 | )
100 |
101 | if "%1" == "pickle" (
102 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
103 | if errorlevel 1 exit /b 1
104 | echo.
105 | echo.Build finished; now you can process the pickle files.
106 | goto end
107 | )
108 |
109 | if "%1" == "json" (
110 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
111 | if errorlevel 1 exit /b 1
112 | echo.
113 | echo.Build finished; now you can process the JSON files.
114 | goto end
115 | )
116 |
117 | if "%1" == "htmlhelp" (
118 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
119 | if errorlevel 1 exit /b 1
120 | echo.
121 | echo.Build finished; now you can run HTML Help Workshop with the ^
122 | .hhp project file in %BUILDDIR%/htmlhelp.
123 | goto end
124 | )
125 |
126 | if "%1" == "qthelp" (
127 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
128 | if errorlevel 1 exit /b 1
129 | echo.
130 | echo.Build finished; now you can run "qcollectiongenerator" with the ^
131 | .qhcp project file in %BUILDDIR%/qthelp, like this:
132 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\orgmode.qhcp
133 | echo.To view the help file:
134 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\orgmode.ghc
135 | goto end
136 | )
137 |
138 | if "%1" == "devhelp" (
139 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
140 | if errorlevel 1 exit /b 1
141 | echo.
142 | echo.Build finished.
143 | goto end
144 | )
145 |
146 | if "%1" == "epub" (
147 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
148 | if errorlevel 1 exit /b 1
149 | echo.
150 | echo.Build finished. The epub file is in %BUILDDIR%/epub.
151 | goto end
152 | )
153 |
154 | if "%1" == "epub3" (
155 | %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
156 | if errorlevel 1 exit /b 1
157 | echo.
158 | echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
159 | goto end
160 | )
161 |
162 | if "%1" == "latex" (
163 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
164 | if errorlevel 1 exit /b 1
165 | echo.
166 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
167 | goto end
168 | )
169 |
170 | if "%1" == "latexpdf" (
171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
172 | cd %BUILDDIR%/latex
173 | make all-pdf
174 | cd %~dp0
175 | echo.
176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex.
177 | goto end
178 | )
179 |
180 | if "%1" == "latexpdfja" (
181 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
182 | cd %BUILDDIR%/latex
183 | make all-pdf-ja
184 | cd %~dp0
185 | echo.
186 | echo.Build finished; the PDF files are in %BUILDDIR%/latex.
187 | goto end
188 | )
189 |
190 | if "%1" == "text" (
191 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
192 | if errorlevel 1 exit /b 1
193 | echo.
194 | echo.Build finished. The text files are in %BUILDDIR%/text.
195 | goto end
196 | )
197 |
198 | if "%1" == "man" (
199 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
200 | if errorlevel 1 exit /b 1
201 | echo.
202 | echo.Build finished. The manual pages are in %BUILDDIR%/man.
203 | goto end
204 | )
205 |
206 | if "%1" == "texinfo" (
207 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
208 | if errorlevel 1 exit /b 1
209 | echo.
210 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
211 | goto end
212 | )
213 |
214 | if "%1" == "gettext" (
215 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
216 | if errorlevel 1 exit /b 1
217 | echo.
218 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
219 | goto end
220 | )
221 |
222 | if "%1" == "changes" (
223 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
224 | if errorlevel 1 exit /b 1
225 | echo.
226 | echo.The overview file is in %BUILDDIR%/changes.
227 | goto end
228 | )
229 |
230 | if "%1" == "linkcheck" (
231 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
232 | if errorlevel 1 exit /b 1
233 | echo.
234 | echo.Link check complete; look for any errors in the above output ^
235 | or in %BUILDDIR%/linkcheck/output.txt.
236 | goto end
237 | )
238 |
239 | if "%1" == "doctest" (
240 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
241 | if errorlevel 1 exit /b 1
242 | echo.
243 | echo.Testing of doctests in the sources finished, look at the ^
244 | results in %BUILDDIR%/doctest/output.txt.
245 | goto end
246 | )
247 |
248 | if "%1" == "coverage" (
249 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
250 | if errorlevel 1 exit /b 1
251 | echo.
252 | echo.Testing of coverage in the sources finished, look at the ^
253 | results in %BUILDDIR%/coverage/python.txt.
254 | goto end
255 | )
256 |
257 | if "%1" == "xml" (
258 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
259 | if errorlevel 1 exit /b 1
260 | echo.
261 | echo.Build finished. The XML files are in %BUILDDIR%/xml.
262 | goto end
263 | )
264 |
265 | if "%1" == "pseudoxml" (
266 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
267 | if errorlevel 1 exit /b 1
268 | echo.
269 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
270 | goto end
271 | )
272 |
273 | if "%1" == "dummy" (
274 | %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
275 | if errorlevel 1 exit /b 1
276 | echo.
277 | echo.Build finished. Dummy builder generates no files.
278 | goto end
279 | )
280 |
281 | :end
282 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/docs/orgmode.liborgmode.rst:
--------------------------------------------------------------------------------
1 | orgmode.liborgmode package
2 | ==========================
3 |
4 | Submodules
5 | ----------
6 |
7 | orgmode.liborgmode.agenda module
8 | --------------------------------
9 |
10 | .. automodule:: orgmode.liborgmode.agenda
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | orgmode.liborgmode.agendafilter module
16 | --------------------------------------
17 |
18 | .. automodule:: orgmode.liborgmode.agendafilter
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | orgmode.liborgmode.base module
24 | ------------------------------
25 |
26 | .. automodule:: orgmode.liborgmode.base
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | orgmode.liborgmode.checkboxes module
32 | ------------------------------------
33 |
34 | .. automodule:: orgmode.liborgmode.checkboxes
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 | orgmode.liborgmode.documents module
40 | -----------------------------------
41 |
42 | .. automodule:: orgmode.liborgmode.documents
43 | :members:
44 | :undoc-members:
45 | :show-inheritance:
46 |
47 | orgmode.liborgmode.dom_obj module
48 | ---------------------------------
49 |
50 | .. automodule:: orgmode.liborgmode.dom_obj
51 | :members:
52 | :undoc-members:
53 | :show-inheritance:
54 |
55 | orgmode.liborgmode.headings module
56 | ----------------------------------
57 |
58 | .. automodule:: orgmode.liborgmode.headings
59 | :members:
60 | :undoc-members:
61 | :show-inheritance:
62 |
63 | orgmode.liborgmode.orgdate module
64 | ---------------------------------
65 |
66 | .. automodule:: orgmode.liborgmode.orgdate
67 | :members:
68 | :undoc-members:
69 | :show-inheritance:
70 |
71 |
72 | Module contents
73 | ---------------
74 |
75 | .. automodule:: orgmode.liborgmode
76 | :members:
77 | :undoc-members:
78 | :show-inheritance:
79 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/docs/orgmode.plugins.rst:
--------------------------------------------------------------------------------
1 | orgmode.plugins package
2 | =======================
3 |
4 | Submodules
5 | ----------
6 |
7 | orgmode.plugins.Agenda module
8 | -----------------------------
9 |
10 | .. automodule:: orgmode.plugins.Agenda
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | orgmode.plugins.Date module
16 | ---------------------------
17 |
18 | .. automodule:: orgmode.plugins.Date
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | orgmode.plugins.EditCheckbox module
24 | -----------------------------------
25 |
26 | .. automodule:: orgmode.plugins.EditCheckbox
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | orgmode.plugins.EditStructure module
32 | ------------------------------------
33 |
34 | .. automodule:: orgmode.plugins.EditStructure
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 | orgmode.plugins.Export module
40 | -----------------------------
41 |
42 | .. automodule:: orgmode.plugins.Export
43 | :members:
44 | :undoc-members:
45 | :show-inheritance:
46 |
47 | orgmode.plugins.Hyperlinks module
48 | ---------------------------------
49 |
50 | .. automodule:: orgmode.plugins.Hyperlinks
51 | :members:
52 | :undoc-members:
53 | :show-inheritance:
54 |
55 | orgmode.plugins.LoggingWork module
56 | ----------------------------------
57 |
58 | .. automodule:: orgmode.plugins.LoggingWork
59 | :members:
60 | :undoc-members:
61 | :show-inheritance:
62 |
63 | orgmode.plugins.Misc module
64 | ---------------------------
65 |
66 | .. automodule:: orgmode.plugins.Misc
67 | :members:
68 | :undoc-members:
69 | :show-inheritance:
70 |
71 | orgmode.plugins.Navigator module
72 | --------------------------------
73 |
74 | .. automodule:: orgmode.plugins.Navigator
75 | :members:
76 | :undoc-members:
77 | :show-inheritance:
78 |
79 | orgmode.plugins.ShowHide module
80 | -------------------------------
81 |
82 | .. automodule:: orgmode.plugins.ShowHide
83 | :members:
84 | :undoc-members:
85 | :show-inheritance:
86 |
87 | orgmode.plugins.TagsProperties module
88 | -------------------------------------
89 |
90 | .. automodule:: orgmode.plugins.TagsProperties
91 | :members:
92 | :undoc-members:
93 | :show-inheritance:
94 |
95 | orgmode.plugins.Todo module
96 | ---------------------------
97 |
98 | .. automodule:: orgmode.plugins.Todo
99 | :members:
100 | :undoc-members:
101 | :show-inheritance:
102 |
103 |
104 | Module contents
105 | ---------------
106 |
107 | .. automodule:: orgmode.plugins
108 | :members:
109 | :undoc-members:
110 | :show-inheritance:
111 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/docs/orgmode.py3compat.rst:
--------------------------------------------------------------------------------
1 | orgmode.py3compat package
2 | =========================
3 |
4 | Submodules
5 | ----------
6 |
7 | orgmode.py3compat.encode_compatibility module
8 | ---------------------------------------------
9 |
10 | .. automodule:: orgmode.py3compat.encode_compatibility
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | orgmode.py3compat.py_py3_string module
16 | --------------------------------------
17 |
18 | .. automodule:: orgmode.py3compat.py_py3_string
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | orgmode.py3compat.unicode_compatibility module
24 | ----------------------------------------------
25 |
26 | .. automodule:: orgmode.py3compat.unicode_compatibility
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | orgmode.py3compat.xrange_compatibility module
32 | ---------------------------------------------
33 |
34 | .. automodule:: orgmode.py3compat.xrange_compatibility
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 |
40 | Module contents
41 | ---------------
42 |
43 | .. automodule:: orgmode.py3compat
44 | :members:
45 | :undoc-members:
46 | :show-inheritance:
47 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/docs/orgmode.rst:
--------------------------------------------------------------------------------
1 | orgmode package
2 | ===============
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 |
9 | orgmode.liborgmode
10 | orgmode.plugins
11 | orgmode.py3compat
12 |
13 | Submodules
14 | ----------
15 |
16 | orgmode._vim module
17 | -------------------
18 |
19 | .. automodule:: orgmode._vim
20 | :members:
21 | :undoc-members:
22 | :show-inheritance:
23 |
24 | orgmode.exceptions module
25 | -------------------------
26 |
27 | .. automodule:: orgmode.exceptions
28 | :members:
29 | :undoc-members:
30 | :show-inheritance:
31 |
32 | orgmode.keybinding module
33 | -------------------------
34 |
35 | .. automodule:: orgmode.keybinding
36 | :members:
37 | :undoc-members:
38 | :show-inheritance:
39 |
40 | orgmode.menu module
41 | -------------------
42 |
43 | .. automodule:: orgmode.menu
44 | :members:
45 | :undoc-members:
46 | :show-inheritance:
47 |
48 | orgmode.settings module
49 | -----------------------
50 |
51 | .. automodule:: orgmode.settings
52 | :members:
53 | :undoc-members:
54 | :show-inheritance:
55 |
56 | orgmode.vimbuffer module
57 | ------------------------
58 |
59 | .. automodule:: orgmode.vimbuffer
60 | :members:
61 | :undoc-members:
62 | :show-inheritance:
63 |
64 |
65 | Module contents
66 | ---------------
67 |
68 | .. automodule:: orgmode
69 | :members:
70 | :undoc-members:
71 | :show-inheritance:
72 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/exceptions.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | class PluginError(BaseException):
5 | def __init__(self, message):
6 | BaseException.__init__(self, message)
7 |
8 |
9 | class BufferNotFound(BaseException):
10 | def __init__(self, message):
11 | BaseException.__init__(self, message)
12 |
13 |
14 | class BufferNotInSync(BaseException):
15 | def __init__(self, message):
16 | BaseException.__init__(self, message)
17 |
18 |
19 | class HeadingDomError(BaseException):
20 | def __init__(self, message):
21 | BaseException.__init__(self, message)
22 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/keybinding.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import vim
4 |
5 | MODE_ALL = u'a'
6 | MODE_NORMAL = u'n'
7 | MODE_VISUAL = u'v'
8 | MODE_INSERT = u'i'
9 | MODE_OPERATOR = u'o'
10 |
11 | OPTION_BUFFER_ONLY = u''
12 | OPTION_SLIENT = u''
13 |
14 | from orgmode.py3compat.encode_compatibility import *
15 |
16 | def _register(f, name):
17 | def r(*args, **kwargs):
18 | p = f(*args, **kwargs)
19 | if hasattr(p, name) and isinstance(getattr(p, name), list):
20 | for i in getattr(p, name):
21 | i.create()
22 | return p
23 | return r
24 |
25 |
26 | def register_keybindings(f):
27 | return _register(f, u'keybindings')
28 |
29 |
30 | def register_commands(f):
31 | return _register(f, u'commands')
32 |
33 |
34 | class Command(object):
35 | u""" A vim command """
36 |
37 | def __init__(self, name, command, arguments=u'0', complete=None, overwrite_exisiting=False):
38 | u"""
39 | :name: The name of command, first character must be uppercase
40 | :command: The actual command that is executed
41 | :arguments: See :h :command-nargs, only the arguments need to be specified
42 | :complete: See :h :command-completion, only the completion arguments need to be specified
43 | """
44 | object.__init__(self)
45 |
46 | self._name = name
47 | self._command = command
48 | self._arguments = arguments
49 | self._complete = complete
50 | self._overwrite_exisiting = overwrite_exisiting
51 |
52 | def __unicode__(self):
53 | return u':%s' % self.name
54 |
55 | def __str__(self):
56 | return u_encode(self.__unicode__())
57 |
58 | @property
59 | def name(self):
60 | return self._name
61 |
62 | @property
63 | def command(self):
64 | return self._command
65 |
66 | @property
67 | def arguments(self):
68 | return self._arguments
69 |
70 | @property
71 | def complete(self):
72 | return self._complete
73 |
74 | @property
75 | def overwrite_exisiting(self):
76 | return self._overwrite_exisiting
77 |
78 | def create(self):
79 | u""" Register/create the command
80 | """
81 | vim.command(u_encode(':command%(overwrite)s -nargs=%(arguments)s %(complete)s %(name)s %(command)s' %
82 | {u'overwrite': '!' if self.overwrite_exisiting else '',
83 | u'arguments': u_encode(self.arguments),
84 | u'complete': '-complete=%s' % u_encode(self.complete) if self.complete else '',
85 | u'name': self.name,
86 | u'command': self.command}
87 | ))
88 |
89 |
90 | class Plug(object):
91 | u""" Represents a to an abitrary command """
92 |
93 | def __init__(self, name, command, mode=MODE_NORMAL):
94 | u"""
95 | :name: the name of the should be ScriptnameCommandname
96 | :command: the actual command
97 | """
98 | object.__init__(self)
99 |
100 | if mode not in (MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR):
101 | raise ValueError(u'Parameter mode not in MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR')
102 | self._mode = mode
103 |
104 | self.name = name
105 | self.command = command
106 | self.created = False
107 |
108 | def __unicode__(self):
109 | return u'%s' % self.name
110 |
111 | def __str__(self):
112 | return u_encode(self.__unicode__())
113 |
114 | def create(self):
115 | if not self.created:
116 | self.created = True
117 | cmd = self._mode
118 | if cmd == MODE_ALL:
119 | cmd = u''
120 | vim.command(u_encode(u':%snoremap %s %s' % (cmd, str(self), self.command)))
121 |
122 | @property
123 | def mode(self):
124 | return self._mode
125 |
126 |
127 | class Keybinding(object):
128 | u""" Representation of a single key binding """
129 |
130 | def __init__(self, key, action, mode=None, options=None, remap=True, buffer_only=True, silent=True):
131 | u"""
132 | :key: the key(s) action is bound to
133 | :action: the action triggered by key(s)
134 | :mode: definition in which vim modes the key binding is valid. Should be one of MODE_*
135 | :option: list of other options like , ...
136 | :repmap: allow or disallow nested mapping
137 | :buffer_only: define the key binding only for the current buffer
138 | """
139 | object.__init__(self)
140 | self._key = key
141 | self._action = action
142 |
143 | # grab mode from plug if not set otherwise
144 | if isinstance(self._action, Plug) and not mode:
145 | mode = self._action.mode
146 |
147 | if mode not in (MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR):
148 | raise ValueError(u'Parameter mode not in MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT, MODE_OPERATOR')
149 | self._mode = mode
150 | self._options = options
151 | if self._options is None:
152 | self._options = []
153 | self._remap = remap
154 | self._buffer_only = buffer_only
155 | self._silent = silent
156 |
157 | if self._buffer_only and OPTION_BUFFER_ONLY not in self._options:
158 | self._options.append(OPTION_BUFFER_ONLY)
159 |
160 | if self._silent and OPTION_SLIENT not in self._options:
161 | self._options.append(OPTION_SLIENT)
162 |
163 | @property
164 | def key(self):
165 | return self._key
166 |
167 | @property
168 | def action(self):
169 | return str(self._action)
170 |
171 | @property
172 | def mode(self):
173 | return self._mode
174 |
175 | @property
176 | def options(self):
177 | return self._options[:]
178 |
179 | @property
180 | def remap(self):
181 | return self._remap
182 |
183 | @property
184 | def buffer_only(self):
185 | return self._buffer_only
186 |
187 | @property
188 | def silent(self):
189 | return self._silent
190 |
191 | def create(self):
192 | from orgmode._vim import ORGMODE, echom
193 |
194 | cmd = self._mode
195 | if cmd == MODE_ALL:
196 | cmd = u''
197 | if not self._remap:
198 | cmd += u'nore'
199 | try:
200 | create_mapping = True
201 | if isinstance(self._action, Plug):
202 | # create plug
203 | self._action.create()
204 | if int(vim.eval(u_encode(u'hasmapto("%s")' % (self._action, )))):
205 | create_mapping = False
206 | if isinstance(self._action, Command):
207 | # create command
208 | self._action.create()
209 |
210 | if create_mapping:
211 | vim.command(u_encode(u':%smap %s %s %s' % (cmd, u' '.join(self._options), self._key, self._action)))
212 | except BaseException as e:
213 | if ORGMODE.debug:
214 | echom(u'Failed to register key binding %s %s' % (self._key, self._action))
215 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/liborgmode/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/liborgmode/agenda.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | u"""
4 | Agenda
5 | ~~~~~~~~~~~~~~~~~~
6 |
7 | The agenda is one of the main concepts of orgmode. It allows to
8 | collect TODO items from multiple org documents in an agenda view.
9 |
10 | Features:
11 | * filtering
12 | * sorting
13 | """
14 |
15 | from orgmode.liborgmode.agendafilter import filter_items
16 | from orgmode.liborgmode.agendafilter import is_within_week_and_active_todo
17 | from orgmode.liborgmode.agendafilter import contains_active_todo
18 | from orgmode.liborgmode.agendafilter import contains_active_date
19 |
20 |
21 | class AgendaManager(object):
22 | u"""Simple parsing of Documents to create an agenda."""
23 | # TODO Move filters in this file, they do the same thing
24 |
25 | def __init__(self):
26 | super(AgendaManager, self).__init__()
27 |
28 | def get_todo(self, documents):
29 | u"""
30 | Get the todo agenda for the given documents (list of document).
31 | """
32 | filtered = []
33 | for document in iter(documents):
34 | # filter and return headings
35 | filtered.extend(filter_items(document.all_headings(),
36 | [contains_active_todo]))
37 | return sorted(filtered)
38 |
39 | def get_next_week_and_active_todo(self, documents):
40 | u"""
41 | Get the agenda for next week for the given documents (list of
42 | document).
43 | """
44 | filtered = []
45 | for document in iter(documents):
46 | # filter and return headings
47 | filtered.extend(filter_items(document.all_headings(),
48 | [is_within_week_and_active_todo]))
49 | return sorted(filtered)
50 |
51 | def get_timestamped_items(self, documents):
52 | u"""
53 | Get all time-stamped items in a time-sorted way for the given
54 | documents (list of document).
55 | """
56 | filtered = []
57 | for document in iter(documents):
58 | # filter and return headings
59 | filtered.extend(filter_items(document.all_headings(),
60 | [contains_active_date]))
61 | return sorted(filtered)
62 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/liborgmode/agendafilter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | u"""
4 | agendafilter
5 | ~~~~~~~~~~~~~~~~
6 |
7 | AgendaFilter contains all the filters that can be applied to create the
8 | agenda.
9 |
10 |
11 | All functions except filter_items() in the module are filters. Given a
12 | heading they return if the heading meets the criteria of the filter.
13 |
14 | The function filter_items() can combine different filters and only returns
15 | the filtered headings.
16 | """
17 | from datetime import datetime
18 | from datetime import timedelta
19 |
20 | try:
21 | from itertools import ifilter as filter
22 | except:
23 | pass
24 |
25 |
26 | def filter_items(headings, filters):
27 | u""" Filter the given headings.
28 |
29 | Args:
30 | headings (list): Contains headings
31 | filters (list): Filters that will be applied. All functions in
32 | this module (except this function) are filters.
33 |
34 | Returns:
35 | filter iterator: Headings which were not filtered.
36 |
37 | Examples:
38 | >>> filtered = filter_items(headings, [contains_active_date,
39 | contains_active_todo])
40 | """
41 | filtered = headings
42 | for f in filters:
43 | filtered = filter(f, filtered)
44 | return filtered
45 |
46 |
47 | def is_within_week(heading):
48 | u""" Test if headings date is within a week
49 |
50 | Returns:
51 | bool: True if the date in the deading is within a week in the future (or
52 | older False otherwise.
53 | """
54 | if contains_active_date(heading):
55 | next_week = datetime.today() + timedelta(days=7)
56 | if heading.active_date < next_week:
57 | return True
58 |
59 |
60 | def is_within_week_and_active_todo(heading):
61 | u"""
62 | Returns:
63 | bool: True if heading contains an active TODO and the date is within a
64 | week.
65 | """
66 | return is_within_week(heading) and contains_active_todo(heading)
67 |
68 |
69 | def contains_active_todo(heading):
70 | u"""
71 |
72 | Returns:
73 | bool: True if heading contains an active TODO.
74 | """
75 | # TODO make this more efficient by checking some val and not calling the
76 | # function
77 | # TODO why is this import failing at top level? circular dependency...
78 | from orgmode._vim import ORGMODE
79 | active = []
80 | for act in ORGMODE.get_document().get_todo_states():
81 | active.extend(act[0])
82 | return heading.todo in active
83 |
84 |
85 | def contains_active_date(heading):
86 | u"""
87 |
88 | Returns:
89 | bool: True if heading contains an active date.
90 | """
91 | return not(heading.active_date is None)
92 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/liborgmode/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | base
5 | ~~~~~~~~~~
6 |
7 | Here are some really basic data structures that are used throughout
8 | the liborgmode.
9 | """
10 |
11 | try:
12 | from collections import UserList
13 | except:
14 | from UserList import UserList
15 |
16 | try:
17 | from collections.abc import Iterable
18 | except ImportError:
19 | # preserve compatibility with python < 3.10
20 | from collections import Iterable
21 |
22 | import sys
23 | from orgmode.py3compat.unicode_compatibility import *
24 |
25 |
26 | def flatten_list(lst):
27 | """ Flattens a list
28 |
29 | Args:
30 | lst (iterable): An iterable that will is non-flat
31 |
32 | Returns:
33 | list: Flat list
34 | """
35 | # TODO write tests
36 | def gen_lst(item):
37 | if isinstance(item, basestring) or isinstance(item, bytes):
38 | yield item
39 | elif isinstance(item, Iterable):
40 | # yield from would be so nice... but c'est la vie
41 | for val in item:
42 | for final in gen_lst(val):
43 | yield final
44 | else:
45 | yield item
46 | return [i for i in gen_lst(lst)]
47 |
48 |
49 | class Direction():
50 | u"""
51 | Direction is used to indicate the direction of certain actions.
52 |
53 | Example: it defines the direction headings get parted in.
54 | """
55 | FORWARD = 1
56 | BACKWARD = 2
57 |
58 |
59 | class MultiPurposeList(UserList):
60 | u"""
61 | A Multi Purpose List is a list that calls a user defined hook on
62 | change. The implementation is very basic - the hook is called without any
63 | parameters. Otherwise the Multi Purpose List can be used like any other
64 | list.
65 |
66 | The member element "data" can be used to fill the list without causing the
67 | list to be marked dirty. This should only be used during initialization!
68 | """
69 |
70 | def __init__(self, initlist=None, on_change=None):
71 | UserList.__init__(self, initlist)
72 | self._on_change = on_change
73 |
74 | def _changed(self):
75 | u""" Call hook """
76 | if callable(self._on_change):
77 | self._on_change()
78 |
79 | def __setitem__(self, i, item):
80 | if sys.version_info < (3, ) and isinstance(i, slice):
81 | start, stop, _ = i.indices(len(self))
82 | UserList.__setslice__(self, start, stop, item)
83 | else:
84 | UserList.__setitem__(self, i, item)
85 | self._changed()
86 |
87 | def __delitem__(self, i):
88 | if sys.version_info < (3, ) and isinstance(i, slice):
89 | start, stop, _ = i.indices(len(self))
90 | UserList.__delslice__(self, start, stop)
91 | else:
92 | UserList.__delitem__(self, i)
93 | self._changed()
94 |
95 | def __getitem__(self, i):
96 | if sys.version_info < (3, ):
97 | if isinstance(i, slice):
98 | # TODO Return just a list. Why?
99 | return [self[i] for i in range(*i.indices(len(self)))]
100 | # return UserList([self[i] for i in range(*i.indices(len(self)))])
101 | return UserList.__getitem__(self, i)
102 |
103 | # NOTE: These wrappers are necessary because of python 2
104 | def __setslice__(self, i, j, other):
105 | self.__setitem__(slice(i, j), other)
106 |
107 | def __delslice__(self, i, j):
108 | self.__delitem__(slice(i, j))
109 |
110 | def __getslice__(self, i, j):
111 | return self.__getitem__(slice(i, j))
112 |
113 | def __iadd__(self, other):
114 | res = UserList.__iadd__(self, other)
115 | self._changed()
116 | return res
117 |
118 | def __imul__(self, n):
119 | res = UserList.__imul__(self, n)
120 | self._changed()
121 | return res
122 |
123 | def append(self, item):
124 | UserList.append(self, item)
125 | self._changed()
126 |
127 | def insert(self, i, item):
128 | UserList.insert(self, i, item)
129 | self._changed()
130 |
131 | def pop(self, i=-1):
132 | item = self[i]
133 | del self[i]
134 | return item
135 |
136 | def remove(self, item):
137 | self.__delitem__(self.index(item))
138 |
139 | def reverse(self):
140 | UserList.reverse(self)
141 | self._changed()
142 |
143 | def sort(self, *args, **kwds):
144 | UserList.sort(self, *args, **kwds)
145 | self._changed()
146 |
147 | def extend(self, other):
148 | UserList.extend(self, other)
149 | self._changed()
150 |
151 |
152 | def get_domobj_range(content=[], position=0, direction=Direction.FORWARD, identify_fun=None):
153 | u"""
154 | Get the start and end line number of the dom obj lines from content.
155 |
156 | :content: String to be recognized dom obj
157 | :position: Line number in content
158 | :direction: Search direction
159 | :identify_fun: A identify function to recognize dom obj(Heading, Checkbox) title string.
160 |
161 | :return: Start and end line number for the recognized dom obj.
162 | """
163 | len_cb = len(content)
164 |
165 | if position < 0 or position > len_cb:
166 | return (None, None)
167 |
168 | tmp_line = position
169 | start = None
170 | end = None
171 |
172 | if direction == Direction.FORWARD:
173 | while tmp_line < len_cb:
174 | if identify_fun(content[tmp_line]) is not None:
175 | if start is None:
176 | start = tmp_line
177 | elif end is None:
178 | end = tmp_line - 1
179 | if start is not None and end is not None:
180 | break
181 | tmp_line += 1
182 | else:
183 | while tmp_line >= 0 and tmp_line < len_cb:
184 | if identify_fun(content[tmp_line]) is not None:
185 | if start is None:
186 | start = tmp_line
187 | elif end is None:
188 | end = tmp_line - 1
189 | if start is not None and end is not None:
190 | break
191 | tmp_line -= 1 if start is None else -1
192 |
193 | return (start, end)
194 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/liborgmode/orgdate.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | u"""
3 | OrgDate
4 | ~~~~~~~~~~~~~~~~~~
5 |
6 | This module contains all date/time/timerange representations that exist in
7 | orgmode.
8 |
9 | There exist three different kinds:
10 |
11 | * OrgDate: is similar to a date object in python and it looks like
12 | '2011-09-07 Wed'.
13 |
14 | * OrgDateTime: is similar to a datetime object in python and looks like
15 | '2011-09-07 Wed 10:30'
16 |
17 | * OrgTimeRange: indicates a range of time. It has a start and and end date:
18 | * <2011-09-07 Wed>--<2011-09-08 Fri>
19 | * <2011-09-07 Wed 10:00-13:00>
20 |
21 | All OrgTime oblects can be active or inactive.
22 | """
23 |
24 | import datetime
25 | import re
26 |
27 | from orgmode.py3compat.encode_compatibility import *
28 |
29 | # <2011-09-12 Mon>
30 | _DATE_REGEX = re.compile(r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w>", re.UNICODE)
31 | # [2011-09-12 Mon]
32 | _DATE_PASSIVE_REGEX = re.compile(r"\[(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w\]", re.UNICODE)
33 |
34 | # <2011-09-12 Mon 10:20>
35 | _DATETIME_REGEX = re.compile(
36 | r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d{1,2}):(\d\d)>", re.UNICODE)
37 | # [2011-09-12 Mon 10:20]
38 | _DATETIME_PASSIVE_REGEX = re.compile(
39 | r"\[(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d{1,2}):(\d\d)\]", re.UNICODE)
40 |
41 | # <2011-09-12 Mon>--<2011-09-13 Tue>
42 | _DATERANGE_REGEX = re.compile(
43 | # <2011-09-12 Mon>--
44 | r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w>--"
45 | # <2011-09-13 Tue>
46 | r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w>", re.UNICODE)
47 | # <2011-09-12 Mon 10:00>--<2011-09-12 Mon 11:00>
48 | _DATETIMERANGE_REGEX = re.compile(
49 | # <2011-09-12 Mon 10:00>--
50 | r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d\d):(\d\d)>--"
51 | # <2011-09-12 Mon 11:00>
52 | r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d\d):(\d\d)>", re.UNICODE)
53 | # <2011-09-12 Mon 10:00--12:00>
54 | _DATETIMERANGE_SAME_DAY_REGEX = re.compile(
55 | r"<(\d\d\d\d)-(\d\d)-(\d\d) [A-Z]\w\w (\d\d):(\d\d)-(\d\d):(\d\d)>", re.UNICODE)
56 |
57 |
58 | def get_orgdate(data):
59 | u"""
60 | Parse the given data (can be a string or list). Return an OrgDate if data
61 | contains a string representation of an OrgDate; otherwise return None.
62 |
63 | data can be a string or a list containing strings.
64 | """
65 | # TODO maybe it should be checked just for iterable? Does it affect here if
66 | # in base __getitem__(slice(i,j)) doesn't return a list but userlist...
67 | if isinstance(data, list):
68 | return _findfirst(_text2orgdate, data)
69 | else:
70 | return _text2orgdate(data)
71 | # if no dates found
72 | return None
73 |
74 |
75 | def _findfirst(f, seq):
76 | u"""
77 | Return first item in sequence seq where f(item) == True.
78 |
79 | TODO: this is a general help function and it should be moved somewhere
80 | else; preferably into the standard lib :)
81 | """
82 | for found in (f(item) for item in seq if f(item)):
83 | return found
84 |
85 |
86 | def _text2orgdate(string):
87 | u"""
88 | Transform the given string into an OrgDate.
89 | Return an OrgDate if data contains a string representation of an OrgDate;
90 | otherwise return None.
91 | """
92 | # handle active datetime with same day
93 | result = _DATETIMERANGE_SAME_DAY_REGEX.search(string)
94 | if result:
95 | try:
96 | (syear, smonth, sday, shour, smin, ehour, emin) = \
97 | [int(m) for m in result.groups()]
98 | start = datetime.datetime(syear, smonth, sday, shour, smin)
99 | end = datetime.datetime(syear, smonth, sday, ehour, emin)
100 | return OrgTimeRange(True, start, end)
101 | except BaseException:
102 | return None
103 |
104 | # handle active datetime
105 | result = _DATETIMERANGE_REGEX.search(string)
106 | if result:
107 | try:
108 | tmp = [int(m) for m in result.groups()]
109 | (syear, smonth, sday, shour, smin, eyear, emonth, eday, ehour, emin) = tmp
110 | start = datetime.datetime(syear, smonth, sday, shour, smin)
111 | end = datetime.datetime(eyear, emonth, eday, ehour, emin)
112 | return OrgTimeRange(True, start, end)
113 | except BaseException:
114 | return None
115 |
116 | # handle active datetime
117 | result = _DATERANGE_REGEX.search(string)
118 | if result:
119 | try:
120 | tmp = [int(m) for m in result.groups()]
121 | syear, smonth, sday, eyear, emonth, ehour = tmp
122 | start = datetime.date(syear, smonth, sday)
123 | end = datetime.date(eyear, emonth, ehour)
124 | return OrgTimeRange(True, start, end)
125 | except BaseException:
126 | return None
127 |
128 | # handle active datetime
129 | result = _DATETIME_REGEX.search(string)
130 | if result:
131 | try:
132 | year, month, day, hour, minutes = [int(m) for m in result.groups()]
133 | return OrgDateTime(True, year, month, day, hour, minutes)
134 | except BaseException:
135 | return None
136 |
137 | # handle passive datetime
138 | result = _DATETIME_PASSIVE_REGEX.search(string)
139 | if result:
140 | try:
141 | year, month, day, hour, minutes = [int(m) for m in result.groups()]
142 | return OrgDateTime(False, year, month, day, hour, minutes)
143 | except BaseException:
144 | return None
145 |
146 | # handle passive dates
147 | result = _DATE_PASSIVE_REGEX.search(string)
148 | if result:
149 | try:
150 | year, month, day = [int(m) for m in result.groups()]
151 | return OrgDate(False, year, month, day)
152 | except BaseException:
153 | return None
154 |
155 | # handle active dates
156 | result = _DATE_REGEX.search(string)
157 | if result:
158 | try:
159 | year, month, day = [int(m) for m in result.groups()]
160 | return OrgDate(True, year, month, day)
161 | except BaseException:
162 | return None
163 |
164 |
165 | class OrgDate(datetime.date):
166 | u"""
167 | OrgDate represents a normal date like '2011-08-29 Mon'.
168 |
169 | OrgDates can be active or inactive.
170 |
171 | NOTE: date is immutable. That's why there needs to be __new__().
172 | See: http://docs.python.org/reference/datamodel.html#object.__new__
173 | """
174 | def __init__(self, active, year, month, day):
175 | self.active = active
176 | pass
177 |
178 | def __new__(cls, active, year, month, day):
179 | return datetime.date.__new__(cls, year, month, day)
180 |
181 | def __unicode__(self):
182 | u"""
183 | Return a string representation.
184 | """
185 | if self.active:
186 | return self.strftime(u'<%Y-%m-%d %a>')
187 | else:
188 | return self.strftime(u'[%Y-%m-%d %a]')
189 |
190 | def __str__(self):
191 | return u_encode(self.__unicode__())
192 |
193 | def strftime(self, fmt):
194 | return u_decode(datetime.date.strftime(self, u_encode(fmt)))
195 |
196 |
197 | class OrgDateTime(datetime.datetime):
198 | u"""
199 | OrgDateTime represents a normal date like '2011-08-29 Mon'.
200 |
201 | OrgDateTime can be active or inactive.
202 |
203 | NOTE: date is immutable. That's why there needs to be __new__().
204 | See: http://docs.python.org/reference/datamodel.html#object.__new__
205 | """
206 |
207 | def __init__(self, active, year, month, day, hour, mins):
208 | self.active = active
209 |
210 | def __new__(cls, active, year, month, day, hour, minute):
211 | return datetime.datetime.__new__(cls, year, month, day, hour, minute)
212 |
213 | def __unicode__(self):
214 | u"""
215 | Return a string representation.
216 | """
217 | if self.active:
218 | return self.strftime(u'<%Y-%m-%d %a %H:%M>')
219 | else:
220 | return self.strftime(u'[%Y-%m-%d %a %H:%M]')
221 |
222 | def __str__(self):
223 | return u_encode(self.__unicode__())
224 |
225 | def strftime(self, fmt):
226 | return u_decode(datetime.datetime.strftime(self, u_encode(fmt)))
227 |
228 |
229 | class OrgTimeRange(object):
230 | u"""
231 | OrgTimeRange objects have a start and an end. Start and ent can be date
232 | or datetime. Start and end have to be the same type.
233 |
234 | OrgTimeRange objects look like this:
235 | * <2011-09-07 Wed>--<2011-09-08 Fri>
236 | * <2011-09-07 Wed 20:00>--<2011-09-08 Fri 10:00>
237 | * <2011-09-07 Wed 10:00-13:00>
238 | """
239 |
240 | def __init__(self, active, start, end):
241 | u"""
242 | stat and end must be datetime.date or datetime.datetime (both of the
243 | same type).
244 | """
245 | super(OrgTimeRange, self).__init__()
246 | self.start = start
247 | self.end = end
248 | self.active = active
249 |
250 | def __unicode__(self):
251 | u"""
252 | Return a string representation.
253 | """
254 | # active
255 | if self.active:
256 | # datetime
257 | if isinstance(self.start, datetime.datetime):
258 | # if start and end are on same the day
259 | if self.start.year == self.end.year and\
260 | self.start.month == self.end.month and\
261 | self.start.day == self.end.day:
262 | return u"<%s-%s>" % (
263 | self.start.strftime(u'%Y-%m-%d %a %H:%M'),
264 | self.end.strftime(u'%H:%M'))
265 | else:
266 | return u"<%s>--<%s>" % (
267 | self.start.strftime(u'%Y-%m-%d %a %H:%M'),
268 | self.end.strftime(u'%Y-%m-%d %a %H:%M'))
269 | # date
270 | if isinstance(self.start, datetime.date):
271 | return u"<%s>--<%s>" % (
272 | self.start.strftime(u'%Y-%m-%d %a'),
273 | self.end.strftime(u'%Y-%m-%d %a'))
274 | # inactive
275 | else:
276 | if isinstance(self.start, datetime.datetime):
277 | # if start and end are on same the day
278 | if self.start.year == self.end.year and\
279 | self.start.month == self.end.month and\
280 | self.start.day == self.end.day:
281 | return u"[%s-%s]" % (
282 | self.start.strftime(u'%Y-%m-%d %a %H:%M'),
283 | self.end.strftime(u'%H:%M'))
284 | else:
285 | return u"[%s]--[%s]" % (
286 | self.start.strftime(u'%Y-%m-%d %a %H:%M'),
287 | self.end.strftime(u'%Y-%m-%d %a %H:%M'))
288 | if isinstance(self.start, datetime.date):
289 | return u"[%s]--[%s]" % (
290 | self.start.strftime(u'%Y-%m-%d %a'),
291 | self.end.strftime(u'%Y-%m-%d %a'))
292 |
293 | def __str__(self):
294 | return u_encode(self.__unicode__())
295 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/menu.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import vim
4 |
5 | from orgmode.keybinding import Command, Plug, Keybinding
6 | from orgmode.keybinding import MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT
7 |
8 | from orgmode.py3compat.encode_compatibility import *
9 |
10 | def register_menu(f):
11 | def r(*args, **kwargs):
12 | p = f(*args, **kwargs)
13 | def create(entry):
14 | if isinstance(entry, Submenu) or isinstance(entry, Separator) \
15 | or isinstance(entry, ActionEntry):
16 | entry.create()
17 |
18 | if hasattr(p, u'menu'):
19 | if isinstance(p.menu, list) or isinstance(p.menu, tuple):
20 | for e in p.menu:
21 | create(e)
22 | else:
23 | create(p.menu)
24 | return p
25 | return r
26 |
27 |
28 | def add_cmd_mapping_menu(plugin, name, function, key_mapping, menu_desrc):
29 | u"""A helper function to create a vim command and keybinding and add these
30 | to the menu for a given plugin.
31 |
32 | :plugin: the plugin to operate on.
33 | :name: the name of the vim command (and the name of the Plug)
34 | :function: the actual python function which is called when executing the
35 | vim command.
36 | :key_mapping: the keymapping to execute the command.
37 | :menu_desrc: the text which appears in the menu.
38 | """
39 | cmd = Command(name, function)
40 | keybinding = Keybinding(key_mapping, Plug(name, cmd))
41 |
42 | plugin.commands.append(cmd)
43 | plugin.keybindings.append(keybinding)
44 | plugin.menu + ActionEntry(menu_desrc, keybinding)
45 |
46 |
47 | class Submenu(object):
48 | u""" Submenu entry """
49 |
50 | def __init__(self, name, parent=None):
51 | object.__init__(self)
52 | self.name = name
53 | self.parent = parent
54 | self._children = []
55 |
56 | def __add__(self, entry):
57 | if entry not in self._children:
58 | self._children.append(entry)
59 | entry.parent = self
60 | return entry
61 |
62 | def __sub__(self, entry):
63 | if entry in self._children:
64 | idx = self._children.index(entry)
65 | del self._children[idx]
66 |
67 | @property
68 | def children(self):
69 | return self._children[:]
70 |
71 | def get_menu(self):
72 | n = self.name.replace(u' ', u'\\ ')
73 | if self.parent:
74 | return u'%s.%s' % (self.parent.get_menu(), n)
75 | return n
76 |
77 | def create(self):
78 | for c in self.children:
79 | c.create()
80 |
81 | def __str__(self):
82 | res = self.name
83 | for c in self.children:
84 | res += str(c)
85 | return res
86 |
87 | class Separator(object):
88 | u""" Menu entry for a Separator """
89 |
90 | def __init__(self, parent=None):
91 | object.__init__(self)
92 | self.parent = parent
93 |
94 | def __unicode__(self):
95 | return u'-----'
96 |
97 | def __str__(self):
98 | return u_encode(self.__unicode__())
99 |
100 | def create(self):
101 | if self.parent:
102 | menu = self.parent.get_menu()
103 | vim.command(u_encode(u'menu %s.-%s- :' % (menu, id(self))))
104 |
105 | class ActionEntry(object):
106 | u""" ActionEntry entry """
107 |
108 | def __init__(self, lname, action, rname=None, mode=MODE_NORMAL, parent=None):
109 | u"""
110 | :lname: menu title on the left hand side of the menu entry
111 | :action: could be a vim command sequence or an actual Keybinding
112 | :rname: menu title that appears on the right hand side of the menu
113 | entry. If action is a Keybinding this value ignored and is
114 | taken from the Keybinding
115 | :mode: defines when the menu entry/action is executable
116 | :parent: the parent instance of this object. The only valid parent is Submenu
117 | """
118 | object.__init__(self)
119 | self._lname = lname
120 | self._action = action
121 | self._rname = rname
122 | if mode not in (MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT):
123 | raise ValueError(u'Parameter mode not in MODE_ALL, MODE_NORMAL, MODE_VISUAL, MODE_INSERT')
124 | self._mode = mode
125 | self.parent = parent
126 |
127 | def __str__(self):
128 | return u'%s\t%s' % (self.lname, self.rname)
129 |
130 | @property
131 | def lname(self):
132 | return self._lname.replace(u' ', u'\\ ')
133 |
134 | @property
135 | def action(self):
136 | if isinstance(self._action, Keybinding):
137 | return self._action.action
138 | return self._action
139 |
140 | @property
141 | def rname(self):
142 | if isinstance(self._action, Keybinding):
143 | return self._action.key.replace(u'', u'Tab')
144 | return self._rname
145 |
146 | @property
147 | def mode(self):
148 | if isinstance(self._action, Keybinding):
149 | return self._action.mode
150 | return self._mode
151 |
152 | def create(self):
153 | menucmd = u':%smenu ' % self.mode
154 | menu = u''
155 | cmd = u''
156 |
157 | if self.parent:
158 | menu = self.parent.get_menu()
159 | menu += u'.%s' % self.lname
160 |
161 | if self.rname:
162 | cmd = u'%s %s%s %s' % (menucmd, menu, self.rname, self.action)
163 | else:
164 | cmd = u'%s %s %s' % (menucmd, menu, self.action)
165 |
166 | vim.command(u_encode(cmd))
167 |
168 | # keybindings should be stored in the plugin.keybindings property and be registered by the appropriate keybinding registrar
169 | #if isinstance(self._action, Keybinding):
170 | # self._action.create()
171 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/plugins/Export.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import os
4 | import subprocess
5 |
6 | import vim
7 |
8 | from orgmode._vim import ORGMODE, echoe, echom
9 | from orgmode.menu import Submenu, ActionEntry, add_cmd_mapping_menu
10 | from orgmode.keybinding import Keybinding, Plug, Command
11 | from orgmode import settings
12 |
13 | from orgmode.py3compat.py_py3_string import *
14 |
15 | class Export(object):
16 | u"""
17 | Export a orgmode file using emacs orgmode.
18 |
19 | This is a *very simple* wrapper of the emacs/orgmode export. emacs and
20 | orgmode need to be installed. We simply call emacs with some options to
21 | export the .org.
22 |
23 | TODO: Offer export options in vim. Don't use the menu.
24 | TODO: Maybe use a native implementation.
25 | """
26 |
27 | def __init__(self):
28 | u""" Initialize plugin """
29 | object.__init__(self)
30 | # menu entries this plugin should create
31 | self.menu = ORGMODE.orgmenu + Submenu(u'Export')
32 |
33 | # key bindings for this plugin
34 | # key bindings are also registered through the menu so only additional
35 | # bindings should be put in this variable
36 | self.keybindings = []
37 |
38 | # commands for this plugin
39 | self.commands = []
40 |
41 | @classmethod
42 | def _get_init_script(cls):
43 | init_script = settings.get(u'org_export_init_script', u'')
44 | if init_script:
45 | init_script = os.path.expandvars(os.path.expanduser(init_script))
46 | if os.path.exists(init_script):
47 | return init_script
48 | else:
49 | echoe(u'Unable to find init script %s' % init_script)
50 |
51 | @classmethod
52 | def _export(cls, format_):
53 | """Export current file to format.
54 |
55 | Args:
56 | format_: pdf or html
57 |
58 | Returns:
59 | return code
60 | """
61 | emacsbin = os.path.expandvars(os.path.expanduser(
62 | settings.get(u'org_export_emacs', u'/usr/bin/emacs')))
63 | if not os.path.exists(emacsbin):
64 | echoe(u'Unable to find emacs binary %s' % emacsbin)
65 |
66 | # build the export command
67 | cmd = [
68 | emacsbin,
69 | u'-nw',
70 | u'--batch',
71 | u'--visit=%s' % vim.eval(u'expand("%:p")'),
72 | u'--funcall=%s' % format_
73 | ]
74 | # source init script as well
75 | init_script = cls._get_init_script()
76 | if init_script:
77 | cmd.extend(['--script', init_script])
78 |
79 | # export
80 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
81 | p.wait()
82 |
83 | if p.returncode != 0 or settings.get(u'org_export_verbose') == 1:
84 | echom('\n'.join(map(lambda x: x.decode(), p.communicate())))
85 | return p.returncode
86 |
87 | @classmethod
88 | def topdf(cls):
89 | u"""Export the current buffer as pdf using emacs orgmode."""
90 | ret = cls._export(u'org-latex-export-to-pdf')
91 | if ret != 0:
92 | echoe(u'PDF export failed.')
93 | else:
94 | echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'pdf'))
95 |
96 | @classmethod
97 | def tobeamer(cls):
98 | u"""Export the current buffer as beamer pdf using emacs orgmode."""
99 | ret = cls._export(u'org-beamer-export-to-pdf')
100 | if ret != 0:
101 | echoe(u'PDF export failed.')
102 | else:
103 | echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'pdf'))
104 |
105 | @classmethod
106 | def tohtml(cls):
107 | u"""Export the current buffer as html using emacs orgmode."""
108 | ret = cls._export(u'org-html-export-to-html')
109 | if ret != 0:
110 | echoe(u'HTML export failed.')
111 | else:
112 | echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'html'))
113 |
114 | @classmethod
115 | def tolatex(cls):
116 | u"""Export the current buffer as latex using emacs orgmode."""
117 | ret = cls._export(u'org-latex-export-to-latex')
118 | if ret != 0:
119 | echoe(u'latex export failed.')
120 | else:
121 | echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'tex'))
122 |
123 | @classmethod
124 | def tomarkdown(cls):
125 | u"""Export the current buffer as markdown using emacs orgmode."""
126 | ret = cls._export(u'org-md-export-to-markdown')
127 | if ret != 0:
128 | echoe('Markdown export failed. Make sure org-md-export-to-markdown is loaded in emacs, see the manual for details.')
129 | else:
130 | echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'md'))
131 |
132 | def register(self):
133 | u"""Registration and keybindings."""
134 |
135 | # path to emacs executable
136 | settings.set(u'org_export_emacs', u'/usr/bin/emacs')
137 | # verbose output for export
138 | settings.set(u'org_export_verbose', 0)
139 | # allow the user to define an initialization script
140 | settings.set(u'org_export_init_script', u'')
141 |
142 | # to PDF
143 | add_cmd_mapping_menu(
144 | self,
145 | name=u'OrgExportToPDF',
146 | function=u':%s ORGMODE.plugins[u"Export"].topdf()' % VIM_PY_CALL,
147 | key_mapping=u'ep',
148 | menu_desrc=u'To PDF (via Emacs)'
149 | )
150 | # to Beamer PDF
151 | add_cmd_mapping_menu(
152 | self,
153 | name=u'OrgExportToBeamerPDF',
154 | function=u':%s ORGMODE.plugins[u"Export"].tobeamer()' % VIM_PY_CALL,
155 | key_mapping=u'eb',
156 | menu_desrc=u'To Beamer PDF (via Emacs)'
157 | )
158 | # to latex
159 | add_cmd_mapping_menu(
160 | self,
161 | name=u'OrgExportToLaTeX',
162 | function=u':%s ORGMODE.plugins[u"Export"].tolatex()' % VIM_PY_CALL,
163 | key_mapping=u'el',
164 | menu_desrc=u'To LaTeX (via Emacs)'
165 | )
166 | # to HTML
167 | add_cmd_mapping_menu(
168 | self,
169 | name=u'OrgExportToHTML',
170 | function=u':%s ORGMODE.plugins[u"Export"].tohtml()' % VIM_PY_CALL,
171 | key_mapping=u'eh',
172 | menu_desrc=u'To HTML (via Emacs)'
173 | )
174 | # to Markdown
175 | add_cmd_mapping_menu(
176 | self,
177 | name=u'OrgExportToMarkdown',
178 | function=u':%s ORGMODE.plugins[u"Export"].tomarkdown()' % VIM_PY_CALL,
179 | key_mapping=u'em',
180 | menu_desrc=u'To Markdown (via Emacs)'
181 | )
182 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/plugins/Hyperlinks.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import re
4 |
5 | import vim
6 |
7 | from orgmode._vim import echom, ORGMODE, realign_tags
8 | from orgmode.menu import Submenu, Separator, ActionEntry
9 | from orgmode.keybinding import Keybinding, Plug, Command
10 |
11 | from orgmode.py3compat.encode_compatibility import *
12 | from orgmode.py3compat.py_py3_string import *
13 |
14 | class Hyperlinks(object):
15 | u""" Hyperlinks plugin """
16 |
17 | def __init__(self):
18 | u""" Initialize plugin """
19 | object.__init__(self)
20 | # menu entries this plugin should create
21 | self.menu = ORGMODE.orgmenu + Submenu(u'Hyperlinks')
22 |
23 | # key bindings for this plugin
24 | # key bindings are also registered through the menu so only additional
25 | # bindings should be put in this variable
26 | self.keybindings = []
27 |
28 | # commands for this plugin
29 | self.commands = []
30 |
31 | uri_match = re.compile(
32 | r'^\[{2}(?P[^][]*)(\]\[(?P[^][]*))?\]{2}')
33 |
34 | @classmethod
35 | def _get_link(cls, cursor=None):
36 | u"""
37 | Get the link the cursor is on and return it's URI and description
38 |
39 | :cursor: None or (Line, Column)
40 | :returns: None if no link was found, otherwise {uri:URI,
41 | description:DESCRIPTION, line:LINE, start:START, end:END}
42 | or uri and description could be None if not set
43 | """
44 | cursor = cursor if cursor else vim.current.window.cursor
45 | line = u_decode(vim.current.buffer[cursor[0] - 1])
46 |
47 | # if the cursor is on the last bracket, it's not recognized as a hyperlink
48 | start = line.rfind(u'[[', 0, cursor[1])
49 | if start == -1:
50 | start = line.rfind(u'[[', 0, cursor[1] + 2)
51 | end = line.find(u']]', cursor[1])
52 | if end == -1:
53 | end = line.find(u']]', cursor[1] - 1)
54 |
55 | # extract link
56 | if start != -1 and end != -1:
57 | end += 2
58 | match = Hyperlinks.uri_match.match(line[start:end])
59 |
60 | res = {
61 | u'line': line,
62 | u'start': start,
63 | u'end': end,
64 | u'uri': None,
65 | u'description': None}
66 | if match:
67 | res.update(match.groupdict())
68 | # reverse character escaping(partly done due to matching)
69 | res[u'uri'] = res[u'uri'].replace(u'\\\\', u'\\')
70 | return res
71 |
72 | @classmethod
73 | def follow(cls, action=u'openLink', visual=u''):
74 | u""" Follow hyperlink. If called on a regular string UTL determines the
75 | outcome. Normally a file with that name will be opened.
76 |
77 | :action: "copy" if the link should be copied to clipboard, otherwise
78 | the link will be opened
79 | :visual: "visual" if Universal Text Linking should be triggered in
80 | visual mode
81 |
82 | :returns: URI or None
83 | """
84 | if not int(vim.eval(u'exists(":Utl")')):
85 | echom(u'Universal Text Linking plugin not installed, unable to proceed.')
86 | return
87 |
88 | action = u'copyLink' \
89 | if (action and action.startswith(u'copy')) \
90 | else u'openLink'
91 | visual = u'visual' if visual and visual.startswith(u'visual') else u''
92 |
93 | link = Hyperlinks._get_link()
94 |
95 | if link and link[u'uri'] is not None:
96 | # call UTL with the URI
97 | vim.command(u_encode(u'Utl %s %s %s' % (action, visual, link[u'uri'])))
98 | return link[u'uri']
99 | else:
100 | # call UTL and let it decide what to do
101 | vim.command(u_encode(u'Utl %s %s' % (action, visual)))
102 |
103 | @classmethod
104 | @realign_tags
105 | def insert(cls, uri=None, description=None):
106 | u""" Inserts a hyperlink. If no arguments are provided, an interactive
107 | query will be started.
108 |
109 | :uri: The URI that will be opened
110 | :description: An optional description that will be displayed instead of
111 | the URI
112 |
113 | :returns: (URI, description)
114 | """
115 | link = Hyperlinks._get_link()
116 | if link:
117 | if uri is None and link[u'uri'] is not None:
118 | uri = link[u'uri']
119 | if description is None and link[u'description'] is not None:
120 | description = link[u'description']
121 |
122 | if uri is None:
123 | uri = vim.eval(u'input("Link: ", "", "file")')
124 | elif link:
125 | uri = vim.eval(u'input("Link: ", "%s", "file")' % link[u'uri'])
126 | if uri is None:
127 | return
128 | else:
129 | uri = u_decode(uri)
130 |
131 | # character escaping
132 | uri = uri.replace(u'\\', u'\\\\\\\\')
133 | uri = uri.replace(u' ', u'\\ ')
134 |
135 | if description is None:
136 | description = u_decode(vim.eval(u'input("Description: ")'))
137 | elif link:
138 | description = vim.eval(
139 | u'input("Description: ", "%s")' %
140 | u_decode(link[u'description']))
141 | if description is None:
142 | return
143 |
144 | cursor = vim.current.window.cursor
145 | cl = u_decode(vim.current.buffer[cursor[0] - 1])
146 | head = cl[:cursor[1] + 1] if not link else cl[:link[u'start']]
147 | tail = cl[cursor[1] + 1:] if not link else cl[link[u'end']:]
148 |
149 | separator = u''
150 | if description:
151 | separator = u']['
152 |
153 | if uri or description:
154 | vim.current.buffer[cursor[0] - 1] = \
155 | u_encode(u''.join((head, u'[[%s%s%s]]' % (uri, separator, description), tail)))
156 | elif link:
157 | vim.current.buffer[cursor[0] - 1] = \
158 | u_encode(u''.join((head, tail)))
159 |
160 | def register(self):
161 | u"""
162 | Registration of plugin. Key bindings and other initialization should be done.
163 | """
164 | cmd = Command(
165 | u'OrgHyperlinkFollow',
166 | u'%s ORGMODE.plugins[u"Hyperlinks"].follow()' % VIM_PY_CALL)
167 | self.commands.append(cmd)
168 | self.keybindings.append(
169 | Keybinding(u'gl', Plug(u'OrgHyperlinkFollow', self.commands[-1])))
170 | self.menu + ActionEntry(u'&Follow Link', self.keybindings[-1])
171 |
172 | cmd = Command(
173 | u'OrgHyperlinkCopy',
174 | u'%s ORGMODE.plugins[u"Hyperlinks"].follow(action=u"copy")' % VIM_PY_CALL)
175 | self.commands.append(cmd)
176 | self.keybindings.append(
177 | Keybinding(u'gyl', Plug(u'OrgHyperlinkCopy', self.commands[-1])))
178 | self.menu + ActionEntry(u'&Copy Link', self.keybindings[-1])
179 |
180 | cmd = Command(
181 | u'OrgHyperlinkInsert',
182 | u'%s ORGMODE.plugins[u"Hyperlinks"].insert()' % VIM_PY_CALL,
183 | arguments=u'*')
184 | self.commands.append(cmd)
185 | self.keybindings.append(
186 | Keybinding(u'gil', Plug(u'OrgHyperlinkInsert', self.commands[-1])))
187 | self.menu + ActionEntry(u'&Insert Link', self.keybindings[-1])
188 |
189 | self.menu + Separator()
190 |
191 | # find next link
192 | cmd = Command(
193 | u'OrgHyperlinkNextLink',
194 | u":if search('\\[\\{2}\\zs[^][]*\\(\\]\\[[^][]*\\)\\?\\ze\\]\\{2}', 's') == 0 | echo 'No further link found.' | endif")
195 | self.commands.append(cmd)
196 | self.keybindings.append(
197 | Keybinding(u'gn', Plug(u'OrgHyperlinkNextLink', self.commands[-1])))
198 | self.menu + ActionEntry(u'&Next Link', self.keybindings[-1])
199 |
200 | # find previous link
201 | cmd = Command(
202 | u'OrgHyperlinkPreviousLink',
203 | u":if search('\\[\\{2}\\zs[^][]*\\(\\]\\[[^][]*\\)\\?\\ze\\]\\{2}', 'bs') == 0 | echo 'No further link found.' | endif")
204 | self.commands.append(cmd)
205 | self.keybindings.append(
206 | Keybinding(u'go', Plug(u'OrgHyperlinkPreviousLink', self.commands[-1])))
207 | self.menu + ActionEntry(u'&Previous Link', self.keybindings[-1])
208 |
209 | self.menu + Separator()
210 |
211 | # Descriptive Links
212 | cmd = Command(u'OrgHyperlinkDescriptiveLinks', u':setlocal cole=2')
213 | self.commands.append(cmd)
214 | self.menu + ActionEntry(u'&Descriptive Links', self.commands[-1])
215 |
216 | # Literal Links
217 | cmd = Command(u'OrgHyperlinkLiteralLinks', u':setlocal cole=0')
218 | self.commands.append(cmd)
219 | self.menu + ActionEntry(u'&Literal Links', self.commands[-1])
220 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/plugins/LoggingWork.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import vim
4 |
5 | from orgmode._vim import echo, echom, echoe, ORGMODE, apply_count, repeat
6 | from orgmode.menu import Submenu, Separator, ActionEntry
7 | from orgmode.keybinding import Keybinding, Plug, Command
8 |
9 | from orgmode.py3compat.py_py3_string import *
10 |
11 | class LoggingWork(object):
12 | u""" LoggingWork plugin """
13 |
14 | def __init__(self):
15 | u""" Initialize plugin """
16 | object.__init__(self)
17 | # menu entries this plugin should create
18 | self.menu = ORGMODE.orgmenu + Submenu(u'&Logging work')
19 |
20 | # key bindings for this plugin
21 | # key bindings are also registered through the menu so only additional
22 | # bindings should be put in this variable
23 | self.keybindings = []
24 |
25 | # commands for this plugin
26 | self.commands = []
27 |
28 | @classmethod
29 | def action(cls):
30 | u""" Some kind of action
31 |
32 | :returns: TODO
33 | """
34 | pass
35 |
36 | def register(self):
37 | u"""
38 | Registration of plugin. Key bindings and other initialization should be done.
39 | """
40 | # an Action menu entry which binds "keybinding" to action ":action"
41 | self.commands.append(Command(u'OrgLoggingRecordDoneTime', u'%s ORGMODE.plugins[u"LoggingWork"].action()' % VIM_PY_CALL))
42 | self.menu + ActionEntry(u'&Record DONE time', self.commands[-1])
43 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/plugins/Misc.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import vim
4 |
5 | from orgmode._vim import ORGMODE, apply_count
6 | from orgmode.menu import Submenu
7 | from orgmode.keybinding import Keybinding, Plug, MODE_VISUAL, MODE_OPERATOR
8 |
9 | from orgmode.py3compat.encode_compatibility import *
10 | from orgmode.py3compat.py_py3_string import *
11 |
12 | class Misc(object):
13 | u""" Miscellaneous functionality """
14 |
15 | def __init__(self):
16 | u""" Initialize plugin """
17 | object.__init__(self)
18 | # menu entries this plugin should create
19 | self.menu = ORGMODE.orgmenu + Submenu(u'Misc')
20 |
21 | # key bindings for this plugin
22 | # key bindings are also registered through the menu so only additional
23 | # bindings should be put in this variable
24 | self.keybindings = []
25 |
26 | @classmethod
27 | def jump_to_first_character(cls):
28 | heading = ORGMODE.get_document().current_heading()
29 | if not heading or heading.start_vim != vim.current.window.cursor[0]:
30 | vim.eval(u_encode(u'feedkeys("^", "n")'))
31 | return
32 |
33 | vim.current.window.cursor = (vim.current.window.cursor[0], heading.level + 1)
34 |
35 | @classmethod
36 | def edit_at_first_character(cls):
37 | heading = ORGMODE.get_document().current_heading()
38 | if not heading or heading.start_vim != vim.current.window.cursor[0]:
39 | vim.eval(u_encode(u'feedkeys("I", "n")'))
40 | return
41 |
42 | vim.current.window.cursor = (vim.current.window.cursor[0], heading.level + 1)
43 | vim.command(u_encode(u'startinsert'))
44 |
45 | # @repeat
46 | @classmethod
47 | @apply_count
48 | def i_heading(cls, mode=u'visual', selection=u'inner', skip_children=False):
49 | u"""
50 | inner heading text object
51 | """
52 | heading = ORGMODE.get_document().current_heading()
53 | if heading:
54 | if selection != u'inner':
55 | heading = heading if not heading.parent else heading.parent
56 |
57 | line_start, col_start = [int(i) for i in vim.eval(u_encode(u'getpos("\'<")'))[1:3]]
58 | line_end, col_end = [int(i) for i in vim.eval(u_encode(u'getpos("\'>")'))[1:3]]
59 |
60 | if mode != u'visual':
61 | line_start = vim.current.window.cursor[0]
62 | line_end = line_start
63 |
64 | start = line_start
65 | end = line_end
66 | move_one_character_back = u'' if mode == u'visual' else u'h'
67 |
68 | if heading.start_vim < line_start:
69 | start = heading.start_vim
70 | if heading.end_vim > line_end and not skip_children:
71 | end = heading.end_vim
72 | elif heading.end_of_last_child_vim > line_end and skip_children:
73 | end = heading.end_of_last_child_vim
74 |
75 | if mode != u'visual' and not vim.current.buffer[end - 1]:
76 | end -= 1
77 | move_one_character_back = u''
78 |
79 | swap_cursor = u'o' if vim.current.window.cursor[0] == line_start else u''
80 |
81 | if selection == u'inner' and vim.current.window.cursor[0] != line_start:
82 | h = ORGMODE.get_document().current_heading()
83 | if h:
84 | heading = h
85 |
86 | visualmode = u_decode(vim.eval(u'visualmode()')) if mode == u'visual' else u'v'
87 |
88 | if line_start == start and line_start != heading.start_vim:
89 | if col_start in (0, 1):
90 | vim.command(u_encode(u'normal! %dgg0%s%dgg$%s%s' % (start, visualmode, end, move_one_character_back, swap_cursor)))
91 | else:
92 | vim.command(u_encode(u'normal! %dgg0%dl%s%dgg$%s%s' % (start, col_start - 1, visualmode, end, move_one_character_back, swap_cursor)))
93 | else:
94 | vim.command(u_encode(u'normal! %dgg0%dl%s%dgg$%s%s' % (start, heading.level + 1, visualmode, end, move_one_character_back, swap_cursor)))
95 |
96 | if selection == u'inner':
97 | if mode == u'visual':
98 | return u'OrgInnerHeadingVisual' if not skip_children else u'OrgInnerTreeVisual'
99 | else:
100 | return u'OrgInnerHeadingOperator' if not skip_children else u'OrgInnerTreeOperator'
101 | else:
102 | if mode == u'visual':
103 | return u'OrgOuterHeadingVisual' if not skip_children else u'OrgOuterTreeVisual'
104 | else:
105 | return u'OrgOuterHeadingOperator' if not skip_children else u'OrgOuterTreeOperator'
106 | elif mode == u'visual':
107 | vim.command(u_encode(u'normal! gv'))
108 |
109 | # @repeat
110 | @classmethod
111 | @apply_count
112 | def a_heading(cls, selection=u'inner', skip_children=False):
113 | u"""
114 | a heading text object
115 | """
116 | heading = ORGMODE.get_document().current_heading()
117 | if heading:
118 | if selection != u'inner':
119 | heading = heading if not heading.parent else heading.parent
120 |
121 | line_start, col_start = [int(i) for i in vim.eval(u_encode(u'getpos("\'<")'))[1:3]]
122 | line_end, col_end = [int(i) for i in vim.eval(u_encode(u'getpos("\'>")'))[1:3]]
123 |
124 | start = line_start
125 | end = line_end
126 |
127 | if heading.start_vim < line_start:
128 | start = heading.start_vim
129 | if heading.end_vim > line_end and not skip_children:
130 | end = heading.end_vim
131 | elif heading.end_of_last_child_vim > line_end and skip_children:
132 | end = heading.end_of_last_child_vim
133 |
134 | swap_cursor = u'o' if vim.current.window.cursor[0] == line_start else u''
135 |
136 | vim.command(u_encode(u'normal! %dgg%s%dgg$%s' % (start, vim.eval(u_encode(u'visualmode()')), end, swap_cursor)))
137 | if selection == u'inner':
138 | return u'OrgAInnerHeadingVisual' if not skip_children else u'OrgAInnerTreeVisual'
139 | else:
140 | return u'OrgAOuterHeadingVisual' if not skip_children else u'OrgAOuterTreeVisual'
141 | else:
142 | vim.command(u_encode(u'normal! gv'))
143 |
144 | def register(self):
145 | u"""
146 | Registration of plugin. Key bindings and other initialization should be done.
147 | """
148 | self.keybindings.append(Keybinding(u'^',
149 | Plug(u'OrgJumpToFirstCharacter', u'%s ORGMODE.plugins[u"Misc"].jump_to_first_character()' % VIM_PY_CALL)))
150 | self.keybindings.append(Keybinding(u'I',
151 | Plug(u'OrgEditAtFirstCharacter', u'%s ORGMODE.plugins[u"Misc"].edit_at_first_character()' % VIM_PY_CALL)))
152 |
153 | self.keybindings.append(Keybinding(u'ih', Plug(u'OrgInnerHeadingVisual', u':%s ORGMODE.plugins[u"Misc"].i_heading()' % VIM_PY_CALL, mode=MODE_VISUAL)))
154 | self.keybindings.append(Keybinding(u'ah', Plug(u'OrgAInnerHeadingVisual', u':%s ORGMODE.plugins[u"Misc"].a_heading()' % VIM_PY_CALL, mode=MODE_VISUAL)))
155 | self.keybindings.append(Keybinding(u'Oh', Plug(u'OrgOuterHeadingVisual', u':%s ORGMODE.plugins[u"Misc"].i_heading(selection=u"outer")' % VIM_PY_CALL, mode=MODE_VISUAL)))
156 | self.keybindings.append(Keybinding(u'OH', Plug(u'OrgAOuterHeadingVisual', u':%s ORGMODE.plugins[u"Misc"].a_heading(selection=u"outer")' % VIM_PY_CALL, mode=MODE_VISUAL)))
157 |
158 | self.keybindings.append(Keybinding(u'ih', Plug(u'OrgInnerHeadingOperator', u':%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator")' % VIM_PY_CALL, mode=MODE_OPERATOR)))
159 | self.keybindings.append(Keybinding(u'ah', u':normal Vah', mode=MODE_OPERATOR))
160 | self.keybindings.append(Keybinding(u'Oh', Plug(u'OrgOuterHeadingOperator', ':%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator", selection=u"outer")' % VIM_PY_CALL, mode=MODE_OPERATOR)))
161 | self.keybindings.append(Keybinding(u'OH', u':normal VOH', mode=MODE_OPERATOR))
162 |
163 | self.keybindings.append(Keybinding(u'ir', Plug(u'OrgInnerTreeVisual', u':%s ORGMODE.plugins[u"Misc"].i_heading(skip_children=True)' % VIM_PY_CALL, mode=MODE_VISUAL)))
164 | self.keybindings.append(Keybinding(u'ar', Plug(u'OrgAInnerTreeVisual', u':%s ORGMODE.plugins[u"Misc"].a_heading(skip_children=True)' % VIM_PY_CALL, mode=MODE_VISUAL)))
165 | self.keybindings.append(Keybinding(u'Or', Plug(u'OrgOuterTreeVisual', u'<:%s ORGMODE.plugins[u"Misc"].i_heading(selection=u"outer", skip_children=True)' % VIM_PY_CALL, mode=MODE_VISUAL)))
166 | self.keybindings.append(Keybinding(u'OR', Plug(u'OrgAOuterTreeVisual', u':%s ORGMODE.plugins[u"Misc"].a_heading(selection=u"outer", skip_children=True)' % VIM_PY_CALL, mode=MODE_VISUAL)))
167 |
168 | self.keybindings.append(Keybinding(u'ir', Plug(u'OrgInnerTreeOperator', u':%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator", skip_children=True)' % VIM_PY_CALL, mode=MODE_OPERATOR)))
169 | self.keybindings.append(Keybinding(u'ar', u':normal Var', mode=MODE_OPERATOR))
170 | self.keybindings.append(Keybinding(u'Or', Plug(u'OrgOuterTreeOperator', u':%s ORGMODE.plugins[u"Misc"].i_heading(mode=u"operator", selection=u"outer", skip_children=True)' % VIM_PY_CALL, mode=MODE_OPERATOR)))
171 | self.keybindings.append(Keybinding(u'OR', u':normal VOR', mode=MODE_OPERATOR))
172 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/plugins/ShowHide.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import vim
4 |
5 | from orgmode.liborgmode.headings import Heading
6 | from orgmode._vim import ORGMODE, apply_count
7 | from orgmode import settings
8 | from orgmode.menu import Submenu, ActionEntry
9 | from orgmode.keybinding import Keybinding, Plug, MODE_NORMAL
10 |
11 | from orgmode.py3compat.encode_compatibility import *
12 | from orgmode.py3compat.xrange_compatibility import *
13 | from orgmode.py3compat.py_py3_string import *
14 |
15 | class ShowHide(object):
16 | u""" Show Hide plugin """
17 |
18 | def __init__(self):
19 | u""" Initialize plugin """
20 | object.__init__(self)
21 | # menu entries this plugin should create
22 | self.menu = ORGMODE.orgmenu + Submenu(u'&Show Hide')
23 |
24 | # key bindings for this plugin
25 | # key bindings are also registered through the menu so only additional
26 | # bindings should be put in this variable
27 | self.keybindings = []
28 |
29 | @classmethod
30 | def _fold_depth(cls, h):
31 | """ Find the deepest level of open folds
32 |
33 | :h: Heading
34 | :returns: Tuple (int - level of open folds, boolean - found fold) or None if h is not a Heading
35 | """
36 | if not isinstance(h, Heading):
37 | return
38 |
39 | if int(vim.eval(u_encode(u'foldclosed(%d)' % h.start_vim))) != -1:
40 | return (h.number_of_parents, True)
41 |
42 | res = [h.number_of_parents + 1]
43 | found = False
44 | for c in h.children:
45 | d, f = cls._fold_depth(c)
46 | res.append(d)
47 | found |= f
48 |
49 | return (max(res), found)
50 |
51 | @classmethod
52 | @apply_count
53 | def toggle_folding(cls, reverse=False):
54 | u""" Toggle folding similar to the way orgmode does
55 |
56 | This is just a convenience function, don't hesitate to use the z*
57 | keybindings vim offers to deal with folding!
58 |
59 | :reverse: If False open folding by one level otherwise close it by one.
60 | """
61 | d = ORGMODE.get_document()
62 | heading = d.current_heading()
63 | if not heading:
64 | vim.eval(u_encode(u'feedkeys("", "n")'))
65 | return
66 |
67 | cursor = vim.current.window.cursor[:]
68 |
69 | if int(vim.eval(u_encode(u'foldclosed(%d)' % heading.start_vim))) != -1:
70 | if not reverse:
71 | # open closed fold
72 | p = heading.number_of_parents
73 | if not p:
74 | p = heading.level
75 | vim.command(u_encode(u'normal! %dzo' % p))
76 | else:
77 | # reverse folding opens all folds under the cursor
78 | vim.command(u_encode(u'%d,%dfoldopen!' % (heading.start_vim, heading.end_of_last_child_vim)))
79 | vim.current.window.cursor = cursor
80 | return heading
81 |
82 | def open_fold(h):
83 | if h.number_of_parents <= open_depth:
84 | vim.command(u_encode(u'normal! %dgg%dzo' % (h.start_vim, open_depth)))
85 | for c in h.children:
86 | open_fold(c)
87 |
88 | def close_fold(h):
89 | for c in h.children:
90 | close_fold(c)
91 | if h.number_of_parents >= open_depth - 1 and \
92 | int(vim.eval(u_encode(u'foldclosed(%d)' % h.start_vim))) == -1:
93 | vim.command(u_encode(u'normal! %dggzc' % (h.start_vim, )))
94 |
95 | # find deepest fold
96 | open_depth, found_fold = cls._fold_depth(heading)
97 |
98 | if not reverse:
99 | # recursively open folds
100 | if found_fold:
101 | for child in heading.children:
102 | open_fold(child)
103 | else:
104 | vim.command(u_encode(u'%d,%dfoldclose!' % (heading.start_vim, heading.end_of_last_child_vim)))
105 |
106 | if heading.number_of_parents:
107 | # restore cursor position, it might have been changed by open_fold
108 | vim.current.window.cursor = cursor
109 |
110 | p = heading.number_of_parents
111 | if not p:
112 | p = heading.level
113 | # reopen fold again because the former closing of the fold closed all levels, including parents!
114 | vim.command(u_encode(u'normal! %dzo' % (p, )))
115 | else:
116 | # close the last level of folds
117 | close_fold(heading)
118 |
119 | # restore cursor position
120 | vim.current.window.cursor = cursor
121 | return heading
122 |
123 | @classmethod
124 | @apply_count
125 | def global_toggle_folding(cls, reverse=False):
126 | """ Toggle folding globally
127 |
128 | :reverse: If False open folding by one level otherwise close it by one.
129 | """
130 | d = ORGMODE.get_document()
131 | if reverse:
132 | foldlevel = int(vim.eval(u_encode(u'&foldlevel')))
133 | if foldlevel == 0:
134 | # open all folds because the user tries to close folds beyond 0
135 | vim.eval(u_encode(u'feedkeys("zR", "n")'))
136 | else:
137 | # vim can reduce the foldlevel on its own
138 | vim.eval(u_encode(u'feedkeys("zm", "n")'))
139 | else:
140 | found = False
141 | for h in d.headings:
142 | res = cls._fold_depth(h)
143 | if res:
144 | found = res[1]
145 | if found:
146 | break
147 | if not found:
148 | # no fold found and the user tries to advance the fold level
149 | # beyond maximum so close everything
150 | vim.eval(u_encode(u'feedkeys("zM", "n")'))
151 | else:
152 | # fold found, vim can increase the foldlevel on its own
153 | vim.eval(u_encode(u'feedkeys("zr", "n")'))
154 |
155 | return d
156 |
157 | def register(self):
158 | u"""
159 | Registration of plugin. Key bindings and other initialization should be done.
160 | """
161 | # register plug
162 |
163 | self.keybindings.append(Keybinding(u'',
164 | Plug(u'OrgToggleFoldingNormal', u'%s ORGMODE.plugins[u"ShowHide"].toggle_folding()' % VIM_PY_CALL)))
165 | self.menu + ActionEntry(u'&Cycle Visibility', self.keybindings[-1])
166 |
167 | self.keybindings.append(Keybinding(u'',
168 | Plug(u'OrgToggleFoldingReverse', u'%s ORGMODE.plugins[u"ShowHide"].toggle_folding(reverse=True)' % VIM_PY_CALL)))
169 | self.menu + ActionEntry(u'Cycle Visibility &Reverse', self.keybindings[-1])
170 |
171 | self.keybindings.append(Keybinding(u'.',
172 | Plug(u'OrgGlobalToggleFoldingNormal', u'%s ORGMODE.plugins[u"ShowHide"].global_toggle_folding()' % VIM_PY_CALL)))
173 | self.menu + ActionEntry(u'Cycle Visibility &Globally', self.keybindings[-1])
174 |
175 | self.keybindings.append(Keybinding(u',',
176 | Plug(u'OrgGlobalToggleFoldingReverse',
177 | u'%s ORGMODE.plugins[u"ShowHide"].global_toggle_folding(reverse=True)' % VIM_PY_CALL)))
178 | self.menu + ActionEntry(u'Cycle Visibility Reverse G&lobally', self.keybindings[-1])
179 |
180 | for i in range(0, 10):
181 | self.keybindings.append(Keybinding(u'%d' % (i, ), u'zM:set fdl=%d' % i, mode=MODE_NORMAL))
182 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/plugins/TagsProperties.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import vim
4 |
5 | from orgmode._vim import ORGMODE, repeat
6 | from orgmode.menu import Submenu, ActionEntry
7 | from orgmode.keybinding import Keybinding, Plug, Command
8 | from orgmode import settings
9 |
10 | from orgmode.py3compat.encode_compatibility import *
11 | from orgmode.py3compat.py_py3_string import *
12 |
13 | class TagsProperties(object):
14 | u""" TagsProperties plugin """
15 |
16 | def __init__(self):
17 | u""" Initialize plugin """
18 | object.__init__(self)
19 | # menu entries this plugin should create
20 | self.menu = ORGMODE.orgmenu + Submenu(u'&TAGS and Properties')
21 |
22 | # key bindings for this plugin
23 | # key bindings are also registered through the menu so only additional
24 | # bindings should be put in this variable
25 | self.keybindings = []
26 |
27 | # commands for this plugin
28 | self.commands = []
29 |
30 | @classmethod
31 | def complete_tags(cls):
32 | u""" build a list of tags and store it in variable b:org_tag_completion
33 | """
34 | d = ORGMODE.get_document()
35 | heading = d.current_heading()
36 | if not heading:
37 | return
38 |
39 | leading_portion = u_decode(vim.eval(u'a:ArgLead'))
40 | cursor = int(vim.eval(u'a:CursorPos'))
41 |
42 | # extract currently completed tag
43 | idx_orig = leading_portion.rfind(u':', 0, cursor)
44 | if idx_orig == -1:
45 | idx = 0
46 | else:
47 | idx = idx_orig
48 |
49 | current_tag = leading_portion[idx: cursor].lstrip(u':')
50 | head = leading_portion[:idx + 1]
51 | if idx_orig == -1:
52 | head = u''
53 | tail = leading_portion[cursor:]
54 |
55 | # extract all tags of the current file
56 | all_tags = set()
57 | for h in d.all_headings():
58 | for t in h.tags:
59 | all_tags.add(t)
60 |
61 | ignorecase = bool(int(settings.get(u'org_tag_completion_ignorecase', int(vim.eval(u'&ignorecase')))))
62 | possible_tags = []
63 | # TODO current tags never used...
64 | current_tags = heading.tags
65 | for t in all_tags:
66 | if ignorecase:
67 | if t.lower().startswith(current_tag.lower()):
68 | possible_tags.append(t)
69 | elif t.startswith(current_tag):
70 | possible_tags.append(t)
71 |
72 | 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])))
73 |
74 | @classmethod
75 | @repeat
76 | def set_tags(cls):
77 | u""" Set tags for current heading
78 | """
79 | d = ORGMODE.get_document()
80 | heading = d.current_heading()
81 | if not heading:
82 | return
83 |
84 | # retrieve tags
85 | res = None
86 | if heading.tags:
87 | res = vim.eval(u'input("Tags: ", ":%s:", "customlist,Org_complete_tags")' % u':'.join(heading.tags))
88 | else:
89 | res = vim.eval(u'input("Tags: ", "", "customlist,Org_complete_tags")')
90 |
91 | if res is None:
92 | # user pressed abort any further processing
93 | return
94 |
95 | # remove empty tags
96 | heading.tags = [x for x in u_decode(res).strip().strip(u':').split(u':') if x.strip() != u'']
97 |
98 | d.write()
99 |
100 | return u'OrgSetTags'
101 |
102 | @classmethod
103 | def find_tags(cls):
104 | """ Find tags in current file
105 | """
106 | tags = vim.eval(u'input("Find Tags: ", "", "customlist,Org_complete_tags")')
107 | if tags is None:
108 | # user pressed abort any further processing
109 | return
110 |
111 | tags = [x for x in u_decode(tags).strip().strip(u':').split(u':') if x.strip() != u'']
112 | if tags:
113 | searchstring = u'\\('
114 | first = True
115 | for t1 in tags:
116 | if first:
117 | first = False
118 | searchstring += u'%s' % t1
119 | else:
120 | searchstring += u'\\|%s' % t1
121 |
122 | for t2 in tags:
123 | if t1 == t2:
124 | continue
125 | searchstring += u'\\(:[a-zA-Z:]*\\)\\?:%s' % t2
126 | searchstring += u'\\)'
127 |
128 | vim.command(u'/\\zs:%s:\\ze' % searchstring)
129 | return u'OrgFindTags'
130 |
131 | @classmethod
132 | def realign_tags(cls):
133 | u"""
134 | Updates tags when user finished editing a heading
135 | """
136 | d = ORGMODE.get_document(allow_dirty=True)
137 | heading = d.find_current_heading()
138 | if not heading:
139 | return
140 |
141 | if vim.current.window.cursor[0] == heading.start_vim:
142 | heading.set_dirty_heading()
143 | d.write_heading(heading, including_children=False)
144 |
145 | @classmethod
146 | def realign_all_tags(cls):
147 | u"""
148 | Updates tags when user finishes editing a heading
149 | """
150 | d = ORGMODE.get_document()
151 | for heading in d.all_headings():
152 | heading.set_dirty_heading()
153 |
154 | d.write()
155 |
156 | def register(self):
157 | u"""
158 | Registration of plugin. Key bindings and other initialization should be done.
159 | """
160 | # an Action menu entry which binds "keybinding" to action ":action"
161 | settings.set(u'org_tag_column', vim.eval(u'&textwidth'))
162 | settings.set(u'org_tag_completion_ignorecase', int(vim.eval(u'&ignorecase')))
163 |
164 | cmd = Command(
165 | u'OrgSetTags',
166 | u'%s ORGMODE.plugins[u"TagsProperties"].set_tags()' % VIM_PY_CALL)
167 | self.commands.append(cmd)
168 | keybinding = Keybinding(
169 | u'st',
170 | Plug(u'OrgSetTags', cmd))
171 | self.keybindings.append(keybinding)
172 | self.menu + ActionEntry(u'Set &Tags', keybinding)
173 |
174 | cmd = Command(
175 | u'OrgFindTags',
176 | u'%s ORGMODE.plugins[u"TagsProperties"].find_tags()' % VIM_PY_CALL)
177 | self.commands.append(cmd)
178 | keybinding = Keybinding(
179 | u'ft',
180 | Plug(u'OrgFindTags', cmd))
181 | self.keybindings.append(keybinding)
182 | self.menu + ActionEntry(u'&Find Tags', keybinding)
183 |
184 | cmd = Command(
185 | u'OrgTagsRealign',
186 | u"%s ORGMODE.plugins[u'TagsProperties'].realign_all_tags()" % VIM_PY_CALL)
187 | self.commands.append(cmd)
188 |
189 | # workaround to align tags when user is leaving insert mode
190 | vim.command(u_encode(u"function Org_complete_tags(ArgLead, CmdLine, CursorPos)\n"
191 | + sys.executable.split('/')[-1] + u""" << EOF
192 | ORGMODE.plugins[u'TagsProperties'].complete_tags()
193 | EOF
194 | if exists('b:org_complete_tags')
195 | let tmp = b:org_complete_tags
196 | unlet b:org_complete_tags
197 | return tmp
198 | else
199 | return []
200 | endif
201 | endfunction"""))
202 |
203 | vim.command(u_encode(u"""function Org_realign_tags_on_insert_leave()
204 | if !exists('b:org_complete_tag_on_insertleave_au')
205 | :au orgmode InsertLeave %s ORGMODE.plugins[u'TagsProperties'].realign_tags()
206 | let b:org_complete_tag_on_insertleave_au = 1
207 | endif
208 | endfunction""" % VIM_PY_CALL))
209 |
210 | # this is for all org files opened after this file
211 | vim.command(u_encode(u"au orgmode FileType org call Org_realign_tags_on_insert_leave()"))
212 | # this is for the current file
213 | vim.command(u_encode(u"call Org_realign_tags_on_insert_leave()"))
214 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/plugins/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/py3compat/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/py3compat/encode_compatibility.py:
--------------------------------------------------------------------------------
1 | import sys
2 | if sys.version_info < (3,):
3 | def u_encode(string):
4 | return string.encode('utf8')
5 | def u_decode(string):
6 | return string.decode('utf8')
7 | else:
8 | def u_encode(string):
9 | return string
10 | def u_decode(string):
11 | return string
12 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/py3compat/py_py3_string.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from string import Formatter
3 |
4 |
5 | if sys.version_info < (3,):
6 | VIM_PY_CALL = u':py'
7 | else:
8 | VIM_PY_CALL = u':py3'
9 |
10 |
11 | class NoneAsEmptyFormatter(Formatter):
12 | def get_value(self, key, args, kwargs):
13 | v = super().get_value(key, args, kwargs)
14 | return '' if v is None else v
15 |
16 |
17 | fmt = NoneAsEmptyFormatter()
18 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/py3compat/unicode_compatibility.py:
--------------------------------------------------------------------------------
1 | try:
2 | unicode
3 | except NameError:
4 | basestring = unicode = str
5 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/py3compat/xrange_compatibility.py:
--------------------------------------------------------------------------------
1 | try:
2 | from __builtin__ import xrange as range
3 | except:
4 | pass
5 |
--------------------------------------------------------------------------------
/ftplugin/orgmode/settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import vim
4 |
5 | import sys
6 | from orgmode.py3compat.encode_compatibility import *
7 | from orgmode.py3compat.unicode_compatibility import *
8 |
9 | SCOPE_ALL = 1
10 |
11 | # for all vim-orgmode buffers
12 | SCOPE_GLOBAL = 2
13 |
14 | # just for the current buffer - has priority before the global settings
15 | SCOPE_BUFFER = 4
16 |
17 | VARIABLE_LEADER = {SCOPE_GLOBAL: u'g', SCOPE_BUFFER: u'b'}
18 |
19 | u""" Evaluate and store settings """
20 |
21 |
22 | def get(setting, default=None, scope=SCOPE_ALL):
23 | u""" Evaluate setting in scope of the current buffer,
24 | globally and also from the contents of the current buffer
25 |
26 | WARNING: Only string values are converted to unicode. If a different value
27 | is received, e.g. a list or dict, no conversion is done.
28 |
29 | :setting: name of the variable to evaluate
30 | :default: default value in case the variable is empty
31 |
32 | :returns: variable value
33 | """
34 | # TODO first read setting from org file which take precedence over vim
35 | # variable settings
36 | if (scope & SCOPE_ALL | SCOPE_BUFFER) and \
37 | int(vim.eval(u_encode(u'exists("b:%s")' % setting))):
38 | res = vim.eval(u_encode(u"b:%s" % setting))
39 | if type(res) in (unicode, str):
40 | return u_decode(res)
41 | return res
42 |
43 | elif (scope & SCOPE_ALL | SCOPE_GLOBAL) and \
44 | int(vim.eval(u_encode(u'exists("g:%s")' % setting))):
45 | res = vim.eval(u_encode(u"g:%s" % setting))
46 | if type(res) in (unicode, str):
47 | return u_decode(res)
48 | return res
49 | return default
50 |
51 |
52 | def set(setting, value, scope=SCOPE_GLOBAL, overwrite=False):
53 | u""" Store setting in the defined scope
54 |
55 | WARNING: For the return value, only string are converted to unicode. If a
56 | different value is received by vim.eval, e.g. a list or dict, no conversion
57 | is done.
58 |
59 | :setting: name of the setting
60 | :value: the actual value, repr is called on the value to create a string
61 | representation
62 | :scope: the scope o the setting/variable
63 | :overwrite: overwrite existing settings (probably user defined settings)
64 |
65 | :returns: the new value in case of overwrite==False the current value
66 | """
67 | if (not overwrite) and (
68 | int(vim.eval(u_encode(u'exists("%s:%s")' % \
69 | (VARIABLE_LEADER[scope], setting))))):
70 | res = vim.eval(
71 | u_encode(u'%s:%s' % (VARIABLE_LEADER[scope], setting)))
72 | if type(res) in (unicode, str):
73 | return u_decode(res)
74 | return res
75 | v = repr(value)
76 | if type(value) == unicode and sys.version_info < (3,):
77 | # strip leading u of unicode string representations
78 | v = v[1:]
79 |
80 | cmd = u'let %s:%s = %s' % (VARIABLE_LEADER[scope], setting, v)
81 | vim.command(u_encode(cmd))
82 | return value
83 |
84 |
85 | def unset(setting, scope=SCOPE_GLOBAL):
86 | u""" Unset setting in the defined scope
87 | :setting: name of the setting
88 | :scope: the scope o the setting/variable
89 |
90 | :returns: last value of setting
91 | """
92 | value = get(setting, scope=scope)
93 | cmd = u'unlet! %s:%s' % (VARIABLE_LEADER[scope], setting)
94 | vim.command(u_encode(cmd))
95 | return value
96 |
--------------------------------------------------------------------------------
/indent/org.vim:
--------------------------------------------------------------------------------
1 | " Delete the next line to avoid the special indention of items
2 | if !exists("g:org_indent")
3 | let g:org_indent = 0
4 | endif
5 |
6 | setlocal foldtext=GetOrgFoldtext()
7 | setlocal fillchars-=fold:-
8 | setlocal fillchars+=fold:\
9 | setlocal foldexpr=GetOrgFolding()
10 | setlocal foldmethod=expr
11 | setlocal indentexpr=GetOrgIndent()
12 | setlocal nolisp
13 | setlocal nosmartindent
14 | setlocal autoindent
15 |
16 | if has('python3')
17 | let s:py_env = 'python3 << EOF'
18 | else
19 | let s:py_env = 'python << EOF'
20 | endif
21 |
22 | function! GetOrgIndent()
23 | if g:org_indent == 0
24 | return -1
25 | endif
26 |
27 | exe s:py_env
28 | from orgmode._vim import indent_orgmode
29 | indent_orgmode()
30 | EOF
31 |
32 | if exists('b:indent_level')
33 | let l:tmp = b:indent_level
34 | unlet b:indent_level
35 | return l:tmp
36 | else
37 | return -1
38 | endif
39 | endfunction
40 |
41 | function! GetOrgFolding()
42 | let l:mode = mode()
43 | if l:mode == 'i'
44 | " the cache size is limited to 3, because vim queries the current and
45 | " both surrounding lines when the user is typing in insert mode. The
46 | " cache is shared between GetOrgFolding and GetOrgFoldtext
47 | if ! exists('b:org_folding_cache')
48 | let b:org_folding_cache = {}
49 | endif
50 |
51 | if has_key(b:org_folding_cache, v:lnum)
52 | if match(b:org_folding_cache[v:lnum], '^>') == 0 &&
53 | \ match(getline(v:lnum), '^\*\+\s') != 0
54 | " when the user pastes text or presses enter, it happens that
55 | " the cache starts to confuse vim's folding abilities
56 | " these entries can safely be removed
57 | unlet b:org_folding_cache[v:lnum]
58 |
59 | " the fold text cache is probably also damaged, delete it as
60 | " well
61 | unlet! b:org_foldtext_cache
62 | else
63 | return b:org_folding_cache[v:lnum]
64 | endif
65 | endif
66 |
67 | exe s:py_env
68 | from orgmode._vim import fold_orgmode
69 | fold_orgmode(allow_dirty=True)
70 | EOF
71 | else
72 |
73 | exe s:py_env
74 | from orgmode._vim import fold_orgmode
75 | fold_orgmode()
76 | EOF
77 | endif
78 |
79 | if exists('b:fold_expr')
80 | let l:tmp = b:fold_expr
81 | unlet b:fold_expr
82 | if l:mode == 'i'
83 | if ! has_key(b:org_folding_cache, v:lnum)
84 | if len(b:org_folding_cache) > 3
85 | let b:org_folding_cache = {}
86 | endif
87 | let b:org_folding_cache[v:lnum] = l:tmp
88 | endif
89 | endif
90 | return l:tmp
91 | else
92 | return -1
93 | endif
94 | endfunction
95 |
96 | function! SetOrgFoldtext(text)
97 | let b:foldtext = a:text
98 | endfunction
99 |
100 | function! GetOrgFoldtext()
101 | let l:mode = mode()
102 | if l:mode == 'i'
103 | " add a separate cache for fold text
104 | if ! exists('b:org_foldtext_cache') ||
105 | \ ! has_key(b:org_foldtext_cache, 'timestamp') ||
106 | \ b:org_foldtext_cache['timestamp'] > (localtime() + 10)
107 | let b:org_foldtext_cache = {'timestamp': localtime()}
108 | endif
109 |
110 | if has_key(b:org_foldtext_cache, v:foldstart)
111 | return b:org_foldtext_cache[v:foldstart]
112 | endif
113 | exe s:py_env
114 | from orgmode._vim import fold_text
115 | fold_text(allow_dirty=True)
116 | EOF
117 | else
118 | unlet! b:org_foldtext_cache
119 | exec s:py_env
120 | from orgmode._vim import fold_text
121 | fold_text()
122 | EOF
123 | endif
124 |
125 | if exists('b:foldtext')
126 | let l:tmp = b:foldtext
127 | unlet b:foldtext
128 | if l:mode == 'i'
129 | let b:org_foldtext_cache[v:foldstart] = l:tmp
130 | endif
131 | return l:tmp
132 | endif
133 | endfunction
134 |
--------------------------------------------------------------------------------
/syntax/orgagenda.vim:
--------------------------------------------------------------------------------
1 | " TODO do we really need a separate syntax file for the agenda?
2 | " - Most of the stuff here is also in syntax.org
3 | " - DRY!
4 |
5 | syn match org_todo_key /\[\zs[^]]*\ze\]/
6 | hi def link org_todo_key Identifier
7 |
8 | let s:todo_headings = ''
9 | let s:i = 1
10 | while s:i <= g:org_heading_highlight_levels
11 | if s:todo_headings == ''
12 | let s:todo_headings = 'containedin=org_heading' . s:i
13 | else
14 | let s:todo_headings = s:todo_headings . ',org_heading' . s:i
15 | endif
16 | let s:i += 1
17 | endwhile
18 | unlet! s:i
19 |
20 | if !exists('g:loaded_orgagenda_syntax')
21 | let g:loaded_orgagenda_syntax = 1
22 | function! s:ReadTodoKeywords(keywords, todo_headings)
23 | let l:default_group = 'Todo'
24 | for l:i in a:keywords
25 | if type(l:i) == 3
26 | call s:ReadTodoKeywords(l:i, a:todo_headings)
27 | continue
28 | endif
29 | if l:i == '|'
30 | let l:default_group = 'Question'
31 | continue
32 | endif
33 | " strip access key
34 | let l:_i = substitute(l:i, "\(.*$", "", "")
35 |
36 | let l:group = l:default_group
37 | for l:j in g:org_todo_keyword_faces
38 | if l:j[0] == l:_i
39 | let l:group = 'orgtodo_todo_keyword_face_' . l:_i
40 | call OrgExtendHighlightingGroup(l:default_group, l:group, OrgInterpretFaces(l:j[1]))
41 | break
42 | endif
43 | endfor
44 | silent! exec 'syntax match orgtodo_todo_keyword_' . l:_i . ' /' . l:_i .'/ ' . a:todo_headings
45 | silent! exec 'hi def link orgtodo_todo_keyword_' . l:_i . ' ' . l:group
46 | endfor
47 | endfunction
48 | endif
49 |
50 | call s:ReadTodoKeywords(g:org_todo_keywords, s:todo_headings)
51 | unlet! s:todo_headings
52 |
53 | " Timestamps
54 | "<2003-09-16 Tue>
55 | syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k>\)/
56 | "<2003-09-16 Tue 12:00>
57 | syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d>\)/
58 | "<2003-09-16 Tue 12:00-12:30>
59 | syn match org_timestamp /\(<\d\d\d\d-\d\d-\d\d \k\k\k \d\d:\d\d-\d\d:\d\d>\)/
60 | "<2003-09-16 Tue>--<2003-09-16 Tue>
61 | 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>\)/
62 | "<2003-09-16 Tue 12:00>--<2003-09-16 Tue 12:00>
63 | 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>\)/
64 | syn match org_timestamp /\(<%%(diary-float.\+>\)/
65 | hi def link org_timestamp PreProc
66 |
67 | " special words
68 | syn match today /TODAY$/
69 | hi def link today PreProc
70 |
71 | syn match week_agenda /^Week Agenda:$/
72 | hi def link week_agenda PreProc
73 |
74 | " Hyperlinks
75 | syntax match hyperlink "\[\{2}[^][]*\(\]\[[^][]*\)\?\]\{2}" contains=hyperlinkBracketsLeft,hyperlinkURL,hyperlinkBracketsRight containedin=ALL
76 | syntax match hyperlinkBracketsLeft contained "\[\{2}" conceal
77 | syntax match hyperlinkURL contained "[^][]*\]\[" conceal
78 | syntax match hyperlinkBracketsRight contained "\]\{2}" conceal
79 | hi def link hyperlink Underlined
80 |
--------------------------------------------------------------------------------
/syntax/orgtodo.vim:
--------------------------------------------------------------------------------
1 | syn match org_todo_key /\[\zs[^]]*\ze\]/
2 | hi def link org_todo_key Identifier
3 |
4 | let s:todo_headings = ''
5 | let s:i = 1
6 | while s:i <= g:org_heading_highlight_levels
7 | if s:todo_headings == ''
8 | let s:todo_headings = 'containedin=org_heading' . s:i
9 | else
10 | let s:todo_headings = s:todo_headings . ',org_heading' . s:i
11 | endif
12 | let s:i += 1
13 | endwhile
14 | unlet! s:i
15 |
16 | if !exists('g:loaded_orgtodo_syntax')
17 | let g:loaded_orgtodo_syntax = 1
18 | function! s:ReadTodoKeywords(keywords, todo_headings)
19 | let l:default_group = 'Todo'
20 | for l:i in a:keywords
21 | if type(l:i) == 3
22 | call s:ReadTodoKeywords(l:i, a:todo_headings)
23 | continue
24 | endif
25 | if l:i == '|'
26 | let l:default_group = 'Question'
27 | continue
28 | endif
29 | " strip access key
30 | let l:_i = substitute(l:i, "\(.*$", "", "")
31 |
32 | let l:group = l:default_group
33 | for l:j in g:org_todo_keyword_faces
34 | if l:j[0] == l:_i
35 | let l:group = 'orgtodo_todo_keyword_face_' . l:_i
36 | call OrgExtendHighlightingGroup(l:default_group, l:group, OrgInterpretFaces(l:j[1]))
37 | break
38 | endif
39 | endfor
40 | silent! exec 'syntax match orgtodo_todo_keyword_' . l:_i . ' /' . l:_i .'/ ' . a:todo_headings . ' contains=@NoSpell'
41 | silent! exec 'hi def link orgtodo_todo_keyword_' . l:_i . ' ' . l:group
42 | endfor
43 | endfunction
44 | endif
45 |
46 | call s:ReadTodoKeywords(g:org_todo_keywords, s:todo_headings)
47 | unlet! s:todo_headings
48 |
--------------------------------------------------------------------------------
/tests/orgmode_testfile.org:
--------------------------------------------------------------------------------
1 |
2 | * bold, italics and underline syntax matching
3 | ** Should match:
4 |
5 | *foo* *foo*
6 | *Really, quite long sentence*.
7 | _foo_ _foo_
8 | _really, quite long sentence._.
9 |
10 | *Übermensch á* *eä* *ý€*
11 | _Ÿ ï_
12 |
13 | *sdf l.*
14 | *sdfsdf ,.*
15 | *foo_ sdf /*
16 | /sdf sdf sdf ./
17 |
18 | /google.com/
19 |
20 | *[sdf]*
21 | *a* /a/ =b= ~b~ `d`
22 |
23 | *abc* /abc/ =bde= ~bde~ `def`
24 | *=*a*=*
25 | ** Should not match
26 | http://google.com/
27 | //google.com/
28 | * sdf* _ sdf_
29 | *sdfsdf sdf,*
30 | *foo *
31 | foo_not underlined_bar
32 |
33 | *.sdf*[
34 | [*.sdf*
35 | [*sdf*]
36 | *=*a*=
37 |
38 |
--------------------------------------------------------------------------------
/tests/run_tests.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import unittest
5 |
6 | import test_vimbuffer
7 |
8 | import test_libagendafilter
9 | import test_libcheckbox
10 | import test_libbase
11 | import test_libheading
12 | import test_liborgdate
13 | import test_liborgdate_utf8
14 | import test_liborgdate_parsing
15 | import test_liborgdatetime
16 | import test_liborgtimerange
17 |
18 | import test_plugin_date
19 | import test_plugin_edit_structure
20 | import test_plugin_edit_checkbox
21 | import test_plugin_misc
22 | import test_plugin_navigator
23 | import test_plugin_show_hide
24 | import test_plugin_tags_properties
25 | import test_plugin_todo
26 | import test_plugin_mappings
27 |
28 | if __name__ == '__main__':
29 | tests = unittest.TestSuite()
30 |
31 | tests.addTests(test_vimbuffer.suite())
32 |
33 | # lib
34 | tests.addTests(test_libbase.suite())
35 | tests.addTests(test_libcheckbox.suite())
36 | tests.addTests(test_libagendafilter.suite())
37 | tests.addTests(test_libheading.suite())
38 | tests.addTests(test_liborgdate.suite())
39 | tests.addTests(test_liborgdate_utf8.suite())
40 | tests.addTests(test_liborgdate_parsing.suite())
41 | tests.addTests(test_liborgdatetime.suite())
42 | tests.addTests(test_liborgtimerange.suite())
43 |
44 | # plugins
45 | tests.addTests(test_plugin_date.suite())
46 | tests.addTests(test_plugin_edit_structure.suite())
47 | tests.addTests(test_plugin_edit_checkbox.suite())
48 | tests.addTests(test_plugin_misc.suite())
49 | tests.addTests(test_plugin_navigator.suite())
50 | tests.addTests(test_plugin_show_hide.suite())
51 | tests.addTests(test_plugin_tags_properties.suite())
52 | tests.addTests(test_plugin_todo.suite())
53 | tests.addTests(test_plugin_mappings.suite())
54 |
55 | runner = unittest.TextTestRunner()
56 | runner.run(tests)
57 |
--------------------------------------------------------------------------------
/tests/test_libagendafilter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | import sys
5 | sys.path.append(u'../ftplugin')
6 |
7 | import unittest
8 | from datetime import date
9 | from datetime import timedelta
10 |
11 | from orgmode.liborgmode.headings import Heading
12 | from orgmode.liborgmode.orgdate import OrgDate
13 | from orgmode.liborgmode.agendafilter import contains_active_todo
14 | from orgmode.liborgmode.agendafilter import contains_active_date
15 | from orgmode.liborgmode.orgdate import OrgDateTime
16 | from orgmode.liborgmode.agendafilter import is_within_week
17 | from orgmode.liborgmode.agendafilter import is_within_week_and_active_todo
18 | from orgmode.liborgmode.agendafilter import filter_items
19 |
20 | import vim
21 |
22 | from orgmode.py3compat.encode_compatibility import *
23 |
24 | counter = 0
25 |
26 | class AgendaFilterTestCase(unittest.TestCase):
27 | u"""Tests all the functionality of the Agenda filter module."""
28 |
29 | def setUp(self):
30 | global counter
31 | counter += 1
32 |
33 | vim.EVALHISTORY = []
34 | vim.EVALRESULTS = {
35 | # no org_todo_keywords for b
36 | u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
37 | # global values for org_todo_keywords
38 | u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
39 | u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
40 | u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
41 | u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
42 | u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
43 | u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
44 | u_encode(u"v:count"): u_encode(u'0')
45 | }
46 | vim.current.buffer[:] = [u_encode(i) for i in u"""
47 | * TODO Heading 1
48 | some text
49 | """.split(u'\n')]
50 |
51 | def test_contains_active_todo(self):
52 | heading = Heading(title=u'Refactor the code', todo='TODO')
53 | self.assertTrue(contains_active_todo(heading))
54 |
55 | heading = Heading(title=u'Refactor the code', todo='DONE')
56 | self.assertFalse(contains_active_todo(heading))
57 |
58 | heading = Heading(title=u'Refactor the code', todo=None)
59 | self.assertFalse(contains_active_todo(heading))
60 |
61 | def test_contains_active_date(self):
62 | heading = Heading(title=u'Refactor the code', active_date=None)
63 | self.assertFalse(contains_active_date(heading))
64 |
65 | odate = OrgDate(True, 2011, 11, 1)
66 | heading = Heading(title=u'Refactor the code', active_date=odate)
67 | self.assertTrue(contains_active_date(heading))
68 |
69 | def test_is_within_week_with_orgdate(self):
70 | # to far in the future
71 | tmpdate = date.today() + timedelta(days=8)
72 | odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
73 | heading = Heading(title=u'Refactor the code', active_date=odate)
74 | self.assertFalse(is_within_week(heading))
75 |
76 | # within a week
77 | tmpdate = date.today() + timedelta(days=5)
78 | odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
79 | heading = Heading(title=u'Refactor the code', active_date=odate)
80 | self.assertTrue(is_within_week(heading))
81 |
82 | # in the past
83 | tmpdate = date.today() - timedelta(days=105)
84 | odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
85 | heading = Heading(title=u'Refactor the code', active_date=odate)
86 | self.assertTrue(is_within_week(heading))
87 |
88 | def test_is_within_week_with_orgdatetime(self):
89 | # to far in the future
90 | tmp = date.today() + timedelta(days=1000)
91 | odate = OrgDateTime(True, tmp.year, tmp.month, tmp.day, 10, 10)
92 | heading = Heading(title=u'Refactor the code', active_date=odate)
93 | self.assertFalse(is_within_week(heading))
94 |
95 | # within a week
96 | tmpdate = date.today() + timedelta(days=5)
97 | odate = OrgDateTime(True, tmpdate.year, tmpdate.month, tmpdate.day, 1, 0)
98 | heading = Heading(title=u'Refactor the code', active_date=odate)
99 | self.assertTrue(is_within_week(heading))
100 |
101 | # in the past
102 | tmpdate = date.today() - timedelta(days=5)
103 | odate = OrgDateTime(True, tmpdate.year, tmpdate.month, tmpdate.day, 1, 0)
104 | heading = Heading(title=u'Refactor the code', active_date=odate)
105 | self.assertTrue(is_within_week(heading))
106 |
107 | def test_filter_items(self):
108 | # only headings with date and todo should be returned
109 | vim.EVALRESULTS[u_encode(u'g:org_todo_keywords')] = \
110 | [u_encode(u'TODO'), u_encode(u'STARTED'), u_encode(u'|'), u_encode(u'DONE')]
111 | tmpdate = date.today()
112 | odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
113 | tmp_head = Heading(title=u'Refactor the code', todo=u'TODO', active_date=odate)
114 | tmp_head_01 = Heading(title=u'Refactor the code', todo=u'STARTED', active_date=odate)
115 | # TODO add more tests
116 | headings = [tmp_head, tmp_head_01]
117 | filtered = list(filter_items(headings,
118 | [contains_active_date, contains_active_todo]))
119 |
120 | self.assertEqual(len(filtered), 2)
121 | self.assertEqual(filtered, headings)
122 |
123 | # try a longer list
124 | headings = headings * 3
125 | filtered = list(filter_items(headings,
126 | [contains_active_date, contains_active_todo]))
127 |
128 | self.assertEqual(len(filtered), 6)
129 | self.assertEqual(filtered, headings)
130 |
131 | # date does not contain all needed fields thus gets ignored
132 | tmpdate = date.today()
133 | odate = OrgDate(True, tmpdate.year, tmpdate.month, tmpdate.day)
134 | tmp_head = Heading(title=u'Refactor the code', active_date=odate)
135 | headings = [tmp_head]
136 | filtered = list(filter_items(headings, [contains_active_date,
137 | contains_active_todo]))
138 | self.assertEqual([], filtered)
139 |
140 | def test_filter_items_with_some_todos_and_dates(self):
141 | u"""
142 | Only the headings with todo and dates should be returned.
143 | """
144 | tmp = [u"* TODO OrgMode Demo und Tests"
145 | u"<2011-08-22 Mon>"]
146 | headings = [Heading.parse_heading_from_data(tmp, [u'TODO'])]
147 | filtered = list(filter_items(headings,
148 | [is_within_week_and_active_todo]))
149 | self.assertEqual(len(filtered), 1)
150 | self.assertEqual(headings, filtered)
151 |
152 | tmp = [Heading.parse_heading_from_data([u"** DONE something <2011-08-10 Wed>"], [u'TODO']),
153 | Heading.parse_heading_from_data([u"*** TODO rsitenaoritns more <2011-08-25 Thu>"], [u'TODO']),
154 | Heading.parse_heading_from_data([u"*** DONE some more <2011-08-25 Thu>"], [u'TODO']),
155 | Heading.parse_heading_from_data([u"*** TODO some more <2011-08-25 Thu>"], [u'TODO']),
156 | Heading.parse_heading_from_data([u"** DONE something2 <2011-08-10 Wed>"], [u'TODO'])
157 | ]
158 | for h in tmp:
159 | headings.append(h)
160 |
161 | filtered = list(filter_items(headings,
162 | [is_within_week_and_active_todo]))
163 | self.assertEqual(len(filtered), 3)
164 | self.assertEqual(filtered, [headings[0], headings[2], headings[4]])
165 |
166 |
167 | def suite():
168 | return unittest.TestLoader().loadTestsFromTestCase(AgendaFilterTestCase)
169 |
--------------------------------------------------------------------------------
/tests/test_libbase.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import unittest
4 | import sys
5 | sys.path.append(u'../ftplugin')
6 |
7 | from orgmode.liborgmode.base import Direction, get_domobj_range
8 | from orgmode.liborgmode.headings import Heading
9 |
10 |
11 | class LibBaseTestCase(unittest.TestCase):
12 |
13 | def setUp(self):
14 | self.case1 = """
15 | * head1
16 | heading body
17 | for testing
18 | * head2
19 | ** head3
20 | """.split("\n")
21 |
22 | def test_base_functions(self):
23 | # direction FORWARD
24 | (start, end) = get_domobj_range(content=self.case1, position=1, identify_fun=Heading.identify_heading)
25 | self.assertEqual((start, end), (1, 3))
26 | (start, end) = get_domobj_range(content=self.case1, position=3, direction=Direction.BACKWARD, \
27 | identify_fun=Heading.identify_heading)
28 | self.assertEqual((start, end), (1, 3))
29 |
30 | def suite():
31 | return unittest.TestLoader() \
32 | .loadTestsFromTestCase(
33 | LibBaseTestCase)
34 |
--------------------------------------------------------------------------------
/tests/test_libcheckbox.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import unittest
4 | import sys
5 | sys.path.append(u'../ftplugin')
6 |
7 | import vim
8 | from orgmode.liborgmode.checkboxes import Checkbox
9 | from orgmode._vim import ORGMODE
10 |
11 | from orgmode.py3compat.encode_compatibility import *
12 |
13 | def set_vim_buffer(buf=None, cursor=(2, 0), bufnr=0):
14 | if buf is None:
15 | buf = []
16 | vim.current.buffer[:] = buf
17 | vim.current.window.cursor = cursor
18 | vim.current.buffer.number = bufnr
19 |
20 |
21 | class CheckboxTestCase(unittest.TestCase):
22 |
23 | def setUp(self):
24 | counter = 0
25 | vim.CMDHISTORY = []
26 | vim.CMDRESULTS = {}
27 | vim.EVALHISTORY = []
28 | vim.EVALRESULTS = {
29 | # no org_todo_keywords for b
30 | u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
31 | # global values for org_todo_keywords
32 | u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
33 | u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
34 | u_encode(u'exists("g:org_improve_split_heading")'): u_encode(u'0'),
35 | u_encode(u'exists("b:org_improve_split_heading")'): u_encode(u'0'),
36 | u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
37 | u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
38 | u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
39 | u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
40 | u_encode(u'&ts'): u_encode(u'8'),
41 | u_encode(u'exists("g:org_tag_column")'): u_encode(u'0'),
42 | u_encode(u'exists("b:org_tag_column")'): u_encode(u'0'),
43 | u_encode(u"v:count"): u_encode(u'0')}
44 |
45 | self.c1 = """
46 | * heading1 [/]
47 | - [-] checkbox1 [%]
48 | - [X] checkbox2
49 | - [ ] checkbox3
50 | - [X] checkbox4
51 | """.split("\n")
52 |
53 | self.c2 = """
54 | * heading1
55 | - [ ] checkbox1
56 | - [ ] checkbox2
57 | - [ ] checkbox3
58 | - [ ] checkbox4
59 | - [ ] checkbox5
60 | - [ ] checkbox6
61 | """.split("\n")
62 |
63 | def test_init(self):
64 | # test initialize Checkbox
65 | c = Checkbox(level=1, title="checkbox1")
66 | self.assertEqual(str(c), " - [ ] checkbox1")
67 | c = Checkbox(level=3, title="checkbox2", status="[X]")
68 | self.assertEqual(str(c), " - [X] checkbox2")
69 |
70 | def test_basic(self):
71 | bufnr = 1
72 | set_vim_buffer(buf=self.c1, bufnr=bufnr)
73 | h = ORGMODE.get_document(bufnr=bufnr).current_heading()
74 | h.init_checkboxes()
75 |
76 | c = h.current_checkbox(position=2)
77 | self.assertEqual(str(c), self.c1[2])
78 | self.assertFalse(c.are_children_all(Checkbox.STATUS_ON))
79 | self.assertTrue(c.is_child_one(Checkbox.STATUS_OFF))
80 | self.assertFalse(c.are_siblings_all(Checkbox.STATUS_ON))
81 |
82 | for child in c.all_children():
83 | pass
84 | for sibling in c.all_siblings():
85 | pass
86 | c = h.current_checkbox(position=3)
87 | new_checkbox = c.copy()
88 | self.assertEqual(str(c), self.c1[3])
89 | c.get_parent_list()
90 | c.get_index_in_parent_list()
91 |
92 | def test_identify(self):
93 | # test identify_checkbox
94 | self.assertEqual(Checkbox.identify_checkbox(self.c1[2]), 2)
95 | self.assertEqual(Checkbox.identify_checkbox(self.c1[3]), 8)
96 | # check for corner case
97 | self.assertEqual(Checkbox.identify_checkbox(" - [ ]"), 1)
98 |
99 | def test_toggle(self):
100 | bufnr = 2
101 | # test init_checkboxes
102 | set_vim_buffer(buf=self.c1, bufnr=bufnr)
103 | h = ORGMODE.get_document(bufnr=bufnr).current_heading()
104 | h.init_checkboxes()
105 |
106 | # toggle checkbox
107 | c = h.current_checkbox(position=4)
108 | c.toggle()
109 | self.assertEqual(str(c), " - [X] checkbox3")
110 | c.toggle()
111 | self.assertEqual(str(c), " - [ ] checkbox3")
112 |
113 | (total, on) = c.all_siblings_status()
114 | self.assertEqual((total, on), (2, 1))
115 |
116 | def test_subtasks(self):
117 | bufnr = 3
118 | set_vim_buffer(buf=self.c1, bufnr=bufnr)
119 | h = ORGMODE.get_document(bufnr=bufnr).current_heading()
120 | h.init_checkboxes()
121 | c = h.current_checkbox(position=3)
122 | c.toggle()
123 | c = h.current_checkbox(position=2)
124 | (total, on) = c.all_siblings_status()
125 | c.update_subtasks(total=total, on=on)
126 | self.assertEqual(str(c), " - [-] checkbox1 [50%]")
127 |
128 |
129 | def suite():
130 | return unittest.TestLoader().loadTestsFromTestCase(CheckboxTestCase)
131 |
--------------------------------------------------------------------------------
/tests/test_libheading.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import unittest
4 | import sys
5 | sys.path.append(u'../ftplugin')
6 |
7 | from orgmode.liborgmode.headings import Heading
8 | from orgmode.liborgmode.orgdate import OrgDate
9 | from orgmode.liborgmode.orgdate import OrgDateTime
10 |
11 |
12 | class TestHeadingRecognizeDatesInHeading(unittest.TestCase):
13 |
14 | def setUp(self):
15 | self.allowed_todo_states = ["TODO"]
16 |
17 | tmp = ["* This heading is earlier <2011-08-24 Wed>"]
18 | self.h1 = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
19 |
20 | tmp = ["* This heading is later <2011-08-25 Thu>"]
21 | self.h2 = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
22 |
23 | tmp = ["* This heading is later <2011-08-25 Thu 10:20>"]
24 | self.h2_datetime = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
25 |
26 | tmp = ["* This heading is later <2011-08-26 Fri 10:20>"]
27 | self.h3 = Heading.parse_heading_from_data(tmp, self.allowed_todo_states)
28 |
29 | tmp = ["* This heading has no date and should be later than the rest"]
30 | self.h_no_date = Heading.parse_heading_from_data(tmp,
31 | self.allowed_todo_states)
32 |
33 | def test_heading_parsing_no_date(self):
34 | """""
35 | 'text' doesn't contain any valid date.
36 | """
37 | text = ["* TODO This is a test :hallo:"]
38 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
39 | self.assertEqual(None, h.active_date)
40 |
41 | text = ["* TODO This is a test <2011-08-25>"]
42 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
43 | self.assertEqual(None, h.active_date)
44 |
45 | text = ["* TODO This is a test <2011-08-25 Wednesday>"]
46 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
47 | self.assertEqual(None, h.active_date)
48 |
49 | text = ["* TODO This is a test <20110825>"]
50 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
51 | self.assertEqual(None, h.active_date)
52 |
53 | def test_heading_parsing_with_date(self):
54 | """""
55 | 'text' does contain valid dates.
56 | """
57 | # orgdate
58 | text = ["* TODO This is a test <2011-08-24 Wed> :hallo:"]
59 | odate = OrgDate(True, 2011, 8, 24)
60 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
61 | self.assertEqual(odate, h.active_date)
62 |
63 | # orgdatetime
64 | text = ["* TODO This is a test <2011-08-25 Thu 10:10> :hallo:"]
65 | odate = OrgDateTime(True, 2011, 8, 25, 10, 10)
66 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
67 | self.assertEqual(odate, h.active_date)
68 |
69 | def test_heading_parsing_with_date_and_body(self):
70 | """""
71 | 'text' contains valid dates (in the body).
72 | """
73 | # orgdatetime
74 | text = ["* TODO This is a test <2011-08-25 Thu 10:10> :hallo:",
75 | "some body text",
76 | "some body text"]
77 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
78 | self.assertTrue(isinstance(h.active_date, OrgDateTime))
79 | self.assertEqual("<2011-08-25 Thu 10:10>", str(h.active_date))
80 |
81 | text = ["* TODO This is a test :hallo:",
82 | "some body text",
83 | "some body text<2011-08-25 Thu 10:10>"]
84 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
85 | self.assertTrue(isinstance(h.active_date, OrgDateTime))
86 | self.assertEqual("<2011-08-25 Thu 10:10>", str(h.active_date))
87 |
88 | text = ["* TODO This is a test :hallo:",
89 | "some body text <2011-08-24 Wed>",
90 | "some body text<2011-08-25 Thu 10:10>"]
91 | h = Heading.parse_heading_from_data(text, self.allowed_todo_states)
92 | odate = OrgDate(True, 2011, 8, 24)
93 | self.assertEqual(odate, h.active_date)
94 |
95 | def test_less_than_for_dates_in_heading(self):
96 | self.assertTrue(self.h1 < self.h2)
97 | self.assertTrue(self.h1 < self.h3)
98 | self.assertTrue(self.h1 < self.h_no_date)
99 | self.assertTrue(self.h2 < self.h_no_date)
100 | self.assertTrue(self.h2 < self.h3)
101 | self.assertTrue(self.h3 < self.h_no_date)
102 |
103 | self.assertFalse(self.h2 < self.h1)
104 | self.assertFalse(self.h3 < self.h2)
105 |
106 | def test_less_equal_for_dates_in_heading(self):
107 | self.assertTrue(self.h1 <= self.h2)
108 | self.assertTrue(self.h1 <= self.h_no_date)
109 | self.assertTrue(self.h2 <= self.h_no_date)
110 | self.assertTrue(self.h2 <= self.h2_datetime)
111 | self.assertTrue(self.h2 <= self.h3)
112 |
113 | def test_greate_than_for_dates_in_heading(self):
114 | self.assertTrue(self.h2 > self.h1)
115 | self.assertTrue(self.h_no_date > self.h1)
116 | self.assertTrue(self.h_no_date > self.h2)
117 |
118 | self.assertFalse(self.h2 > self.h2_datetime)
119 |
120 | def test_greate_equal_for_dates_in_heading(self):
121 | self.assertTrue(self.h2 >= self.h1)
122 | self.assertTrue(self.h_no_date >= self.h1)
123 | self.assertTrue(self.h_no_date >= self.h2)
124 | self.assertTrue(self.h2 >= self.h2_datetime)
125 |
126 | def test_sorting_of_headings(self):
127 | """Headings should be sortable."""
128 | self.assertEqual([self.h1, self.h2], sorted([self.h2, self.h1]))
129 |
130 | self.assertEqual([self.h1, self.h2_datetime],
131 | sorted([self.h2_datetime, self.h1]))
132 |
133 | self.assertEqual([self.h2_datetime, self.h2],
134 | sorted([self.h2_datetime, self.h2]))
135 |
136 | self.assertEqual([self.h1, self.h2], sorted([self.h1, self.h2]))
137 |
138 | self.assertEqual([self.h1, self.h_no_date],
139 | sorted([self.h1, self.h_no_date]))
140 |
141 | self.assertEqual([self.h1, self.h_no_date],
142 | sorted([self.h_no_date, self.h1]))
143 |
144 | self.assertEqual([self.h1, self.h2, self.h_no_date],
145 | sorted([self.h2, self.h_no_date, self.h1]))
146 |
147 | self.assertEqual(
148 | [self.h1, self.h2_datetime, self.h2, self.h3, self.h_no_date],
149 | sorted([self.h2_datetime, self.h3, self.h2, self.h_no_date, self.h1]))
150 |
151 |
152 | def suite():
153 | return unittest.TestLoader().loadTestsFromTestCase(
154 | TestHeadingRecognizeDatesInHeading)
155 |
--------------------------------------------------------------------------------
/tests/test_liborgdate.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | import sys
5 | import unittest
6 | from datetime import date
7 |
8 | sys.path.append(u'../ftplugin')
9 | from orgmode.liborgmode.orgdate import OrgDate
10 |
11 | from orgmode.py3compat.unicode_compatibility import *
12 |
13 | class OrgDateTestCase(unittest.TestCase):
14 | u"""
15 | Tests all the functionality of the OrgDate
16 | """
17 |
18 | def setUp(self):
19 | self.date = date(2011, 8, 29)
20 | self.year = 2011
21 | self.month = 8
22 | self.day = 29
23 | self.text = u'<2011-08-29 Mon>'
24 | self.textinactive = u'[2011-08-29 Mon]'
25 |
26 | def test_OrgDate_ctor_active(self):
27 | u"""OrdDate should be created."""
28 | today = date.today()
29 | od = OrgDate(True, today.year, today.month, today.day)
30 | self.assertTrue(isinstance(od, OrgDate))
31 | self.assertTrue(od.active)
32 |
33 | def test_OrgDate_ctor_inactive(self):
34 | u"""OrdDate should be created."""
35 | today = date.today()
36 | od = OrgDate(False, today.year, today.month, today.day)
37 | self.assertTrue(isinstance(od, OrgDate))
38 | self.assertFalse(od.active)
39 |
40 | def test_OrdDate_str_active(self):
41 | u"""Representation of OrgDates"""
42 | od = OrgDate(True, self.year, self.month, self.day)
43 | self.assertEqual(self.text, unicode(od))
44 |
45 | def test_OrdDate_str_inactive(self):
46 | od = OrgDate(False, self.year, self.month, self.day)
47 | self.assertEqual(self.textinactive, unicode(od))
48 |
49 |
50 | def suite():
51 | return unittest.TestLoader().loadTestsFromTestCase(OrgDateTestCase)
52 |
--------------------------------------------------------------------------------
/tests/test_liborgdate_parsing.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | import sys
5 | import unittest
6 |
7 | sys.path.append(u'../ftplugin')
8 | from orgmode.liborgmode.orgdate import get_orgdate
9 | from orgmode.liborgmode.orgdate import OrgDate
10 | from orgmode.liborgmode.orgdate import OrgDateTime
11 | from orgmode.liborgmode.orgdate import OrgTimeRange
12 |
13 | from orgmode.py3compat.unicode_compatibility import *
14 |
15 | class OrgDateParsingTestCase(unittest.TestCase):
16 | u"""
17 | Tests the functionality of the parsing function of OrgDate.
18 |
19 | Mostly function get_orgdate().
20 | """
21 |
22 | def setUp(self):
23 | self.text = u'<2011-08-29 Mon>'
24 | self.textinactive = u'[2011-08-29 Mon]'
25 |
26 | def test_get_orgdate_parsing_active(self):
27 | u"""
28 | get_orgdate should recognize all orgdates in a given text
29 | """
30 | result = get_orgdate(self.text)
31 | self.assertNotEqual(result, None)
32 | self.assertTrue(isinstance(result, OrgDate))
33 | self.assertTrue(isinstance(get_orgdate(u"<2011-08-30 Tue>"), OrgDate))
34 | self.assertEqual(get_orgdate(u"<2011-08-30 Tue>").year, 2011)
35 | self.assertEqual(get_orgdate(u"<2011-08-30 Tue>").month, 8)
36 | self.assertEqual(get_orgdate(u"<2011-08-30 Tue>").day, 30)
37 | self.assertTrue(get_orgdate(u"<2011-08-30 Tue>").active)
38 |
39 | datestr = u"This date <2011-08-30 Tue> is embedded"
40 | self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
41 |
42 |
43 | def test_get_orgdatetime_parsing_active(self):
44 | u"""
45 | get_orgdate should recognize all orgdatetimes in a given text
46 | """
47 | result = get_orgdate(u"<2011-09-12 Mon 10:20>")
48 | self.assertNotEqual(result, None)
49 | self.assertTrue(isinstance(result, OrgDateTime))
50 | self.assertEqual(result.year, 2011)
51 | self.assertEqual(result.month, 9)
52 | self.assertEqual(result.day, 12)
53 | self.assertEqual(result.hour, 10)
54 | self.assertEqual(result.minute, 20)
55 | self.assertTrue(result.active)
56 |
57 | result = get_orgdate(u"some datetime <2011-09-12 Mon 10:20> stuff")
58 | self.assertTrue(isinstance(result, OrgDateTime))
59 |
60 |
61 | def test_get_orgtimerange_parsing_active(self):
62 | u"""
63 | get_orgdate should recognize all orgtimeranges in a given text
64 | """
65 | daterangestr = u"<2011-09-12 Mon>--<2011-09-13 Tue>"
66 | result = get_orgdate(daterangestr)
67 | self.assertNotEqual(result, None)
68 | self.assertTrue(isinstance(result, OrgTimeRange))
69 | self.assertEqual(unicode(result), daterangestr)
70 | self.assertTrue(result.active)
71 |
72 | daterangestr = u"<2011-09-12 Mon 10:20>--<2011-09-13 Tue 13:20>"
73 | result = get_orgdate(daterangestr)
74 | self.assertNotEqual(result, None)
75 | self.assertTrue(isinstance(result, OrgTimeRange))
76 | self.assertEqual(unicode(result), daterangestr)
77 | self.assertTrue(result.active)
78 |
79 | daterangestr = u"<2011-09-12 Mon 10:20-13:20>"
80 | result = get_orgdate(daterangestr)
81 | self.assertNotEqual(result, None)
82 | self.assertTrue(isinstance(result, OrgTimeRange))
83 | self.assertEqual(unicode(result), daterangestr)
84 | self.assertTrue(result.active)
85 |
86 | def test_get_orgdate_parsing_inactive(self):
87 | u"""
88 | get_orgdate should recognize all inactive orgdates in a given text
89 | """
90 | result = get_orgdate(self.textinactive)
91 | self.assertNotEqual(result, None)
92 | self.assertTrue(isinstance(result, OrgDate))
93 | self.assertTrue(isinstance(get_orgdate(u"[2011-08-30 Tue]"), OrgDate))
94 | self.assertEqual(get_orgdate(u"[2011-08-30 Tue]").year, 2011)
95 | self.assertEqual(get_orgdate(u"[2011-08-30 Tue]").month, 8)
96 | self.assertEqual(get_orgdate(u"[2011-08-30 Tue]").day, 30)
97 | self.assertFalse(get_orgdate(u"[2011-08-30 Tue]").active)
98 |
99 | datestr = u"This date [2011-08-30 Tue] is embedded"
100 | self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
101 |
102 | def test_get_orgdatetime_parsing_passive(self):
103 | u"""
104 | get_orgdate should recognize all orgdatetimes in a given text
105 | """
106 | result = get_orgdate(u"[2011-09-12 Mon 10:20]")
107 | self.assertNotEqual(result, None)
108 | self.assertTrue(isinstance(result, OrgDateTime))
109 | self.assertEqual(result.year, 2011)
110 | self.assertEqual(result.month, 9)
111 | self.assertEqual(result.day, 12)
112 | self.assertEqual(result.hour, 10)
113 | self.assertEqual(result.minute, 20)
114 | self.assertFalse(result.active)
115 |
116 | result = get_orgdate(u"some datetime [2011-09-12 Mon 10:20] stuff")
117 | self.assertTrue(isinstance(result, OrgDateTime))
118 |
119 | def test_get_orgdate_parsing_with_list_of_texts(self):
120 | u"""
121 | get_orgdate should return the first date in the list.
122 | """
123 | datelist = [u"<2011-08-29 Mon>"]
124 | result = get_orgdate(datelist)
125 | self.assertNotEquals(result, None)
126 | self.assertTrue(isinstance(result, OrgDate))
127 | self.assertEqual(result.year, 2011)
128 | self.assertEqual(result.month, 8)
129 | self.assertEqual(result.day, 29)
130 |
131 | datelist = [u"<2011-08-29 Mon>",
132 | u"<2012-03-30 Fri>"]
133 | result = get_orgdate(datelist)
134 | self.assertNotEquals(result, None)
135 | self.assertTrue(isinstance(result, OrgDate))
136 | self.assertEqual(result.year, 2011)
137 | self.assertEqual(result.month, 8)
138 | self.assertEqual(result.day, 29)
139 |
140 | datelist = [u"some <2011-08-29 Mon>text",
141 | u"<2012-03-30 Fri> is here"]
142 | result = get_orgdate(datelist)
143 | self.assertNotEquals(result, None)
144 | self.assertTrue(isinstance(result, OrgDate))
145 | self.assertEqual(result.year, 2011)
146 | self.assertEqual(result.month, 8)
147 | self.assertEqual(result.day, 29)
148 |
149 | datelist = [u"here is no date",
150 | u"some <2011-08-29 Mon>text",
151 | u"<2012-03-30 Fri> is here"]
152 | result = get_orgdate(datelist)
153 | self.assertNotEquals(result, None)
154 | self.assertTrue(isinstance(result, OrgDate))
155 | self.assertEqual(result.year, 2011)
156 | self.assertEqual(result.month, 8)
157 | self.assertEqual(result.day, 29)
158 |
159 | datelist = [u"here is no date",
160 | u"some <2011-08-29 Mon 20:10> text",
161 | u"<2012-03-30 Fri> is here"]
162 | result = get_orgdate(datelist)
163 | self.assertNotEquals(result, None)
164 | self.assertTrue(isinstance(result, OrgDateTime))
165 | self.assertEqual(result.year, 2011)
166 | self.assertEqual(result.month, 8)
167 | self.assertEqual(result.day, 29)
168 | self.assertEqual(result.hour, 20)
169 | self.assertEqual(result.minute, 10)
170 |
171 | def test_get_orgdate_parsing_with_invalid_input(self):
172 | self.assertEquals(get_orgdate(u"NONSENSE"), None)
173 | self.assertEquals(get_orgdate(u"No D<2011- Date 08-29 Mon>"), None)
174 | self.assertEquals(get_orgdate(u"2011-08-r9 Mon]"), None)
175 | self.assertEquals(get_orgdate(u"<2011-08-29 Mon"), None)
176 | self.assertEquals(get_orgdate(u"<2011-08-29 Mon]"), None)
177 | self.assertEquals(get_orgdate(u"2011-08-29 Mon"), None)
178 | self.assertEquals(get_orgdate(u"2011-08-29"), None)
179 | self.assertEquals(get_orgdate(u"2011-08-29 mon"), None)
180 | self.assertEquals(get_orgdate(u"<2011-08-29 mon>"), None)
181 |
182 | self.assertEquals(get_orgdate(u"wrong date embedded <2011-08-29 mon>"), None)
183 | self.assertEquals(get_orgdate(u"wrong date <2011-08-29 mon>embedded "), None)
184 |
185 | def test_get_orgdate_parsing_with_invalid_dates(self):
186 | u"""
187 | Something like <2011-14-29 Mon> (invalid dates, they don't exist)
188 | should not be parsed
189 | """
190 | datestr = u"<2011-14-30 Tue>"
191 | self.assertEqual(get_orgdate(datestr), None)
192 |
193 | datestr = u"<2012-03-40 Tue>"
194 | self.assertEqual(get_orgdate(datestr), None)
195 |
196 | datestr = u"<2012-03-40 Tue 24:70>"
197 | self.assertEqual(get_orgdate(datestr), None)
198 |
199 | def test_get_orgdate_parsing_with_utf8(self):
200 | u"""
201 | get_orgdate should recognize all orgdates within a given utf-8 text
202 | """
203 | result = get_orgdate(u'<2016-05-07 Sáb>')
204 | self.assertNotEqual(result, None)
205 | self.assertTrue(isinstance(result, OrgDate))
206 | self.assertEqual(result.year, 2016)
207 | self.assertEqual(result.month, 5)
208 | self.assertEqual(result.day, 7)
209 | self.assertTrue(result.active)
210 |
211 | datestr = u"This date <2016-05-07 Sáb> is embedded"
212 | self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
213 |
214 | result = get_orgdate(u'[2016-05-07 Sáb]')
215 | self.assertFalse(result.active)
216 |
217 | datestr = u"This date [2016-05-07 Sáb] is embedded"
218 | self.assertTrue(isinstance(get_orgdate(datestr), OrgDate))
219 |
220 | def test_get_orgdatetime_parsing_with_utf8(self):
221 | u"""
222 | get_orgdate should recognize all orgdatetimes in a given utf-8 text
223 | """
224 | result = get_orgdate(u"<2016-05-07 Sáb 10:20>")
225 | self.assertNotEqual(result, None)
226 | self.assertTrue(isinstance(result, OrgDateTime))
227 | self.assertEqual(result.year, 2016)
228 | self.assertEqual(result.month, 5)
229 | self.assertEqual(result.day, 7)
230 | self.assertEqual(result.hour, 10)
231 | self.assertEqual(result.minute, 20)
232 | self.assertTrue(result.active)
233 |
234 | result = get_orgdate(u"some datetime <2016-05-07 Sáb 10:20> stuff")
235 | self.assertTrue(isinstance(result, OrgDateTime))
236 |
237 | result = get_orgdate(u"[2016-05-07 Sáb 10:20]")
238 | self.assertFalse(result.active)
239 |
240 | result = get_orgdate(u"some datetime [2016-05-07 Sáb 10:20] stuff")
241 | self.assertTrue(isinstance(result, OrgDateTime))
242 |
243 |
244 |
245 | def suite():
246 | return unittest.TestLoader().loadTestsFromTestCase(OrgDateParsingTestCase)
247 |
--------------------------------------------------------------------------------
/tests/test_liborgdate_utf8.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys
4 | import unittest
5 | import locale
6 | import threading
7 |
8 | from datetime import date
9 | from contextlib import contextmanager
10 |
11 | from orgmode.py3compat.unicode_compatibility import *
12 |
13 | sys.path.append(u'../ftplugin')
14 | from orgmode.liborgmode.orgdate import OrgDate
15 |
16 | class OrgDateUtf8TestCase(unittest.TestCase):
17 | u"""
18 | Tests OrgDate with utf-8 enabled locales
19 | """
20 | LOCALE_LOCK = threading.Lock()
21 | UTF8_LOCALE = "fr_FR.utf-8"
22 |
23 | @contextmanager
24 | def setlocale(self, name):
25 | with self.LOCALE_LOCK:
26 | saved = locale.setlocale(locale.LC_ALL)
27 | try:
28 | yield locale.setlocale(locale.LC_ALL, name)
29 | finally:
30 | locale.setlocale(locale.LC_ALL, saved)
31 |
32 | def setUp(self):
33 | self.year = 2016
34 | self.month = 5
35 | self.day = 7
36 | self.text = u'<2016-05-07 sam.>'
37 | self.textinactive = u'[2016-05-07 sam.]'
38 |
39 | def test_OrdDate_str_unicode_active(self):
40 | with self.setlocale(self.UTF8_LOCALE):
41 | od = OrgDate(True, self.year, self.month, self.day)
42 | self.assertEqual(self.text, unicode(od))
43 |
44 | def test_OrdDate_str_unicode_inactive(self):
45 | with self.setlocale(self.UTF8_LOCALE):
46 | od = OrgDate(False, self.year, self.month, self.day)
47 | self.assertEqual(self.textinactive, unicode(od))
48 |
49 | def suite():
50 | return unittest.TestLoader().loadTestsFromTestCase(OrgDateUtf8TestCase)
51 |
--------------------------------------------------------------------------------
/tests/test_liborgdatetime.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys
4 | import unittest
5 | from datetime import datetime
6 |
7 | sys.path.append(u'../ftplugin')
8 | from orgmode.liborgmode.orgdate import OrgDateTime
9 |
10 | from orgmode.py3compat.unicode_compatibility import *
11 |
12 | class OrgDateTimeTestCase(unittest.TestCase):
13 | u"""
14 | Tests all the functionality of the OrgDateTime
15 | """
16 |
17 | def test_OrgDateTime_ctor_active(self):
18 | u"""OrdDateTime should be created."""
19 | today = datetime.today()
20 | odt = OrgDateTime(True, today.year, today.month, today.day, today.hour,
21 | today.minute)
22 | self.assertTrue(isinstance(odt, OrgDateTime))
23 | self.assertTrue(odt.active)
24 |
25 | def test_OrgDateTime_ctor_inactive(self):
26 | u"""OrdDateTime should be created."""
27 | today = datetime.today()
28 | odt = OrgDateTime(False, today.year, today.month, today.day, today.hour,
29 | today.minute)
30 | self.assertTrue(isinstance(odt, OrgDateTime))
31 | self.assertFalse(odt.active)
32 |
33 | def test_OrdDateTime_str_active(self):
34 | u"""Representation of OrgDateTime"""
35 | t = 2011, 9, 8, 10, 20
36 | odt = OrgDateTime(False, t[0], t[1], t[2], t[3], t[4])
37 | self.assertEqual(u"[2011-09-08 Thu 10:20]", unicode(odt))
38 |
39 | def test_OrdDateTime_str_inactive(self):
40 | u"""Representation of OrgDateTime"""
41 | t = 2011, 9, 8, 10, 20
42 | odt = OrgDateTime(True, t[0], t[1], t[2], t[3], t[4])
43 | self.assertEqual(u"<2011-09-08 Thu 10:20>", unicode(odt))
44 |
45 |
46 | def suite():
47 | return unittest.TestLoader().loadTestsFromTestCase(OrgDateTimeTestCase)
48 |
--------------------------------------------------------------------------------
/tests/test_liborgtimerange.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys
4 | import unittest
5 | from datetime import date
6 | from datetime import datetime
7 |
8 | sys.path.append(u'../ftplugin')
9 | from orgmode.liborgmode.orgdate import OrgTimeRange
10 |
11 |
12 | class OrgTimeRangeTestCase(unittest.TestCase):
13 |
14 | def setUp(self):
15 | self.date = date(2011, 8, 29)
16 | self.year = 2011
17 | self.month = 8
18 | self.day = 29
19 | self.text = '<2011-08-29 Mon>'
20 | self.textinactive = '[2011-08-29 Mon]'
21 |
22 | def test_OrgTimeRange_ctor_active(self):
23 | u"""
24 | timerange should be created.
25 | """
26 | start = date(2011, 9 , 12)
27 | end = date(2011, 9 , 13)
28 | timerange = OrgTimeRange(True, start, end)
29 | self.assertTrue(isinstance(timerange, OrgTimeRange))
30 | self.assertTrue(timerange.active)
31 |
32 | def test_OrgTimeRange_ctor_inactive(self):
33 | u"""
34 | timerange should be created.
35 | """
36 | start = date(2011, 9 , 12)
37 | end = date(2011, 9 , 13)
38 | timerange = OrgTimeRange(False, start, end)
39 | self.assertTrue(isinstance(timerange, OrgTimeRange))
40 | self.assertFalse(timerange.active)
41 |
42 | def test_OrdDate_str_active(self):
43 | u"""Representation of OrgDates"""
44 | start = date(2011, 9 , 12)
45 | end = date(2011, 9 , 13)
46 | timerange = OrgTimeRange(True, start, end)
47 | expected = "<2011-09-12 Mon>--<2011-09-13 Tue>"
48 | self.assertEqual(str(timerange), expected)
49 |
50 | start = datetime(2011, 9 , 12, 20, 00)
51 | end = datetime(2011, 9 , 13, 21, 59)
52 | timerange = OrgTimeRange(True, start, end)
53 | expected = "<2011-09-12 Mon 20:00>--<2011-09-13 Tue 21:59>"
54 | self.assertEqual(str(timerange), expected)
55 |
56 | start = datetime(2011, 9 , 12, 20, 00)
57 | end = datetime(2011, 9 , 12, 21, 00)
58 | timerange = OrgTimeRange(True, start, end)
59 | expected = "<2011-09-12 Mon 20:00-21:00>"
60 | self.assertEqual(str(timerange), expected)
61 |
62 | def test_OrdDate_str_inactive(self):
63 | u"""Representation of OrgDates"""
64 | start = date(2011, 9 , 12)
65 | end = date(2011, 9 , 13)
66 | timerange = OrgTimeRange(False, start, end)
67 | expected = "[2011-09-12 Mon]--[2011-09-13 Tue]"
68 | self.assertEqual(str(timerange), expected)
69 |
70 | start = datetime(2011, 9 , 12, 20, 00)
71 | end = datetime(2011, 9 , 13, 21, 59)
72 | timerange = OrgTimeRange(False, start, end)
73 | expected = "[2011-09-12 Mon 20:00]--[2011-09-13 Tue 21:59]"
74 | self.assertEqual(str(timerange), expected)
75 |
76 | start = datetime(2011, 9 , 12, 20, 00)
77 | end = datetime(2011, 9 , 12, 21, 00)
78 | timerange = OrgTimeRange(False, start, end)
79 | expected = "[2011-09-12 Mon 20:00-21:00]"
80 | self.assertEqual(str(timerange), expected)
81 |
82 | def suite():
83 | return unittest.TestLoader().loadTestsFromTestCase(OrgTimeRangeTestCase)
84 |
--------------------------------------------------------------------------------
/tests/test_plugin_date.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from __future__ import print_function
4 |
5 | import unittest
6 | import sys
7 | sys.path.append(u'../ftplugin')
8 |
9 | from datetime import date
10 | from datetime import datetime
11 |
12 | from orgmode.plugins.Date import Date
13 |
14 |
15 | class DateTestCase(unittest.TestCase):
16 | u"""Tests all the functionality of the Date plugin.
17 |
18 | Also see:
19 | http://orgmode.org/manual/The-date_002ftime-prompt.html#The-date_002ftime-prompt
20 | """
21 |
22 | def setUp(self):
23 | self.d = date(2011, 5, 22)
24 |
25 | def test_modify_time_with_None(self):
26 | # no modification should happen
27 | res = Date._modify_time(self.d, None)
28 | self.assertEquals(self.d, res)
29 |
30 | def test_modify_time_with_dot(self):
31 | # no modification should happen
32 | res = Date._modify_time(self.d, u'.')
33 | self.assertEquals(self.d, res)
34 |
35 | def test_modify_time_with_given_relative_days(self):
36 | # modifier and expected result
37 | test_data = [(u'+0d', self.d),
38 | (u'+1d', date(2011, 5, 23)),
39 | (u'+2d', date(2011, 5, 24)),
40 | (u'+7d', date(2011, 5, 29)),
41 | (u'+9d', date(2011, 5, 31)),
42 | (u'+10d', date(2011, 6, 1)),
43 | (u'7d', self.d)] # wrong format: plus is missing
44 |
45 | for modifier, expected in test_data:
46 | self.assertEquals(expected, Date._modify_time(self.d, modifier))
47 |
48 | def test_modify_time_with_given_relative_days_without_d(self):
49 | # modifier and expected result
50 | test_data = [(u'+0', self.d),
51 | (u'+1', date(2011, 5, 23)),
52 | (u'+2', date(2011, 5, 24)),
53 | (u'+7', date(2011, 5, 29)),
54 | (u'+9', date(2011, 5, 31)),
55 | (u'+10', date(2011, 6, 1))]
56 |
57 | for modifier, expected in test_data:
58 | result = Date._modify_time(self.d, modifier)
59 | self.assertEquals(expected, result)
60 |
61 | def test_modify_time_with_given_relative_weeks(self):
62 | # modifier and expected result
63 | test_data = [(u'+1w', date(2011, 5, 29)),
64 | (u'+2w', date(2011, 6, 5)),
65 | (u'+3w', date(2011, 6, 12)),
66 | (u'+3w', date(2011, 6, 12)),
67 | (u'+0w', self.d),
68 | (u'3w', self.d), # wrong format
69 | (u'+w', self.d)] # wrong format
70 |
71 | for modifier, expected in test_data:
72 | self.assertEquals(expected, Date._modify_time(self.d, modifier))
73 |
74 | def test_modify_time_with_given_relative_months(self):
75 | test_data = [(u'+0m', self.d),
76 | (u'+1m', date(2011, 6, 22)),
77 | (u'+2m', date(2011, 7, 22))]
78 |
79 | for modifier, expected in test_data:
80 | self.assertEquals(expected, Date._modify_time(self.d, modifier))
81 |
82 | def test_modify_time_with_given_relative_years(self):
83 | test_data = [(u'+1y', date(2012, 5, 22)),
84 | (u'+10y', date(2021, 5, 22)),
85 | (u'+0y', self.d)]
86 |
87 | for modifier, expected in test_data:
88 | self.assertEquals(expected, Date._modify_time(self.d, modifier))
89 |
90 |
91 | def test_modify_time_with_given_weekday(self):
92 | # use custom day instead of self.d to ease testing
93 | cust_day = date(2011, 5, 25) # it's a Wednesday
94 | #print(cust_day.weekday()) # 2
95 | test_data = [(u'Thu', date(2011, 5, 26)),
96 | (u'thu', date(2011, 5, 26)),
97 | (u'tHU', date(2011, 5, 26)),
98 | (u'THU', date(2011, 5, 26)),
99 | (u'Fri', date(2011, 5, 27)),
100 | (u'sat', date(2011, 5, 28)),
101 | (u'sun', date(2011, 5, 29)),
102 | (u'mon', date(2011, 5, 30)),
103 | (u'tue', date(2011, 5, 31)),
104 | (u'wed', date(2011, 6, 1))]
105 |
106 | for modifier, expected in test_data:
107 | self.assertEquals(expected, Date._modify_time(cust_day, modifier))
108 |
109 | def test_modify_time_with_month_and_day(self):
110 | cust_date = date(2006, 6, 13)
111 | test_data = [(u'sep 15', date(2006, 9, 15)),
112 | (u'Sep 15', date(2006, 9, 15)),
113 | (u'SEP 15', date(2006, 9, 15)),
114 | (u'feb 15', date(2007, 2, 15)),
115 | (u'jan 1', date(2007, 1, 1)),
116 | (u'7/5', date(2006, 7, 5)),
117 | (u'2/5', date(2007, 2, 5)),]
118 |
119 | for modifier, expected in test_data:
120 | self.assertEquals(expected, Date._modify_time(cust_date, modifier))
121 |
122 | def test_modify_time_with_time(self):
123 | cust_date = date(2006, 6, 13)
124 | test_data = [(u'12:45', datetime(2006, 6, 13, 12, 45)),
125 | (u'1:45', datetime(2006, 6, 13, 1, 45)),
126 | (u'1:05', datetime(2006, 6, 13, 1, 5)),]
127 |
128 | for modifier, expected in test_data:
129 | res = Date._modify_time(cust_date, modifier)
130 | self.assertTrue(isinstance(res, datetime))
131 | self.assertEquals(expected, res)
132 |
133 | def test_modify_time_with_full_dates(self):
134 | result = Date._modify_time(self.d, u'2011-01-12')
135 | expected = date(2011, 1, 12)
136 | self.assertEquals(expected, result)
137 |
138 | reults = Date._modify_time(self.d, u'2015-03-12')
139 | expected = date(2015, 3, 12)
140 | self.assertEquals(expected, reults)
141 |
142 | cust_date = date(2006, 6, 13)
143 | test_data = [(u'3-2-5', date(2003, 2, 5)),
144 | (u'12-2-28', date(2012, 2, 28)),
145 | (u'2/5/3', date(2003, 2, 5)),
146 | (u'sep 12 9', date(2009, 9, 12)),
147 | (u'jan 2 99', date(2099, 1, 2)),]
148 |
149 | for modifier, expected in test_data:
150 | self.assertEquals(expected, Date._modify_time(cust_date, modifier))
151 |
152 | def test_modify_time_with_only_days(self):
153 | cust_date = date(2006, 6, 13)
154 | test_data = [(u'14', date(2006, 6, 14)),
155 | (u'12', date(2006, 7, 12)),
156 | (u'1', date(2006, 7, 1)),
157 | (u'29', date(2006, 6, 29)),]
158 | for modifier, expected in test_data:
159 | self.assertEquals(expected, Date._modify_time(cust_date, modifier))
160 |
161 | def test_modify_time_with_day_and_time(self):
162 | cust_date = date(2006, 6, 13)
163 | test_data = [(u'+1 10:20', datetime(2006, 6, 14, 10, 20)),
164 | (u'+1w 10:20', datetime(2006, 6, 20, 10, 20)),
165 | (u'+2 10:30', datetime(2006, 6, 15, 10, 30)),
166 | (u'+2d 10:30', datetime(2006, 6, 15, 10, 30))]
167 | for modifier, expected in test_data:
168 | result = Date._modify_time(cust_date, modifier)
169 | self.assertEquals(expected, result)
170 |
171 | def suite():
172 | return unittest.TestLoader().loadTestsFromTestCase(DateTestCase)
173 |
--------------------------------------------------------------------------------
/tests/test_plugin_edit_checkbox.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import unittest
4 | import sys
5 | sys.path.append(u'../ftplugin')
6 |
7 | import vim
8 |
9 | from orgmode._vim import ORGMODE
10 |
11 | from orgmode.py3compat.encode_compatibility import *
12 |
13 | PLUGIN_NAME = u'EditCheckbox'
14 |
15 | bufnr = 10
16 |
17 | def set_vim_buffer(buf=None, cursor=(2, 0), bufnr=0):
18 | if buf is None:
19 | buf = []
20 | vim.current.buffer[:] = buf
21 | vim.current.window.cursor = cursor
22 | vim.current.buffer.number = bufnr
23 |
24 |
25 | counter = 0
26 | class EditCheckboxTestCase(unittest.TestCase):
27 | def setUp(self):
28 | if PLUGIN_NAME not in ORGMODE.plugins:
29 | ORGMODE.register_plugin(PLUGIN_NAME)
30 | self.editcheckbox = ORGMODE.plugins[PLUGIN_NAME]
31 | vim.EVALRESULTS = {
32 | # no org_todo_keywords for b
33 | u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
34 | # global values for org_todo_keywords
35 | u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
36 | u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
37 | u_encode(u'exists("g:org_improve_split_heading")'): u_encode(u'0'),
38 | u_encode(u'exists("b:org_improve_split_heading")'): u_encode(u'0'),
39 | u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
40 | u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
41 | u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
42 | u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
43 | u_encode(u'&ts'): u_encode(u'8'),
44 | u_encode(u'exists("g:org_tag_column")'): u_encode(u'0'),
45 | u_encode(u'exists("b:org_tag_column")'): u_encode(u'0'),
46 | u_encode(u"v:count"): u_encode(u'0'),
47 | # jump to insert mode after adding heading/checkbox
48 | u_encode(u'exists("g:org_prefer_insert_mode")'): u_encode(u'0'),
49 | u_encode(u'exists("b:org_prefer_insert_mode")'): u_encode(u'0')}
50 |
51 | self.c1 = u"""
52 | * heading1 [%]
53 | - [ ] checkbox1 [/]
54 | - [ ] checkbox2
55 | - [ ] checkbox3
56 | - [ ] checkbox4
57 | - [ ] checkbox5
58 | - [ ] checkbox6
59 | - [ ] checkbox7
60 | - [ ] checkbox8
61 | """.split(u'\n')
62 |
63 | self.c2 = u"""
64 | * a checkbox list [%]
65 | - checkbox [0%]
66 | - [ ] test1
67 | - [ ] test2
68 | - [ ] test3
69 | """.split(u'\n')
70 |
71 | self.c3 = u"""
72 | * heading
73 | 1. [ ] another main task [%]
74 | - [ ] sub task 1
75 | - [ ] sub task 2
76 | 2. [ ] another main task
77 | """.split(u'\n')
78 |
79 | self.c4 = u"""
80 | * heading
81 | """.split(u'\n')
82 |
83 | self.c5 = u"""
84 | * heading1
85 | 1. item
86 | 9. item
87 | }. item
88 | a. item
89 | z. item
90 | A. item
91 | Z. item
92 | aa. item
93 | """.split("\n")
94 |
95 | def test_toggle(self):
96 | global bufnr
97 | bufnr += 1
98 | # test on self.c1
99 | set_vim_buffer(buf=self.c1, cursor=(6, 0), bufnr=bufnr)
100 | # update_checkboxes_status
101 | self.editcheckbox.update_checkboxes_status()
102 | self.assertEqual(vim.current.buffer[1], u"* heading1 [0%]")
103 | # toggle
104 | self.editcheckbox.toggle()
105 | self.assertEqual(vim.current.buffer[5], u" - [X] checkbox4")
106 |
107 | bufnr += 1
108 | set_vim_buffer(buf=self.c1, cursor=(9, 0), bufnr=bufnr)
109 | # toggle and check checkbox status
110 | self.editcheckbox.toggle()
111 | self.assertEqual(vim.current.buffer[8], u" - [X] checkbox7")
112 | self.assertEqual(vim.current.buffer[7], u" - [-] checkbox6")
113 | self.assertEqual(vim.current.buffer[6], u" - [-] checkbox5")
114 |
115 | # new_checkbox
116 | bufnr += 1
117 | set_vim_buffer(buf=self.c1, cursor=(9, 0), bufnr=bufnr)
118 | vim.current.window.cursor = (9, 0)
119 | self.assertEqual(vim.current.buffer[9], u' - [ ] checkbox8')
120 | self.editcheckbox.new_checkbox(below=True)
121 | # vim's buffer behave just opposite to Python's list when inserting a
122 | # new item. The new entry is appended in vim put prepended in Python!
123 | self.assertEqual(vim.current.buffer[10], u' - [ ] checkbox8')
124 | self.assertEqual(vim.current.buffer[9], u' - [ ] ')
125 | self.editcheckbox.update_checkboxes_status()
126 |
127 | def test_no_status_checkbox(self):
128 | global bufnr
129 | bufnr += 1
130 | # test on self.c2
131 | set_vim_buffer(buf=self.c2, bufnr=bufnr)
132 | self.assertEqual(vim.current.buffer[2], u" - checkbox [0%]")
133 | # toggle
134 | vim.current.window.cursor = (4, 0)
135 | self.editcheckbox.toggle()
136 | self.assertEqual(vim.current.buffer[3], u" - [X] test1")
137 |
138 | # self.editcheckbox.update_checkboxes_status()
139 | # see if the no status checkbox update its status
140 | self.assertEqual(vim.current.buffer[2], u" - checkbox [33%]")
141 |
142 | def test_number_list(self):
143 | global bufnr
144 | bufnr += 1
145 | set_vim_buffer(buf=self.c3, bufnr=bufnr)
146 | vim.current.window.cursor = (6, 0)
147 | self.editcheckbox.toggle()
148 | self.assertEqual(vim.current.buffer[5], u" 2. [X] another main task")
149 |
150 | def test_new_checkbox(self):
151 | global bufnr
152 | bufnr += 1
153 | set_vim_buffer(buf=self.c4, bufnr=bufnr)
154 | vim.current.window.cursor = (2, 1)
155 | self.editcheckbox.new_checkbox(below=True)
156 | self.assertEqual(vim.current.buffer[2], u" - [ ] ")
157 |
158 | def test_item_decrement(self):
159 | global bufnr
160 | bufnr += 1
161 | set_vim_buffer(buf=self.c5, bufnr=bufnr)
162 |
163 | vim.current.window.cursor = (3, 1)
164 | self.editcheckbox.new_checkbox(below=False, plain=True)
165 | self.assertEqual(vim.current.buffer[2], u" 0. ")
166 | self.assertEqual(vim.current.buffer[3], u" 1. item")
167 |
168 | vim.current.window.cursor = (3, 1)
169 | self.editcheckbox.new_checkbox(below=False, plain=True)
170 | self.assertEqual(vim.current.buffer[1], u"* heading1")
171 | self.assertEqual(vim.current.buffer[2], u" 0. ")
172 | self.assertEqual(vim.current.buffer[3], u" 1. item")
173 |
174 | vim.current.window.cursor = (5, 1)
175 | self.editcheckbox.new_checkbox(below=False, plain=True)
176 | self.assertEqual(vim.current.buffer[4], u" 8. ")
177 | self.assertEqual(vim.current.buffer[5], u" 9. item")
178 |
179 | vim.current.window.cursor = (8, 1)
180 | self.editcheckbox.new_checkbox(below=False, plain=True)
181 | # no further decrement than a
182 | self.assertEqual(vim.current.buffer[6], u" }. item")
183 | self.assertEqual(vim.current.buffer[7], u" a. item")
184 | self.assertEqual(vim.current.buffer[8], u" z. item")
185 |
186 | def test_item_decrementA(self):
187 | global bufnr
188 | bufnr += 1
189 | set_vim_buffer(buf=self.c5, bufnr=bufnr)
190 | vim.current.window.cursor = (8, 1)
191 | self.editcheckbox.new_checkbox(below=False, plain=True)
192 | # decrement from A to z
193 | self.assertEqual(vim.current.buffer[7], u" z. ")
194 | self.assertEqual(vim.current.buffer[8], u" A. item")
195 |
196 | def test_item_increment(self):
197 | global bufnr
198 | bufnr += 1
199 | set_vim_buffer(buf=self.c5, bufnr=bufnr)
200 |
201 | vim.current.window.cursor = (3, 1)
202 | self.editcheckbox.new_checkbox(below=True, plain=True)
203 | self.assertEqual(vim.current.buffer[2], u" 1. item")
204 | self.assertEqual(vim.current.buffer[3], u" 2. ")
205 |
206 | vim.current.window.cursor = (5, 1)
207 | self.editcheckbox.new_checkbox(below=True, plain=True)
208 | self.assertEqual(vim.current.buffer[4], u" 9. item")
209 | self.assertEqual(vim.current.buffer[5], u" }. item")
210 | self.assertEqual(vim.current.buffer[6], u" 10. ")
211 |
212 | def test_item_incrementz(self):
213 | global bufnr
214 | bufnr += 1
215 | set_vim_buffer(buf=self.c5, bufnr=bufnr)
216 |
217 | vim.current.window.cursor = (6, 1)
218 | self.editcheckbox.new_checkbox(below=True, plain=True)
219 | self.assertEqual(vim.current.buffer[5], u" a. item")
220 | self.assertEqual(vim.current.buffer[6], u" b. ")
221 |
222 | vim.current.window.cursor = (8, 1)
223 | self.editcheckbox.new_checkbox(below=True, plain=True)
224 | self.assertEqual(vim.current.buffer[7], u" z. item")
225 | self.assertEqual(vim.current.buffer[8], u" A. ")
226 |
227 | vim.current.window.cursor = (11, 1)
228 | self.editcheckbox.new_checkbox(below=True, plain=True)
229 | self.assertEqual(vim.current.buffer[10], u" Z. item")
230 | self.assertEqual(vim.current.buffer[11], u" aa. item")
231 | self.assertEqual(vim.current.buffer[12], u"")
232 |
233 | vim.current.window.cursor = (12, 1)
234 | self.editcheckbox.new_checkbox(below=True, plain=True)
235 | self.assertEqual(vim.current.buffer[11], u" aa. item")
236 | self.assertEqual(vim.current.buffer[12], u"")
237 |
238 | def suite():
239 | return unittest.TestLoader().loadTestsFromTestCase(EditCheckboxTestCase)
240 |
--------------------------------------------------------------------------------
/tests/test_plugin_mappings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from __future__ import print_function
4 |
5 | import sys
6 | sys.path.append(u'../ftplugin')
7 |
8 | import unittest
9 | import orgmode.settings
10 | from orgmode.exceptions import PluginError
11 | from orgmode._vim import ORGMODE
12 | from orgmode.keybinding import MODE_ALL, Plug
13 |
14 | import vim
15 |
16 | from orgmode.py3compat.encode_compatibility import *
17 |
18 | ORG_PLUGINS = ['ShowHide', '|', 'Navigator', 'EditStructure', '|', 'Hyperlinks', '|', 'Todo', 'TagsProperties', 'Date', 'Agenda', 'Misc', '|', 'Export']
19 |
20 |
21 | class MappingTestCase(unittest.TestCase):
22 | u"""Tests all plugins for overlapping mappings."""
23 | def test_non_overlapping_plug_mappings(self):
24 | def find_overlapping_mappings(kb, all_keybindings):
25 | found_overlapping_mapping = False
26 | for tkb in all_keybindings:
27 | if kb.mode == tkb.mode or MODE_ALL in (kb.mode, tkb.mode):
28 | if isinstance(kb._action, Plug) and isinstance(tkb._action, Plug):
29 | akb = kb.action
30 | atkb = tkb.action
31 | if (akb.startswith(atkb) or atkb.startswith(akb)) and akb != atkb:
32 | print(u'\nERROR: Found overlapping mapping: %s (%s), %s (%s)' % (kb.key, akb, tkb.key, atkb))
33 | found_overlapping_mapping = True
34 |
35 | if all_keybindings:
36 | res = find_overlapping_mappings(all_keybindings[0], all_keybindings[1:])
37 | if not found_overlapping_mapping:
38 | return res
39 | return found_overlapping_mapping
40 |
41 | if self.keybindings:
42 | self.assertFalse(find_overlapping_mappings(self.keybindings[0], self.keybindings[1:]))
43 |
44 | def setUp(self):
45 | self.keybindings = []
46 |
47 | vim.EVALRESULTS = {
48 | u'exists("g:org_debug")': 0,
49 | u'exists("b:org_debug")': 0,
50 | u'exists("*repeat#set()")': 0,
51 | u'b:changedtick': 0,
52 | u_encode(u'exists("b:org_plugins")'): 0,
53 | u_encode(u'exists("g:org_plugins")'): 1,
54 | u_encode(u'g:org_plugins'): ORG_PLUGINS,
55 | }
56 | for plugin in filter(lambda p: p != '|', ORG_PLUGINS):
57 | try:
58 | ORGMODE.register_plugin(plugin)
59 | except PluginError:
60 | pass
61 | if plugin in ORGMODE._plugins:
62 | self.keybindings.extend(ORGMODE._plugins[plugin].keybindings)
63 |
64 |
65 | def suite():
66 | return unittest.TestLoader().loadTestsFromTestCase(MappingTestCase)
67 |
--------------------------------------------------------------------------------
/tests/test_plugin_misc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import unittest
5 | import sys
6 | sys.path.append(u'../ftplugin')
7 |
8 | import vim
9 |
10 | from orgmode._vim import indent_orgmode, fold_orgmode, ORGMODE
11 |
12 | from orgmode.py3compat.encode_compatibility import *
13 |
14 | ORGMODE.debug = True
15 |
16 | START = True
17 | END = False
18 |
19 | counter = 0
20 | class MiscTestCase(unittest.TestCase):
21 | def setUp(self):
22 | global counter
23 | counter += 1
24 | vim.CMDHISTORY = []
25 | vim.CMDRESULTS = {}
26 | vim.EVALHISTORY = []
27 | vim.EVALRESULTS = {
28 | # no org_todo_keywords for b
29 | u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
30 | # global values for org_todo_keywords
31 | u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
32 | u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
33 | u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
34 | u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
35 | u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
36 | u_encode(u"v:count"): u_encode(u'0'),
37 | u_encode(u'b:changedtick'): u_encode(u'%d' % counter),
38 | u_encode(u"v:lnum"): u_encode(u'0')}
39 | vim.current.buffer[:] = [ u_encode(i) for i in u"""
40 | * Überschrift 1
41 | Text 1
42 |
43 | Bla bla
44 | ** Überschrift 1.1
45 | Text 2
46 |
47 | Bla Bla bla
48 | ** Überschrift 1.2
49 | Text 3
50 |
51 | **** Überschrift 1.2.1.falsch
52 |
53 | Bla Bla bla bla
54 | *** Überschrift 1.2.1
55 | * Überschrift 2
56 | * Überschrift 3
57 | asdf sdf
58 | """.split(u'\n') ]
59 |
60 | def test_indent_noheading(self):
61 | # test first heading
62 | vim.current.window.cursor = (1, 0)
63 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'1')
64 | indent_orgmode()
65 | self.assertEqual(len(vim.CMDHISTORY), 0)
66 |
67 | def test_indent_heading(self):
68 | # test first heading
69 | vim.current.window.cursor = (2, 0)
70 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'2')
71 | indent_orgmode()
72 | self.assertEqual(len(vim.CMDHISTORY), 0)
73 |
74 | def test_indent_heading_middle(self):
75 | # test first heading
76 | vim.current.window.cursor = (3, 0)
77 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'3')
78 | indent_orgmode()
79 | self.assertEqual(len(vim.CMDHISTORY), 1)
80 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:indent_level = 2'))
81 |
82 | def test_indent_heading_middle2(self):
83 | # test first heading
84 | vim.current.window.cursor = (4, 0)
85 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'4')
86 | indent_orgmode()
87 | self.assertEqual(len(vim.CMDHISTORY), 1)
88 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:indent_level = 2'))
89 |
90 | def test_indent_heading_end(self):
91 | # test first heading
92 | vim.current.window.cursor = (5, 0)
93 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'5')
94 | indent_orgmode()
95 | self.assertEqual(len(vim.CMDHISTORY), 1)
96 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:indent_level = 2'))
97 |
98 | def test_fold_heading_start(self):
99 | # test first heading
100 | vim.current.window.cursor = (2, 0)
101 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'2')
102 | fold_orgmode()
103 | self.assertEqual(len(vim.CMDHISTORY), 1)
104 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">1"'))
105 |
106 | def test_fold_heading_middle(self):
107 | # test first heading
108 | vim.current.window.cursor = (3, 0)
109 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'3')
110 | fold_orgmode()
111 | self.assertEqual(len(vim.CMDHISTORY), 1)
112 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 1'))
113 |
114 | def test_fold_heading_end(self):
115 | # test first heading
116 | vim.current.window.cursor = (5, 0)
117 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'5')
118 | fold_orgmode()
119 | self.assertEqual(len(vim.CMDHISTORY), 1)
120 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 1'))
121 |
122 | def test_fold_heading_end_of_last_child(self):
123 | # test first heading
124 | vim.current.window.cursor = (16, 0)
125 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'16')
126 | fold_orgmode()
127 | self.assertEqual(len(vim.CMDHISTORY), 1)
128 | # which is also end of the parent heading <1
129 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">3"'))
130 |
131 | def test_fold_heading_end_of_last_child_next_heading(self):
132 | # test first heading
133 | vim.current.window.cursor = (17, 0)
134 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'17')
135 | fold_orgmode()
136 | self.assertEqual(len(vim.CMDHISTORY), 1)
137 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">1"'))
138 |
139 | def test_fold_middle_subheading(self):
140 | # test first heading
141 | vim.current.window.cursor = (13, 0)
142 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'13')
143 | fold_orgmode()
144 | self.assertEqual(len(vim.CMDHISTORY), 1)
145 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = ">4"'))
146 |
147 | def test_fold_middle_subheading2(self):
148 | # test first heading
149 | vim.current.window.cursor = (14, 0)
150 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'14')
151 | fold_orgmode()
152 | self.assertEqual(len(vim.CMDHISTORY), 1)
153 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 4'))
154 |
155 | def test_fold_middle_subheading3(self):
156 | # test first heading
157 | vim.current.window.cursor = (15, 0)
158 | vim.EVALRESULTS[u_encode(u'v:lnum')] = u_encode(u'15')
159 | fold_orgmode()
160 | self.assertEqual(len(vim.CMDHISTORY), 1)
161 | self.assertEqual(vim.CMDHISTORY[-1], u_encode(u'let b:fold_expr = 4'))
162 |
163 | def suite():
164 | return unittest.TestLoader().loadTestsFromTestCase(MiscTestCase)
165 |
--------------------------------------------------------------------------------
/tests/test_plugin_tags_properties.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import unittest
5 | import sys
6 | sys.path.append(u'../ftplugin')
7 |
8 | import vim
9 |
10 | from orgmode._vim import indent_orgmode, fold_orgmode, ORGMODE
11 |
12 | from orgmode.py3compat.encode_compatibility import *
13 |
14 | ORGMODE.debug = True
15 |
16 | START = True
17 | END = False
18 |
19 | counter = 0
20 | class TagsPropertiesTestCase(unittest.TestCase):
21 | def setUp(self):
22 | global counter
23 | counter += 1
24 | vim.CMDHISTORY = []
25 | vim.CMDRESULTS = {}
26 | vim.EVALHISTORY = []
27 | vim.EVALRESULTS = {
28 | # no org_todo_keywords for b
29 | u_encode(u'exists("b:org_todo_keywords")'): u_encode('0'),
30 | # global values for org_todo_keywords
31 | u_encode(u'exists("g:org_todo_keywords")'): u_encode('1'),
32 | u_encode(u'g:org_todo_keywords'): [u_encode(u'TODO'), u_encode(u'|'), u_encode(u'DONE')],
33 | u_encode(u'&ts'): u_encode(u'6'),
34 | u_encode(u'exists("b:org_tag_column")'): u_encode(u'0'),
35 | u_encode(u'exists("g:org_tag_column")'): u_encode(u'0'),
36 | u_encode(u'exists("g:org_debug")'): u_encode(u'0'),
37 | u_encode(u'exists("b:org_debug")'): u_encode(u'0'),
38 | u_encode(u'exists("*repeat#set()")'): u_encode(u'0'),
39 | u_encode(u'b:changedtick'): (u_encode(u'%d' % counter)),
40 | u_encode(u"v:count"): u_encode(u'0')}
41 | if not u'TagsProperties' in ORGMODE.plugins:
42 | ORGMODE.register_plugin(u'TagsProperties')
43 | self.tagsproperties = ORGMODE.plugins[u'TagsProperties']
44 | vim.current.buffer[:] = [ u_encode(i) for i in u"""
45 | * Überschrift 1
46 | Text 1
47 |
48 | Bla bla
49 | ** Überschrift 1.1
50 | Text 2
51 |
52 | Bla Bla bla
53 | ** Überschrift 1.2
54 | Text 3
55 |
56 | **** Überschrift 1.2.1.falsch
57 |
58 | Bla Bla bla bla
59 | *** Überschrift 1.2.1
60 | * Überschrift 2
61 | * Überschrift 3
62 | asdf sdf
63 | """.split(u'\n') ]
64 |
65 | def test_new_property(self):
66 | u""" TODO: Docstring for test_new_property
67 |
68 | :returns: TODO
69 | """
70 | pass
71 |
72 | def test_set_tags(self):
73 | # set first tag
74 | vim.current.window.cursor = (2, 0)
75 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:')
76 | self.tagsproperties.set_tags()
77 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
78 |
79 | # set second tag
80 | vim.EVALRESULTS[u_encode(u'input("Tags: ", ":hello:", "customlist,Org_complete_tags")')] = u_encode(u':hello:world:')
81 | self.tagsproperties.set_tags()
82 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
83 |
84 | def test_parse_tags_no_colons_single_tag(self):
85 | vim.current.window.cursor = (2, 0)
86 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello')
87 | self.tagsproperties.set_tags()
88 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
89 |
90 | def test_parse_tags_no_colons_multiple_tags(self):
91 | vim.current.window.cursor = (2, 0)
92 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello:world')
93 | self.tagsproperties.set_tags()
94 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
95 |
96 | def test_parse_tags_single_colon_left_single_tag(self):
97 | vim.current.window.cursor = (2, 0)
98 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello')
99 | self.tagsproperties.set_tags()
100 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
101 |
102 | def test_parse_tags_single_colon_left_multiple_tags(self):
103 | vim.current.window.cursor = (2, 0)
104 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:world')
105 | self.tagsproperties.set_tags()
106 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
107 |
108 | def test_parse_tags_single_colon_right_single_tag(self):
109 | vim.current.window.cursor = (2, 0)
110 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello:')
111 | self.tagsproperties.set_tags()
112 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
113 |
114 | def test_parse_tags_single_colon_right_multiple_tags(self):
115 | vim.current.window.cursor = (2, 0)
116 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'hello:world:')
117 | self.tagsproperties.set_tags()
118 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
119 |
120 | def test_filter_empty_tags(self):
121 | vim.current.window.cursor = (2, 0)
122 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u'::hello::')
123 | self.tagsproperties.set_tags()
124 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
125 |
126 | def test_delete_tags(self):
127 | # set up
128 | vim.current.window.cursor = (2, 0)
129 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:world:')
130 | self.tagsproperties.set_tags()
131 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
132 |
133 | # delete second of two tags
134 | vim.EVALRESULTS[u_encode(u'input("Tags: ", ":hello:world:", "customlist,Org_complete_tags")')] = u_encode(u':hello:')
135 | self.tagsproperties.set_tags()
136 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t\t :hello:'))
137 |
138 | # delete last tag
139 | vim.EVALRESULTS[u_encode(u'input("Tags: ", ":hello:", "customlist,Org_complete_tags")')] = u_encode(u'')
140 | self.tagsproperties.set_tags()
141 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
142 |
143 | def test_realign_tags_noop(self):
144 | vim.current.window.cursor = (2, 0)
145 | self.tagsproperties.realign_tags()
146 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
147 |
148 | def test_realign_tags_remove_spaces(self):
149 | # remove spaces in multiple locations
150 | vim.current.buffer[1] = u_encode(u'* Überschrift 1 ')
151 | vim.current.window.cursor = (2, 0)
152 | self.tagsproperties.realign_tags()
153 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
154 |
155 | # remove tabs and spaces in multiple locations
156 | vim.current.buffer[1] = u_encode(u'*\t \tÜberschrift 1 \t')
157 | vim.current.window.cursor = (2, 0)
158 | self.tagsproperties.realign_tags()
159 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1'))
160 |
161 | def test_realign_tags(self):
162 | vim.current.window.cursor = (2, 0)
163 | vim.EVALRESULTS[u_encode(u'input("Tags: ", "", "customlist,Org_complete_tags")')] = u_encode(u':hello:world:')
164 | self.tagsproperties.set_tags()
165 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
166 |
167 | d = ORGMODE.get_document()
168 | heading = d.find_current_heading()
169 | self.assertEqual(str(heading), u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
170 | self.tagsproperties.realign_tags()
171 | heading = d.find_current_heading()
172 | self.assertEqual(str(heading), u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
173 | self.assertEqual(vim.current.buffer[1], u_encode(u'* Überschrift 1\t\t\t\t\t\t\t\t :hello:world:'))
174 |
175 | def suite():
176 | return unittest.TestLoader().loadTestsFromTestCase(TagsPropertiesTestCase)
177 |
--------------------------------------------------------------------------------
/tests/vim.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | class VimWindow(object):
5 | u""" Docstring for VimWindow """
6 |
7 | def __init__(self, test):
8 | object.__init__(self)
9 | self._test = test
10 | self.cursor = (1, 0)
11 |
12 | def buffer():
13 | def fget(self):
14 | return self._test.buffer
15 |
16 | def fset(self, value):
17 | self._test.buffer = value
18 | return locals()
19 | buffer = property(**buffer())
20 |
21 |
22 | class VimBuffer(list):
23 | def __init__(self, iterable=None):
24 | self.number = 0
25 | if iterable is not None:
26 | list.__init__(self, iterable)
27 | else:
28 | list.__init__(self)
29 |
30 | def append(self, o):
31 | u"""
32 | mimic the specific behavior of vim.current.buffer
33 | """
34 | if isinstance(o, list) or isinstance(o, tuple):
35 | for i in o:
36 | list.append(self, i)
37 | else:
38 | list.append(self, o)
39 |
40 |
41 | class VimTest(object):
42 | u""" Replacement for vim API """
43 |
44 | def __init__(self):
45 | object.__init__(self)
46 | self._buffer = VimBuffer()
47 | self.window = VimWindow(self)
48 |
49 | def buffer():
50 | def fget(self):
51 | return self._buffer
52 |
53 | def fset(self, value):
54 | self._buffer = VimBuffer(value)
55 | return locals()
56 | buffer = property(**buffer())
57 |
58 |
59 | EVALHISTORY = []
60 | EVALRESULTS = {
61 | u'exists("g:org_debug")': 0,
62 | u'exists("b:org_debug")': 0,
63 | u'exists("*repeat#set()")': 0,
64 | u'exists("b:org_plugins")': 0,
65 | u'exists("g:org_plugins")': 0,
66 | u'b:changedtick': 0,
67 | }
68 |
69 |
70 | def eval(cmd):
71 | u""" evaluate command
72 |
73 | :returns: results stored in EVALRESULTS
74 | """
75 | EVALHISTORY.append(cmd)
76 | return EVALRESULTS.get(cmd, None)
77 |
78 |
79 | CMDHISTORY = []
80 | CMDRESULTS = {}
81 |
82 |
83 | def command(cmd):
84 | CMDHISTORY.append(cmd)
85 | return CMDRESULTS.get(cmd, None)
86 |
87 |
88 | current = VimTest()
89 |
--------------------------------------------------------------------------------