Пример #1
0
    def create(self):
        from orgmode._vim import ORGMODE, echom

        cmd = self._mode
        if cmd == MODE_ALL:
            cmd = u''
        if not self._remap:
            cmd += u'nore'
        try:
            create_mapping = True
            if isinstance(self._action, Plug):
                # create plug
                self._action.create()
                if int(
                        vim.eval((u'hasmapto("%s")' %
                                  (self._action, )).encode(u'utf-8'))):
                    create_mapping = False
            if isinstance(self._action, Command):
                # create command
                self._action.create()

            if create_mapping:
                vim.command((u':%smap %s %s %s' % (cmd, u' '.join(
                    self._options), self._key, self._action)).encode(u'utf-8'))
        except Exception, e:
            if ORGMODE.debug:
                echom(u'Failed to register key binding %s %s' %
                      (self._key, self._action))
Пример #2
0
	def tolatex(cls):
		u"""Export the current buffer as latex using emacs orgmode."""
		ret = cls._export(u'org-latex-export-to-latex')
		if ret != 0:
			echoe(u'latex export failed.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'tex'))
Пример #3
0
	def tobeamer(cls):
		u"""Export the current buffer as beamer pdf using emacs orgmode."""
		ret = cls._export(u'org-beamer-export-to-pdf')
		if ret != 0:
			echoe(u'PDF export failed.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'pdf'))
Пример #4
0
    def _export(cls, format_):
        """Export current file to format.

		Args:
			format_: pdf or html

		Returns:
			return code
		"""
        emacsbin = os.path.expandvars(
            os.path.expanduser(
                settings.get(u'org_export_emacs', u'/usr/bin/emacs')))
        if not os.path.exists(emacsbin):
            echoe(u'Unable to find emacs binary %s' % emacsbin)

        # build the export command
        cmd = [
            emacsbin, u'-nw', u'--batch',
            u'--visit=%s' % vim.eval(u'expand("%:p")'),
            u'--funcall=%s' % format_
        ]
        # source init script as well
        init_script = cls._get_init_script()
        if init_script:
            cmd.extend(['--script', init_script])

        # export
        p = subprocess.Popen(cmd,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        p.wait()

        if p.returncode != 0 or settings.get(u'org_export_verbose') == 1:
            echom('\n'.join(p.communicate()))
        return p.returncode
Пример #5
0
def split_access_key(t, sub=None):
    u""" Split access key

	Args:
		t (str): Todo state
		sub: A value that will be returned instead of access key if there was
			not access key

	Returns:
		tuple: Todo state and access key separated (TODO, ACCESS_KEY)

	Example:
		>>> split_access_key('TODO(t)')
		>>> ('TODO', '(t)')
		>>> split_access_key('WANT', sub='(hi)')
		>>> ('WANT', '(hi)')
	"""
    if type(t) != unicode:
        echom("String must be unicode")
        return (None, None)

    idx = t.find(u'(')

    v, k = (t, sub)
    if idx != -1 and t[idx + 1:-1]:
        v, k = (t[:idx], t[idx + 1:-1])
    return (v, k)
Пример #6
0
	def tohtml(cls):
		u"""Export the current buffer as html using emacs orgmode."""
		ret = cls._export(u'html')
		if ret != 0:
			echoe(u'HTML export failed.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'html'))
Пример #7
0
    def follow(cls, action=u'openLink', visual=u''):
        u""" Follow hyperlink. If called on a regular string UTL determines the
		outcome. Normally a file with that name will be opened.

		:action: "copy" if the link should be copied to clipboard, otherwise
				the link will be opened
		:visual: "visual" if Universal Text Linking should be triggered in
				visual mode

		:returns: URI or None
		"""
        if not int(vim.eval(u'exists(":Utl")')):
            echom(
                u'Universal Text Linking plugin not installed, unable to proceed.'
            )
            return

        action = u'copyLink' \
         if (action and action.startswith(u'copy')) \
         else u'openLink'
        visual = u'visual' if visual and visual.startswith(u'visual') else u''

        link = Hyperlinks._get_link()

        if link and link[u'uri'] is not None:
            # call UTL with the URI
            vim.command(
                u_encode(u'Utl %s %s %s' % (action, visual, link[u'uri'])))
            return link[u'uri']
        else:
            # call UTL and let it decide what to do
            vim.command(u_encode(u'Utl %s %s' % (action, visual)))
Пример #8
0
def split_access_key(t, sub=None):
	u""" Split access key

	Args:
		t (str): Todo state
		sub: A value that will be returned instead of access key if there was
			not access key

	Returns:
		tuple: Todo state and access key separated (TODO, ACCESS_KEY)

	Example:
		>>> split_access_key('TODO(t)')
		>>> ('TODO', '(t)')
		>>> split_access_key('WANT', sub='(hi)')
		>>> ('WANT', '(hi)')
	"""
	if type(t) != unicode:
		echom("String must be unicode")
		return (None, None)

	idx = t.find(u'(')

	v, k = (t, sub)
	if idx != -1 and t[idx + 1:-1]:
		v, k = (t[:idx], t[idx + 1:-1])
	return (v, k)
Пример #9
0
	def topdf(cls):
		u"""Export the current buffer as pdf using emacs orgmode."""
		ret = cls._export(u'pdf')
		if ret != 0:
			echoe(u'PDF export failed.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'pdf'))
Пример #10
0
    def _export(cls, _format):
        """ Export current file in out format

		:flavor:	pdf or html
		:returns:	return code
		"""
        f = _format if _format == 'pdf' else 'html'
        emacs = os.path.expandvars(os.path.expanduser( \
          settings.get(u'org_export_emacs', u'/usr/bin/emacs')))
        if os.path.exists(emacs):
            cmd = [emacs, u'-nw', u'--batch', u'--visit=%s' \
              % (vim.eval(u'expand("%:p")'), ), \
              u'--funcall=org-export-as-%s' % f]

            # source init script as well
            init_script = cls._get_init_script()
            if init_script:
                cmd.extend(['--script', init_script])
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, \
              stderr=subprocess.PIPE)
            p.wait()
            if p.returncode != 0 or settings.get(u'org_export_verbose') == 1:
                echom('\n'.join(p.communicate()))

            return p.returncode
        else:
            echoe(u'Unable to find emacs binary %s' % emacs)
Пример #11
0
	def tohtml(cls):
		u"""Export the current buffer as html using emacs orgmode."""
		ret = cls._export(u'org-html-export-to-html')
		if ret != 0:
			echoe(u'HTML export failed.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'html'))
Пример #12
0
	def tomarkdown(cls):
		u"""Export the current buffer as markdown using emacs orgmode."""
		ret = cls._export(u'org-md-export-to-markdown')
		if ret != 0:
			echoe('Markdown export failed. Make sure org-md-export-to-markdown is loaded in emacs, see the manual for details.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'md'))
Пример #13
0
	def _export(cls, _format):
		""" Export current file in out format

		:flavor:	pdf or html
		:returns:	return code
		"""
		f = _format if _format == 'pdf' else 'html'
		emacs = os.path.expandvars(os.path.expanduser( \
				settings.get(u'org_export_emacs', u'/usr/bin/emacs')))
		if os.path.exists(emacs):
			cmd = [emacs, u'-nw', u'--batch', u'--visit=%s' \
					% (vim.eval(u'expand("%:p")'), ), \
					u'--funcall=org-export-as-%s' % f]

			# source init script as well
			init_script = cls._get_init_script()
			if init_script:
				cmd.extend(['--script', init_script])
			p = subprocess.Popen(cmd, stdout=subprocess.PIPE, \
					stderr=subprocess.PIPE)
			p.wait()
			if p.returncode != 0 or settings.get(u'org_export_verbose') == 1:
				echom('\n'.join(p.communicate()))

			return p.returncode
		else:
			echoe(u'Unable to find emacs binary %s' % emacs)
Пример #14
0
	def follow(cls, action=u'openLink', visual=u''):
		u""" Follow hyperlink. If called on a regular string UTL determines the
		outcome. Normally a file with that name will be opened.

		:action: "copy" if the link should be copied to clipboard, otherwise
				the link will be opened
		:visual: "visual" if Universal Text Linking should be triggered in
				visual mode

		:returns: URI or None
		"""
		if not int(vim.eval(u'exists(":Utl")')):
			echom(u'Universal Text Linking plugin not installed, unable to proceed.')
			return

		action = u'copyLink' \
			if (action and action.startswith(u'copy')) \
			else u'openLink'
		visual = u'visual' if visual and visual.startswith(u'visual') else u''

		link = Hyperlinks._get_link()

		if link and link[u'uri'] is not None:
			# call UTL with the URI
			vim.command(u_encode((u'Utl %s %s %s' % (action, visual, link[u'uri']))))
			return link[u'uri']
		else:
			# call UTL and let it decide what to do
			vim.command(u_encode((u'Utl %s %s' % (action, visual))))
Пример #15
0
	def tomarkdown(cls):
		u"""Export the current buffer as markdown using emacs orgmode."""
		ret = cls._export(u'org-md-export-to-markdown')
		if ret != 0:
			echoe('Markdown export failed. Make sure org-md-export-to-markdown is loaded in emacs, see the manual for details.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'md'))
Пример #16
0
    def __init__(self):
        u""" Initialize plugin """
        object.__init__(self)
        # menu entries this plugin should create
        self.menu = ORGMODE.orgmenu + Submenu(u'Dates and Scheduling')

        # key bindings for this plugin
        # key bindings are also registered through the menu so only additional
        # bindings should be put in this variable
        self.keybindings = []

        # commands for this plugin
        self.commands = []

        # set speeddating format that is compatible with orgmode
        try:
            if int(vim.eval(
                    u'exists(":SpeedDatingFormat")'.encode(u'utf-8'))) == 2:
                vim.command(
                    u':1SpeedDatingFormat %Y-%m-%d %a'.encode(u'utf-8'))
                vim.command(
                    u':1SpeedDatingFormat %Y-%m-%d %a %H:%M'.encode(u'utf-8'))
            else:
                echom(u'Speeddating plugin not installed. Please install it.')
        except:
            echom(u'Speeddating plugin not installed. Please install it.')
Пример #17
0
	def _export(cls, format_):
		"""Export current file to format_.

		:format_:  pdf or html
		:returns:  return code
		"""
		emacsbin = os.path.expandvars(os.path.expanduser(
			settings.get(u'org_export_emacs', u'/usr/bin/emacs')))
		if not os.path.exists(emacsbin):
			echoe(u'Unable to find emacs binary %s' % emacsbin)

		# build the export command
		cmd = [
			emacsbin,
			u'-nw',
			u'--batch',
			u'--visit=%s' % vim.eval(u'expand("%:p")'),
			u'--funcall=%s' % format_
		]
		# source init script as well
		init_script = cls._get_init_script()
		if init_script:
			cmd.extend(['--script', init_script])

		# export
		p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
		p.wait()

		if p.returncode != 0 or settings.get(u'org_export_verbose') == 1:
			echom('\n'.join(p.communicate()))
		return p.returncode
Пример #18
0
	def tolatex(cls):
		u"""Export the current buffer as latex using emacs orgmode."""
		ret = cls._export(u'latex')
		if ret != 0:
			echoe(u'latex export failed.')
		else:
			echom(u'Export successful: %s.%s' % (vim.eval(u'expand("%:r")'), 'tex'))
Пример #19
0
    def init_org_todo(cls):
        u""" Initialize org todo selection window.
		"""
        bufnr = int(re.findall('\d+$', vim.current.buffer.name)[0])
        all_states = ORGTODOSTATES.get(bufnr, None)

        vim_commands = [
            u'let g:org_sav_timeoutlen=&timeoutlen',
            u'au orgmode BufEnter <buffer> :if ! exists("g:org_sav_timeoutlen")|let g:org_sav_timeoutlen=&timeoutlen|set timeoutlen=1|endif',
            u'au orgmode BufLeave <buffer> :if exists("g:org_sav_timeoutlen")|let &timeoutlen=g:org_sav_timeoutlen|unlet g:org_sav_timeoutlen|endif',
            u'setlocal nolist tabstop=16 buftype=nofile timeout timeoutlen=1 winfixheight',
            u'setlocal statusline=Org\\ todo\\ (%s)' % vim.eval(
                u_encode(
                    u'fnameescape(fnamemodify(bufname(%d), ":t"))' % bufnr)),
            u'nnoremap <silent> <buffer> <Esc> :%sbw<CR>' %
            vim.eval(u_encode(u'bufnr("%")')),
            u'nnoremap <silent> <buffer> <CR> :let g:org_state = fnameescape(expand("<cword>"))<Bar>bw<Bar>exec "%s ORGMODE.plugins[u\'Todo\'].set_todo_state(\'".g:org_state."\')"<Bar>unlet! g:org_state<CR>'
            % VIM_PY_CALL,
        ]
        # because timeoutlen can only be set globally it needs to be stored and
        # restored later
        # make window a scratch window and set the statusline differently
        for cmd in vim_commands:
            vim.command(u_encode(cmd))

        if all_states is None:
            vim.command(u_encode(u'bw'))
            echom(u'No todo states avaiable for buffer %s' %
                  vim.current.buffer.name)

        for idx, state in enumerate(all_states):
            pairs = [split_access_key(x, sub=u' ') for x in it.chain(*state)]
            line = u'\t'.join(u''.join((u'[%s] ' % x[1], x[0])) for x in pairs)
            vim.current.buffer.append(u_encode(line))
            for todo, key in pairs:
                # FIXME if double key is used for access modified this doesn't work
                vim.command(
                    u_encode(
                        u'nnoremap <silent> <buffer> %s :bw<CR><c-w><c-p>%s ORGMODE.plugins[u"Todo"].set_todo_state("%s")<CR>'
                        % (key, VIM_PY_CALL, u_decode(todo))))

        # position the cursor of the current todo item
        vim.command(u_encode(u'normal! G'))
        current_state = settings.unset(u'org_current_state_%d' % bufnr)
        if current_state is not None and current_state != '':
            for i, buf in enumerate(vim.current.buffer):
                idx = buf.find(current_state)
                if idx != -1:
                    vim.current.window.cursor = (i + 1, idx)
                    break
            else:
                vim.current.window.cursor = (2, 4)

        # finally make buffer non modifiable
        vim.command(u_encode(u'setfiletype orgtodo'))
        vim.command(u_encode(u'setlocal nomodifiable'))

        # remove temporary todo states for the current buffer
        del ORGTODOSTATES[bufnr]
Пример #20
0
	def toggle_todo_state(
		cls, direction=Direction.FORWARD, interactive=False, next_set=False):
		u""" Toggle state of TODO item

		:returns: The changed heading
		"""
		d = ORGMODE.get_document(allow_dirty=True)

		# get heading
		heading = d.find_current_heading()
		if not heading:
			vim.eval(u'feedkeys("^", "n")')
			return

		todo_states = d.get_todo_states(strip_access_key=False)
		# get todo states
		if not todo_states:
			echom(u'No todo keywords configured.')
			return

		current_state = heading.todo

		# get new state interactively
		if interactive:
			# determine position of the interactive prompt
			prompt_pos = settings.get(u'org_todo_prompt_position', u'botright')
			if prompt_pos not in [u'botright', u'topleft']:
				prompt_pos = u'botright'

			# pass todo states to new window
			ORGTODOSTATES[d.bufnr] = todo_states
			settings.set(
				u'org_current_state_%d' % d.bufnr,
				current_state if current_state is not None else u'', overwrite=True)
			todo_buffer_exists = bool(int(vim.eval(u_encode(
				u'bufexists("org:todo/%d")' % (d.bufnr, )))))
			if todo_buffer_exists:
				# if the buffer already exists, reuse it
				vim.command(u_encode(
					u'%s sbuffer org:todo/%d' % (prompt_pos, d.bufnr, )))
			else:
				# create a new window
				vim.command(u_encode(
					u'keepalt %s %dsplit org:todo/%d' % (prompt_pos, len(todo_states), d.bufnr)))
		else:
			new_state = Todo._get_next_state(
				current_state, todo_states, direction=direction,
				next_set=next_set)

			cls.set_todo_state(new_state)

		# plug
		plug = u'OrgTodoForward'
		if direction == Direction.BACKWARD:
			plug = u'OrgTodoBackward'

		return plug
Пример #21
0
	def toggle_todo_state(cls, direction=Direction.FORWARD, interactive=False, next_set=False):
		u""" Toggle state of TODO item

		:returns: The changed heading
		"""
		d = ORGMODE.get_document(allow_dirty=True)

		# get heading
		heading = d.find_current_heading()
		if not heading:
			vim.eval(u'feedkeys("^", "n")')
			return

		todo_states = d.get_todo_states(strip_access_key=False)
		# get todo states
		if not todo_states:
			echom(u'No todo keywords configured.')
			return

		current_state = heading.todo

		# get new state interactively
		if interactive:
			# determine position of the interactive prompt
			prompt_pos = settings.get(u'org_todo_prompt_position', u'botright')
			if prompt_pos not in [u'botright', u'topleft']:
				prompt_pos = u'botright'

			# pass todo states to new window
			ORGTODOSTATES[d.bufnr] = todo_states
			settings.set(
				u'org_current_state_%d' % d.bufnr,
				current_state if current_state is not None else u'', overwrite=True)
			todo_buffer_exists = bool(int(vim.eval((
				u'bufexists("org:todo/%d")' % (d.bufnr, )).encode(u'utf-8'))))
			if todo_buffer_exists:
				# if the buffer already exists, reuse it
				vim.command((
					u'%s sbuffer org:todo/%d' % (prompt_pos, d.bufnr, )).encode(u'utf-8'))
			else:
				# create a new window
				vim.command((
					u'keepalt %s %dsplit org:todo/%d' % (prompt_pos, len(todo_states), d.bufnr)).encode(u'utf-8'))
		else:
			new_state = Todo._get_next_state(
				current_state, todo_states, direction=direction,
				interactive=interactive, next_set=next_set)
			cls.set_todo_state(new_state)

		# plug
		plug = u'OrgTodoForward'
		if direction == Direction.BACKWARD:
			plug = u'OrgTodoBackward'

		return plug
Пример #22
0
	def init_org_todo(cls):
		u""" Initialize org todo selection window.
		"""
		bufnr = int(vim.current.buffer.name.split('/')[-1])
		all_states = ORGTODOSTATES.get(bufnr, None)

		vim_commands = [
			u'let g:org_sav_timeoutlen=&timeoutlen',
			u'au orgmode BufEnter <buffer> :if ! exists("g:org_sav_timeoutlen")|let g:org_sav_timeoutlen=&timeoutlen|set timeoutlen=1|endif',
			u'au orgmode BufLeave <buffer> :if exists("g:org_sav_timeoutlen")|let &timeoutlen=g:org_sav_timeoutlen|unlet g:org_sav_timeoutlen|endif',
			u'setlocal nolist tabstop=16 buftype=nofile timeout timeoutlen=1 winfixheight',
			u'setlocal statusline=Org\\ todo\\ (%s)' % vim.eval(u_encode(u'fnameescape(fnamemodify(bufname(%d), ":t"))' % bufnr)),
			u'nnoremap <silent> <buffer> <Esc> :%sbw<CR>' % vim.eval(u_encode(u'bufnr("%")')),
			u'nnoremap <silent> <buffer> <CR> :let g:org_state = fnameescape(expand("<cword>"))<Bar>bw<Bar>exec "%s ORGMODE.plugins[u\'Todo\'].set_todo_state(\'".g:org_state."\')"<Bar>unlet! g:org_state<CR>' % VIM_PY_CALL,
			]
		# because timeoutlen can only be set globally it needs to be stored and
		# restored later
		# make window a scratch window and set the statusline differently
		for cmd in vim_commands:
			vim.command(u_encode(cmd))

		if all_states is None:
			vim.command(u_encode(u'bw'))
			echom(u'No todo states avaiable for buffer %s' % vim.current.buffer.name)

		for idx, state in enumerate(all_states):
			pairs = [split_access_key(x, sub=u' ') for x in it.chain(*state)]
			line = u'\t'.join(u''.join((u'[%s] ' % x[1], x[0])) for x in pairs)
			vim.current.buffer.append(u_encode(line))
			for todo, key in pairs:
				# FIXME if double key is used for access modified this doesn't work
				vim.command(u_encode(u'nnoremap <silent> <buffer> %s :bw<CR><c-w><c-p>%s ORGMODE.plugins[u"Todo"].set_todo_state("%s")<CR>' % (key, VIM_PY_CALL, u_decode(todo))))

		# position the cursor of the current todo item
		vim.command(u_encode(u'normal! G'))
		current_state = settings.unset(u'org_current_state_%d' % bufnr)
		if current_state is not None and current_state != '':
			for i, buf in enumerate(vim.current.buffer):
				idx = buf.find(current_state)
				if idx != -1:
					vim.current.window.cursor = (i + 1, idx)
					break
			else:
				vim.current.window.cursor = (2, 4)

		# finally make buffer non modifiable
		vim.command(u_encode(u'setfiletype orgtodo'))
		vim.command(u_encode(u'setlocal nomodifiable'))

		# remove temporary todo states for the current buffer
		del ORGTODOSTATES[bufnr]
Пример #23
0
    def _get_next_state(cls,
                        current_state,
                        all_states,
                        direction=Direction.FORWARD,
                        next_set=False):
        u""" Get the next todo state

		Args:
			current_state (str): The current todo state
			all_states (list): A list containing all todo states within
				sublists. The todo states may contain access keys
			direction: Direction of state or keyword set change (forward or
				backward)
			next_set: Advance to the next keyword set in defined direction.

		Returns:
			str or None: next todo state, or None if there is no next state.

		Note: all_states should have the form of:
			[(['TODO(t)'], ['DONE(d)']),
			(['REPORT(r)', 'BUG(b)', 'KNOWNCAUSE(k)'], ['FIXED(f)']),
			([], ['CANCELED(c)'])]
		"""
        cleaned_todos, flattened_todos = cls._process_all_states(all_states)

        # backward direction should really be -1 not 2
        next_dir = -1 if direction == Direction.BACKWARD else 1
        # work only with top level index
        if next_set:
            top_set = next((todo_set[0]
                            for todo_set in enumerate(cleaned_todos)
                            if current_state in todo_set[1]), -1)
            ind = (top_set + next_dir) % len(cleaned_todos)
            if ind != len(cleaned_todos) - 1:
                echom("Using set: %s" % str(all_states[ind]))
            else:
                echom("Keyword removed.")
            return cleaned_todos[ind][0]
        # No next set, cycle around everything
        else:
            ind = next((todo_iter[0]
                        for todo_iter in enumerate(flattened_todos)
                        if todo_iter[1] == current_state), -1)
            return flattened_todos[(ind + next_dir) % len(flattened_todos)]
Пример #24
0
	def _get_next_state(
		cls, current_state, all_states, direction=Direction.FORWARD,
		next_set=False):
		u""" Get the next todo state

		Args:
			current_state (str): The current todo state
			all_states (list): A list containing all todo states within
				sublists. The todo states may contain access keys
			direction: Direction of state or keyword set change (forward or
				backward)
			next_set: Advance to the next keyword set in defined direction.

		Returns:
			str or None: next todo state, or None if there is no next state.

		Note: all_states should have the form of:
			[(['TODO(t)'], ['DONE(d)']),
			(['REPORT(r)', 'BUG(b)', 'KNOWNCAUSE(k)'], ['FIXED(f)']),
			([], ['CANCELED(c)'])]
		"""
		cleaned_todos, flattened_todos = cls._process_all_states(all_states)

		# backward direction should really be -1 not 2
		next_dir = -1 if direction == Direction.BACKWARD else 1
		# work only with top level index
		if next_set:
			top_set = next((
				todo_set[0] for todo_set in enumerate(cleaned_todos)
				if current_state in todo_set[1]), -1)
			ind = (top_set + next_dir) % len(cleaned_todos)
			if ind != len(cleaned_todos) - 1:
				echom("Using set: %s" % str(all_states[ind]))
			else:
				echom("Keyword removed.")
			return cleaned_todos[ind][0]
		# No next set, cycle around everything
		else:
			ind = next((
				todo_iter[0] for todo_iter in enumerate(flattened_todos)
				if todo_iter[1] == current_state), -1)
			return flattened_todos[(ind + next_dir) % len(flattened_todos)]
Пример #25
0
	def __init__(self):
		u""" Initialize plugin """
		object.__init__(self)
		# menu entries this plugin should create
		self.menu = ORGMODE.orgmenu + Submenu(u'Dates and Scheduling')

		# key bindings for this plugin
		# key bindings are also registered through the menu so only additional
		# bindings should be put in this variable
		self.keybindings = []

		# commands for this plugin
		self.commands = []

		# set speeddating format that is compatible with orgmode
		try:
			if int(vim.eval(u'exists(":SpeedDatingFormat")'.encode(u'utf-8'))) == 2:
				vim.command(u':1SpeedDatingFormat %Y-%m-%d %a'.encode(u'utf-8'))
				vim.command(u':1SpeedDatingFormat %Y-%m-%d %a %H:%M'.encode(u'utf-8'))
			else:
				echom(u'Speeddating plugin not installed. Please install it.')
		except:
			echom(u'Speeddating plugin not installed. Please install it.')
Пример #26
0
	def create(self):
		from orgmode._vim import ORGMODE, echom

		cmd = self._mode
		if cmd == MODE_ALL:
			cmd = u''
		if not self._remap:
			cmd += u'nore'
		try:
			create_mapping = True
			if isinstance(self._action, Plug):
				# create plug
				self._action.create()
				if int(vim.eval(u_encode(u'hasmapto("%s")' % (self._action, )))):
					create_mapping = False
			if isinstance(self._action, Command):
				# create command
				self._action.create()

			if create_mapping:
				vim.command(u_encode(u':%smap %s %s %s' % (cmd, u' '.join(self._options), self._key, self._action)))
		except Exception as e:
			if ORGMODE.debug:
				echom(u'Failed to register key binding %s %s' % (self._key, self._action))
Пример #27
0
	def add_planning_date_line(cls, planning_tag):
		u"""
		Insert a planning datestamp in a line after the current line.

		TODO: Show fancy calendar to pick the date from.
		TODO: Update an existing date, if present.
		"""

		today = date.today()
		msg = u''.join([
			u'Inserting ',
			unicode(today.strftime(u'%Y-%m-%d %a'), u'utf-8'),
			u' | Modify date'])
		modifier = get_user_input(msg)

		# abort if the user canceled the input promt
		if modifier is None:
			return
		echom('The mod was' + modifier + str(len(modifier)))

		newdate = cls._modify_time(today, modifier)

		# format
		if isinstance(newdate, datetime):
			newdate = newdate.strftime(
				u'%Y-%m-%d %a %H:%M'.encode(u'utf-8')).decode(u'utf-8')
		else:
			newdate = newdate.strftime(
				u'%Y-%m-%d %a'.encode(u'utf-8')).decode(u'utf-8')

		# Find the heading level for indentation
		curr_line = vim.current.line
		match = re.match(r'^(\*+)', curr_line)

		level = 1
		if match:
			level += len(match.group())

		timestamp = u' ' * level + u'%s: <%s>' % (planning_tag, newdate)

		# Edit the current buffer to insert the planning line
		curr_row, _ = vim.current.window.cursor
		curr_row -= 1  # Change vim 1-based indexing to 0-based indexing
		buff = vim.current.buffer

		pre_lines = buff[:curr_row+1]  # Lines up to and including the current line
		if len(buff) > curr_row + 1:
			if planning_tag in buff[curr_row+1]:
				post_lines = buff[curr_row+2:]
				plan_line = re.sub(
					r'%s:[^>]*>' % planning_tag,
					timestamp.strip(),
					buff[curr_row+1])
			elif 'SCHEDULED' in buff[curr_row+1] or 'DEADLINE' in buff[curr_row+1]:
				post_lines = buff[curr_row+2:]
				plan_line = buff[curr_row+1] + " " + timestamp.strip()
			else:
				post_lines = buff[curr_row+1:]
				plan_line = timestamp
		else:
			post_lines = []
			plan_line = timestamp

		buff[:] = pre_lines + [plan_line] + post_lines
Пример #28
0
    def new_checkbox(cls, below=None, plain=None):
        '''
		if below is:
			True -> create new list below current line
			False/None -> create new list above current line
		if plain is:
			True -> create a plainlist item
			False/None -> create an empty checkbox
		'''
        d = ORGMODE.get_document()
        h = d.current_heading()
        if h is None:
            return
        # init checkboxes for current heading
        h.init_checkboxes()
        c = h.current_checkbox()

        nc = Checkbox()
        nc._heading = h

        # default checkbox level
        # make it align with the 4-space tabbing
        level = 4

        start = vim.current.window.cursor[0] - 1
        # if no checkbox is found, insert at current line with indent level=1
        if c is None:
            h.checkboxes.append(nc)
        else:
            l = c.get_parent_list()
            idx = c.get_index_in_parent_list()
            if l is not None and idx is not None:
                l.insert(idx + (1 if below else 0), nc)
                # workaround for broken associations, Issue #165
                nc._parent = c.parent
                if below:
                    if c.next_sibling:
                        c.next_sibling._previous_sibling = nc
                    nc._next_sibling = c.next_sibling
                    c._next_sibling = nc
                    nc._previous_sibling = c
                else:
                    if c.previous_sibling:
                        c.previous_sibling._next_sibling = nc
                    nc._next_sibling = c
                    nc._previous_sibling = c.previous_sibling
                    c._previous_sibling = nc

            t = c.type
            # increase key for ordered lists
            if t[-1] in OrderListType:
                try:
                    num = int(t[:-1]) + (1 if below else -1)
                    if num < 0:
                        # don't decrease to numbers below zero
                        echom(u"Can't decrement further than '0'")
                        return
                    t = '%d%s' % (num, t[-1])
                except ValueError:
                    try:
                        char = ord(t[:-1]) + (1 if below else -1)
                        if below:
                            if char == 91:
                                # stop incrementing at Z (90)
                                echom(u"Can't increment further than 'Z'")
                                return
                            elif char == 123:
                                # increment from z (122) to A
                                char = 65
                        else:
                            if char == 96:
                                # stop decrementing at a (97)
                                echom(u"Can't decrement further than 'a'")
                                return
                            elif char == 64:
                                # decrement from A (65) to z
                                char = 122
                        t = u'%s%s' % (chr(char), t[-1])
                    except ValueError:
                        pass
            nc.type = t
            level = c.level

            if below:
                start = c.end_of_last_child
            else:
                start = c.start

        if plain:  # only create plainlist item when requested
            nc.status = None
        nc.level = level

        if below:
            start += 1
        # vim's buffer behave just opposite to Python's list when inserting a
        # new item.  The new entry is appended in vim put prepended in Python!
        vim.current.buffer.append("")  # workaround for neovim
        vim.current.buffer[start:start] = [unicode(nc)]
        del vim.current.buffer[-1]  # restore from workaround for neovim

        # update checkboxes status
        cls.update_checkboxes_status()

        # do not start insert upon adding new checkbox, Issue #211
        if int(settings.get(u'org_prefer_insert_mode', u'1')):
            vim.command(
                u_encode(u'exe "normal %dgg"|startinsert!' % (start + 1, )))
        else:
            vim.command(u_encode(u'exe "normal %dgg$"' % (start + 1, )))
Пример #29
0
    def _get_next_state(cls,
                        current_state,
                        all_states,
                        direction=Direction.FORWARD,
                        interactive=False,
                        next_set=False):
        u"""
		WTF is going on here!!!
		FIXME: reimplement this in a clean way :)

		:current_state:		the current todo state
		:all_states:		a list containing all todo states within sublists.
							The todo states may contain access keys
		:direction:			direction of state or keyword set change (forward/backward)
		:interactive:		if interactive and more than one todo sequence is
							specified, open a selection window
		:next_set:			advance to the next keyword set in defined direction

		:return:			return the next state as string, or NONE if the
							next state is no state.
		"""
        if not all_states:
            return

        def find_current_todo_state(c, a, stop=0):
            u"""
			:c:		current todo state
			:a:		list of todo states
			:stop:	internal parameter for parsing only two levels of lists

			:return:	first position of todo state in list in the form
						(IDX_TOPLEVEL, IDX_SECOND_LEVEL (0|1), IDX_OF_ITEM)
			"""
            for i in range(0, len(a)):
                if type(a[i]) in (tuple, list) and stop < 2:
                    r = find_current_todo_state(c, a[i], stop=stop + 1)
                    if r:
                        r.insert(0, i)
                        return r
                # ensure that only on the second level of sublists todo states
                # are found
                if type(a[i]) == unicode and stop == 2:
                    _i = split_access_key(a[i])[0]
                    if c == _i:
                        return [i]

        ci = find_current_todo_state(current_state, all_states)

        if not ci:
            if next_set and direction == Direction.BACKWARD:
                echom(u'Already at the first keyword set')
                return current_state

            return split_access_key(all_states[0][0][0] if all_states[0][0] else all_states[0][1][0])[0] \
             if direction == Direction.FORWARD else \
             split_access_key(all_states[0][1][-1] if all_states[0][1] else all_states[0][0][-1])[0]
        elif next_set:
            if direction == Direction.FORWARD and ci[0] + 1 < len(
                    all_states[ci[0]]):
                echom(u'Keyword set: %s | %s' %
                      (u', '.join(all_states[ci[0] + 1][0]), u', '.join(
                          all_states[ci[0] + 1][1])))
                return split_access_key(all_states[
                    ci[0] +
                    1][0][0] if all_states[ci[0] +
                                           1][0] else all_states[ci[0] +
                                                                 1][1][0])[0]
            elif current_state is not None and direction == Direction.BACKWARD and ci[
                    0] - 1 >= 0:
                echom(u'Keyword set: %s | %s' %
                      (u', '.join(all_states[ci[0] - 1][0]), u', '.join(
                          all_states[ci[0] - 1][1])))
                return split_access_key(all_states[
                    ci[0] -
                    1][0][0] if all_states[ci[0] -
                                           1][0] else all_states[ci[0] -
                                                                 1][1][0])[0]
            else:
                echom(
                    u'Already at the %s keyword set' %
                    (u'first' if direction == Direction.BACKWARD else u'last'))
                return current_state
        else:
            next_pos = ci[2] + 1 if direction == Direction.FORWARD else ci[
                2] - 1
            if direction == Direction.FORWARD:
                if next_pos < len(all_states[ci[0]][ci[1]]):
                    # select next state within done or todo states
                    return split_access_key(
                        all_states[ci[0]][ci[1]][next_pos])[0]

                elif not ci[1] and next_pos - len(
                        all_states[ci[0]][ci[1]]) < len(
                            all_states[ci[0]][ci[1] + 1]):
                    # finished todo states, jump to done states
                    return split_access_key(
                        all_states[ci[0]][ci[1] +
                                          1][next_pos -
                                             len(all_states[ci[0]][ci[1]])])[0]
            else:
                if next_pos >= 0:
                    # select previous state within done or todo states
                    return split_access_key(
                        all_states[ci[0]][ci[1]][next_pos])[0]

                elif ci[1] and len(
                        all_states[ci[0]][ci[1] - 1]) + next_pos < len(
                            all_states[ci[0]][ci[1] - 1]):
                    # finished done states, jump to todo states
                    return split_access_key(
                        all_states[ci[0]][ci[1] -
                                          1][len(all_states[ci[0]][ci[1] - 1])
                                             + next_pos])[0]
Пример #30
0
    def init_org_todo(cls):
        u""" Initialize org todo selection window.
		"""
        bufnr = int(vim.current.buffer.name.split('/')[-1])
        all_states = ORGTODOSTATES.get(bufnr, None)

        # because timeoutlen can only be set globally it needs to be stored and restored later
        vim.command(u_encode(u'let g:org_sav_timeoutlen=&timeoutlen'))
        vim.command(
            u_encode(
                u'au orgmode BufEnter <buffer> :if ! exists("g:org_sav_timeoutlen")|let g:org_sav_timeoutlen=&timeoutlen|set timeoutlen=1|endif'
            ))
        vim.command(
            u_encode(
                u'au orgmode BufLeave <buffer> :if exists("g:org_sav_timeoutlen")|let &timeoutlen=g:org_sav_timeoutlen|unlet g:org_sav_timeoutlen|endif'
            ))
        # make window a scratch window and set the statusline differently
        vim.command(
            u_encode(
                u'setlocal nolist tabstop=16 buftype=nofile timeout timeoutlen=1 winfixheight'
            ))
        vim.command(
            u_encode((u'setlocal statusline=Org\\ todo\\ (%s)' % vim.eval(
                u_encode((u'fnameescape(fnamemodify(bufname(%d), ":t"))' %
                          bufnr))))))
        vim.command(
            u_encode((u'nnoremap <silent> <buffer> <Esc> :%sbw<CR>' %
                      (vim.eval(u_encode(u'bufnr("%")')), ))))
        vim.command(
            u_encode(
                u'nnoremap <silent> <buffer> <CR> :let g:org_state = fnameescape(expand("<cword>"))<Bar>bw<Bar>exec "%s ORGMODE.plugins[u\'Todo\'].set_todo_state(\'".g:org_state."\')"<Bar>unlet! g:org_state<CR>'
                % VIM_PY_CALL))

        if all_states is None:
            vim.command(u_encode(u'bw'))
            echom(u'No todo states avaiable for buffer %s' %
                  vim.current.buffer.name)

        for l in range(0, len(all_states)):
            res = u''
            for j in range(0, 2):
                if j < len(all_states[l]):
                    for i in all_states[l][j]:
                        if type(i) != unicode:
                            continue
                        v, k = split_access_key(i)
                        if k:
                            res += (u'\t'
                                    if res else u'') + u'[%s] %s' % (k, v)
                            # map access keys to callback that updates current heading
                            # map selection keys
                            vim.command(
                                u_encode((
                                    u'nnoremap <silent> <buffer> %s :bw<CR><c-w><c-p>%s ORGMODE.plugins[u"Todo"].set_todo_state(u_decode("%s")))<CR>'
                                    % (k, VIM_PY_CALL, v))))
                        elif v:
                            res += (u'\t' if res else u'') + v
            if res:
                if l == 0:
                    # WORKAROUND: the cursor can not be positioned properly on
                    # the first line. Another line is just inserted and it
                    # works great
                    vim.current.buffer[0] = u_encode(u'')
                vim.current.buffer.append(u_encode(res))

        # position the cursor of the current todo item
        vim.command(u_encode(u'normal! G'))
        current_state = settings.unset(u'org_current_state_%d' % bufnr)
        found = False
        if current_state is not None and current_state != '':
            for i in range(0, len(vim.current.buffer)):
                idx = vim.current.buffer[i].find(current_state)
                if idx != -1:
                    vim.current.window.cursor = (i + 1, idx)
                    found = True
                    break
        if not found:
            vim.current.window.cursor = (2, 4)

        # finally make buffer non modifiable
        vim.command(u_encode(u'setfiletype orgtodo'))
        vim.command(u_encode(u'setlocal nomodifiable'))

        # remove temporary todo states for the current buffer
        del ORGTODOSTATES[bufnr]
Пример #31
0
    def new_checkbox(cls, below=None):
        d = ORGMODE.get_document()
        h = d.current_heading()
        if h is None:
            return
        # init checkboxes for current heading
        h.init_checkboxes()
        c = h.current_checkbox()

        nc = Checkbox()
        nc._heading = h

        # default checkbox level
        level = h.level + 1
        start = vim.current.window.cursor[0] - 1
        # if no checkbox is found, insert at current line with indent level=1
        if c is None:
            h.checkboxes.append(nc)
        else:
            l = c.get_parent_list()
            idx = c.get_index_in_parent_list()
            if l is not None and idx is not None:
                l.insert(idx + (1 if below else 0), nc)
                # workaround for broken associations, Issue #165
                nc._parent = c.parent
                if below:
                    if c.next_sibling:
                        c.next_sibling._previous_sibling = nc
                    nc._next_sibling = c.next_sibling
                    c._next_sibling = nc
                    nc._previous_sibling = c
                else:
                    if c.previous_sibling:
                        c.previous_sibling._next_sibling = nc
                    nc._next_sibling = c
                    nc._previous_sibling = c.previous_sibling
                    c._previous_sibling = nc

            t = c.type
            # increase key for ordered lists
            if t[-1] in OrderListType:
                try:
                    num = int(t[:-1]) + (1 if below else -1)
                    if num < 0:
                        # don't decrease to numbers below zero
                        echom(u"Can't decrement further than '0'")
                        return
                    t = '%d%s' % (num, t[-1])
                except ValueError:
                    try:
                        char = ord(t[:-1]) + (1 if below else -1)
                        if below:
                            if char == 91:
                                # stop incrementing at Z (90)
                                echom(u"Can't increment further than 'Z'")
                                return
                            elif char == 123:
                                # increment from z (122) to A
                                char = 65
                        else:
                            if char == 96:
                                # stop decrementing at a (97)
                                echom(u"Can't decrement further than 'a'")
                                return
                            elif char == 64:
                                # decrement from A (65) to z
                                char = 122
                        t = u'%s%s' % (chr(char), t[-1])
                    except ValueError:
                        pass
            nc.type = t
            if not c.status:
                nc.status = None
            level = c.level

            if below:
                start = c.end_of_last_child
            else:
                start = c.start
        nc.level = level

        if below:
            start += 1
        # vim's buffer behave just opposite to Python's list when inserting a
        # new item.  The new entry is appended in vim put prepended in Python!
        vim.current.buffer[start:start] = [unicode(nc)]

        # update checkboxes status
        cls.update_checkboxes_status()

        vim.command((u'exe "normal %dgg"|startinsert!' %
                     (start + 1, )).encode(u'utf-8'))
Пример #32
0
	def new_checkbox(cls, below=None, plain=None):
		'''
		if below is:
			True -> create new list below current line
			False/None -> create new list above current line
		if plain is:
			True -> create a plainlist item
			False/None -> create an empty checkbox
		'''
		d = ORGMODE.get_document()
		h = d.current_heading()
		if h is None:
			return
		# init checkboxes for current heading
		h.init_checkboxes()
		c = h.current_checkbox()

		nc = Checkbox()
		nc._heading = h

		# default checkbox level
		level = h.level + 1
		start = vim.current.window.cursor[0] - 1
		# if no checkbox is found, insert at current line with indent level=1
		if c is None:
			h.checkboxes.append(nc)
		else:
			l = c.get_parent_list()
			idx = c.get_index_in_parent_list()
			if l is not None and idx is not None:
				l.insert(idx + (1 if below else 0), nc)
				# workaround for broken associations, Issue #165
				nc._parent = c.parent
				if below:
					if c.next_sibling:
						c.next_sibling._previous_sibling = nc
					nc._next_sibling = c.next_sibling
					c._next_sibling = nc
					nc._previous_sibling = c
				else:
					if c.previous_sibling:
						c.previous_sibling._next_sibling = nc
					nc._next_sibling = c
					nc._previous_sibling = c.previous_sibling
					c._previous_sibling = nc

			t = c.type
			# increase key for ordered lists
			if t[-1] in OrderListType:
				try:
					num = int(t[:-1]) + (1 if below else -1)
					if num < 0:
						# don't decrease to numbers below zero
						echom(u"Can't decrement further than '0'")
						return
					t = '%d%s' % (num, t[-1])
				except ValueError:
					try:
						char = ord(t[:-1]) + (1 if below else -1)
						if below:
							if char == 91:
								# stop incrementing at Z (90)
								echom(u"Can't increment further than 'Z'")
								return
							elif char == 123:
								# increment from z (122) to A
								char = 65
						else:
							if char == 96:
								# stop decrementing at a (97)
								echom(u"Can't decrement further than 'a'")
								return
							elif char == 64:
								# decrement from A (65) to z
								char = 122
						t = u'%s%s' % (chr(char), t[-1])
					except ValueError:
						pass
			nc.type = t
			level = c.level

			if below:
				start = c.end_of_last_child
			else:
				start = c.start

		if plain:  	# only create plainlist item when requested
			nc.status = None
		nc.level = level

		if below:
			start += 1
		# vim's buffer behave just opposite to Python's list when inserting a
		# new item.  The new entry is appended in vim put prepended in Python!
		vim.current.buffer.append("") # workaround for neovim
		vim.current.buffer[start:start] = [unicode(nc)]
		del vim.current.buffer[-1] # restore from workaround for neovim

		# update checkboxes status
		cls.update_checkboxes_status()

		# do not start insert upon adding new checkbox, Issue #211
		if int(settings.get(u'org_prefer_insert_mode', u'1')):
			vim.command(u_encode((u'exe "normal %dgg"|startinsert!' % (start + 1, ))))
		else:
			vim.command(u_encode((u'exe "normal %dgg$"' % (start + 1, ))))
Пример #33
0
	def new_checkbox(cls, below=None):
		d = ORGMODE.get_document()
		h = d.current_heading()
		if h is None:
			return
		# init checkboxes for current heading
		h.init_checkboxes()
		c = h.current_checkbox()

		nc = Checkbox()
		nc._heading = h

		# default checkbox level
		level = h.level + 1
		start = vim.current.window.cursor[0] - 1
		# if no checkbox is found, insert at current line with indent level=1
		if c is None:
			h.checkboxes.append(nc)
		else:
			l = c.get_parent_list()
			idx = c.get_index_in_parent_list()
			if l is not None and idx is not None:
				l.insert(idx + (1 if below else 0), nc)
				# workaround for broken associations, Issue #165
				nc._parent = c.parent
				if below:
					if c.next_sibling:
						c.next_sibling._previous_sibling = nc
					nc._next_sibling = c.next_sibling
					c._next_sibling = nc
					nc._previous_sibling = c
				else:
					if c.previous_sibling:
						c.previous_sibling._next_sibling = nc
					nc._next_sibling = c
					nc._previous_sibling = c.previous_sibling
					c._previous_sibling = nc

			t = c.type
			# increase key for ordered lists
			if t[-1] in OrderListType:
				try:
					num = int(t[:-1]) + (1 if below else -1)
					if num < 0:
						# don't decrease to numbers below zero
						echom(u"Can't decrement further than '0'")
						return
					t = '%d%s' % (num, t[-1])
				except ValueError:
					try:
						char = ord(t[:-1]) + (1 if below else -1)
						if below:
							if char == 91:
								# stop incrementing at Z (90)
								echom(u"Can't increment further than 'Z'")
								return
							elif char == 123:
								# increment from z (122) to A
								char = 65
						else:
							if char == 96:
								# stop decrementing at a (97)
								echom(u"Can't decrement further than 'a'")
								return
							elif char == 64:
								# decrement from A (65) to z
								char = 122
						t = u'%s%s' % (chr(char), t[-1])
					except ValueError:
						pass
			nc.type = t
			if not c.status:
				nc.status = None
			level = c.level

			if below:
				start = c.end_of_last_child
			else:
				start = c.start
		nc.level = level

		if below:
			start += 1
		# vim's buffer behave just opposite to Python's list when inserting a
		# new item.  The new entry is appended in vim put prepended in Python!
		vim.current.buffer[start:start] = [unicode(nc)]

		# update checkboxes status
		cls.update_checkboxes_status()

		vim.command((u'exe "normal %dgg"|startinsert!' % (start + 1, )).encode(u'utf-8'))
Пример #34
0
	def init_org_todo(cls):
		u""" Initialize org todo selection window.
		"""
		bufnr = int(vim.current.buffer.name.split('/')[-1])
		all_states = ORGTODOSTATES.get(bufnr, None)

		# because timeoutlen can only be set globally it needs to be stored and restored later
		vim.command(u_encode(u'let g:org_sav_timeoutlen=&timeoutlen'))
		vim.command(u_encode(u'au orgmode BufEnter <buffer> :if ! exists("g:org_sav_timeoutlen")|let g:org_sav_timeoutlen=&timeoutlen|set timeoutlen=1|endif'))
		vim.command(u_encode(u'au orgmode BufLeave <buffer> :if exists("g:org_sav_timeoutlen")|let &timeoutlen=g:org_sav_timeoutlen|unlet g:org_sav_timeoutlen|endif'))
		# make window a scratch window and set the statusline differently
		vim.command(u_encode(u'setlocal nolist tabstop=16 buftype=nofile timeout timeoutlen=1 winfixheight'))
		vim.command(u_encode((u'setlocal statusline=Org\\ todo\\ (%s)' % vim.eval(u_encode((u'fnameescape(fnamemodify(bufname(%d), ":t"))' % bufnr))))))
		vim.command(u_encode((u'nnoremap <silent> <buffer> <Esc> :%sbw<CR>' % (vim.eval(u_encode(u'bufnr("%")')), ))))
		vim.command(u_encode(u'nnoremap <silent> <buffer> <CR> :let g:org_state = fnameescape(expand("<cword>"))<Bar>bw<Bar>exec "%s ORGMODE.plugins[u\'Todo\'].set_todo_state(\'".g:org_state."\')"<Bar>unlet! g:org_state<CR>' % VIM_PY_CALL))

		if all_states is None:
			vim.command(u_encode(u'bw'))
			echom(u'No todo states avaiable for buffer %s' % vim.current.buffer.name)

		for l in range(0, len(all_states)):
			res = u''
			for j in range(0, 2):
				if j < len(all_states[l]):
					for i in all_states[l][j]:
						if type(i) != unicode:
							continue
						v, k = split_access_key(i)
						if k:
							res += (u'\t' if res else u'') + u'[%s] %s' % (k, v)
							# map access keys to callback that updates current heading
							# map selection keys
							vim.command(u_encode((u'nnoremap <silent> <buffer> %s :bw<CR><c-w><c-p>%s ORGMODE.plugins[u"Todo"].set_todo_state(u_decode("%s")))<CR>' % (k, VIM_PY_CALL, v))))
						elif v:
							res += (u'\t' if res else u'') + v
			if res:
				if l == 0:
					# WORKAROUND: the cursor can not be positioned properly on
					# the first line. Another line is just inserted and it
					# works great
					vim.current.buffer[0] = u_encode(u'')
				vim.current.buffer.append(u_encode(res))

		# position the cursor of the current todo item
		vim.command(u_encode(u'normal! G'))
		current_state = settings.unset(u'org_current_state_%d' % bufnr)
		found = False
		if current_state is not None and current_state != '':
			for i in range(0, len(vim.current.buffer)):
				idx = vim.current.buffer[i].find(current_state)
				if idx != -1:
					vim.current.window.cursor = (i + 1, idx)
					found = True
					break
		if not found:
			vim.current.window.cursor = (2, 4)

		# finally make buffer non modifiable
		vim.command(u_encode(u'setfiletype orgtodo'))
		vim.command(u_encode(u'setlocal nomodifiable'))

		# remove temporary todo states for the current buffer
		del ORGTODOSTATES[bufnr]
Пример #35
0
	def _get_next_state(
		cls, current_state, all_states,
		direction=Direction.FORWARD, interactive=False, next_set=False):
		u"""
		WTF is going on here!!!
		FIXME: reimplement this in a clean way :)

		:current_state:		the current todo state
		:all_states:		a list containing all todo states within sublists.
							The todo states may contain access keys
		:direction:			direction of state or keyword set change (forward/backward)
		:interactive:		if interactive and more than one todo sequence is
							specified, open a selection window
		:next_set:			advance to the next keyword set in defined direction

		:return:			return the next state as string, or NONE if the
							next state is no state.
		"""
		if not all_states:
			return

		def find_current_todo_state(c, a, stop=0):
			u"""
			:c:		current todo state
			:a:		list of todo states
			:stop:	internal parameter for parsing only two levels of lists

			:return:	first position of todo state in list in the form
						(IDX_TOPLEVEL, IDX_SECOND_LEVEL (0|1), IDX_OF_ITEM)
			"""
			for i in range(0, len(a)):
				if type(a[i]) in (tuple, list) and stop < 2:
					r = find_current_todo_state(c, a[i], stop=stop + 1)
					if r:
						r.insert(0, i)
						return r
				# ensure that only on the second level of sublists todo states
				# are found
				if type(a[i]) == unicode and stop == 2:
					_i = split_access_key(a[i])[0]
					if c == _i:
						return [i]

		ci = find_current_todo_state(current_state, all_states)

		if not ci:
			if next_set and direction == Direction.BACKWARD:
				echom(u'Already at the first keyword set')
				return current_state

			return split_access_key(all_states[0][0][0] if all_states[0][0] else all_states[0][1][0])[0] \
				if direction == Direction.FORWARD else \
				split_access_key(all_states[0][1][-1] if all_states[0][1] else all_states[0][0][-1])[0]
		elif next_set:
			if direction == Direction.FORWARD and ci[0] + 1 < len(all_states[ci[0]]):
				echom(u'Keyword set: %s | %s' % (u', '.join(all_states[ci[0] + 1][0]), u', '.join(all_states[ci[0] + 1][1])))
				return split_access_key(
					all_states[ci[0] + 1][0][0] if all_states[ci[0] + 1][0] else all_states[ci[0] + 1][1][0])[0]
			elif current_state is not None and direction == Direction.BACKWARD and ci[0] - 1 >= 0:
				echom(u'Keyword set: %s | %s' % (u', '.join(all_states[ci[0] - 1][0]), u', '.join(all_states[ci[0] - 1][1])))
				return split_access_key(
					all_states[ci[0] - 1][0][0] if all_states[ci[0] - 1][0] else all_states[ci[0] - 1][1][0])[0]
			else:
				echom(u'Already at the %s keyword set' % (u'first' if direction == Direction.BACKWARD else u'last'))
				return current_state
		else:
			next_pos = ci[2] + 1 if direction == Direction.FORWARD else ci[2] - 1
			if direction == Direction.FORWARD:
				if next_pos < len(all_states[ci[0]][ci[1]]):
					# select next state within done or todo states
					return split_access_key(all_states[ci[0]][ci[1]][next_pos])[0]

				elif not ci[1] and next_pos - len(all_states[ci[0]][ci[1]]) < len(all_states[ci[0]][ci[1] + 1]):
					# finished todo states, jump to done states
					return split_access_key(all_states[ci[0]][ci[1] + 1][next_pos - len(all_states[ci[0]][ci[1]])])[0]
			else:
				if next_pos >= 0:
					# select previous state within done or todo states
					return split_access_key(all_states[ci[0]][ci[1]][next_pos])[0]

				elif ci[1] and len(all_states[ci[0]][ci[1] - 1]) + next_pos < len(all_states[ci[0]][ci[1] - 1]):
					# finished done states, jump to todo states
					return split_access_key(all_states[ci[0]][ci[1] - 1][len(all_states[ci[0]][ci[1] - 1]) + next_pos])[0]