def setUp(self):
        global counter
        counter += 1
        vim.CMDHISTORY = []
        vim.CMDRESULTS = {}
        vim.EVALHISTORY = []
        vim.EVALRESULTS = {
            # no org_todo_keywords for b
            u'exists("b:org_todo_keywords")'.encode(u'utf-8'):
            '0'.encode(u'utf-8'),
            # global values for org_todo_keywords
            u'exists("g:org_todo_keywords")'.encode(u'utf-8'):
            '1'.encode(u'utf-8'),
            u'g:org_todo_keywords'.encode(u'utf-8'): [
                u'TODO'.encode(u'utf-8'), u'DONE'.encode(u'utf-8'),
                u'|'.encode(u'utf-8')
            ],
            u'exists("g:org_debug")'.encode(u'utf-8'):
            u'0'.encode(u'utf-8'),
            u'exists("b:org_debug")'.encode(u'utf-8'):
            u'0'.encode(u'utf-8'),
            u'exists("*repeat#set()")'.encode(u'utf-8'):
            u'0'.encode(u'utf-8'),
            u'exists("b:org_leader")'.encode(u'utf-8'):
            u'0'.encode(u'utf-8'),
            u'exists("g:org_leader")'.encode(u'utf-8'):
            u'0'.encode(u'utf-8'),
            u'b:changedtick'.encode(u'utf-8'):
            (u'%d' % counter).encode(u'utf-8'),
            u"v:count".encode(u'utf-8'):
            u'0'.encode(u'utf-8')
        }
        if not u'TagsProperties' in ORGMODE.plugins:
            ORGMODE.register_plugin(u'TagsProperties')
        self.showhide = ORGMODE.plugins[u'TagsProperties']
        vim.current.buffer[:] = [
            i.encode(u'utf-8') for i in u"""
* Überschrift 1
Text 1

Bla bla
** Überschrift 1.1
Text 2

Bla Bla bla
** Überschrift 1.2
Text 3

**** Überschrift 1.2.1.falsch

Bla Bla bla bla
*** Überschrift 1.2.1
* Überschrift 2
* Überschrift 3
  asdf sdf
""".split(u'\n')
        ]
Esempio n. 2
0
    def setUp(self):
        global counter
        counter += 1
        vim.CMDHISTORY = []
        vim.CMDRESULTS = {}
        vim.EVALHISTORY = []
        vim.EVALRESULTS = {
            # no org_todo_keywords for b
            u'exists("b:org_todo_keywords")'.encode(u"utf-8"): "0".encode(u"utf-8"),
            # global values for org_todo_keywords
            u'exists("g:org_todo_keywords")'.encode(u"utf-8"): "1".encode(u"utf-8"),
            u"g:org_todo_keywords".encode(u"utf-8"): [
                u"TODO".encode(u"utf-8"),
                u"DONE".encode(u"utf-8"),
                u"|".encode(u"utf-8"),
            ],
            u'exists("g:org_improve_split_heading")'.encode(u"utf-8"): u"0".encode(u"utf-8"),
            u'exists("b:org_improve_split_heading")'.encode(u"utf-8"): u"0".encode(u"utf-8"),
            u'exists("g:org_debug")'.encode(u"utf-8"): u"0".encode(u"utf-8"),
            u'exists("b:org_debug")'.encode(u"utf-8"): u"0".encode(u"utf-8"),
            u'exists("*repeat#set()")'.encode(u"utf-8"): u"0".encode(u"utf-8"),
            u"b:changedtick".encode(u"utf-8"): (u"%d" % counter).encode(u"utf-8"),
            u"&ts".encode(u"utf-8"): u"8".encode(u"utf-8"),
            u'exists("g:org_tag_column")'.encode(u"utf-8"): u"0".encode(u"utf-8"),
            u'exists("b:org_tag_column")'.encode(u"utf-8"): u"0".encode(u"utf-8"),
            u"v:count".encode(u"utf-8"): u"0".encode(u"utf-8"),
        }
        if not u"EditStructure" in ORGMODE.plugins:
            ORGMODE.register_plugin(u"EditStructure")
        self.editstructure = ORGMODE.plugins[u"EditStructure"]
        vim.current.buffer[:] = [
            i.encode(u"utf-8")
            for i in u"""
* Überschrift 1
Text 1

Bla bla
** Überschrift 1.1
Text 2

Bla Bla bla
** Überschrift 1.2
Text 3

**** Überschrift 1.2.1.falsch

Bla Bla bla bla
*** Überschrift 1.2.1
* Überschrift 2
* Überschrift 3
  asdf sdf
""".split(
                u"\n"
            )
        ]
Esempio n. 3
0
	def set_todo_state(cls, state):
		u""" Set todo state for buffer.

		:bufnr:		Number of buffer the todo state should be updated for
		:state:		The new todo state
		"""
		lineno, colno = vim.current.window.cursor
		d = ORGMODE.get_document(allow_dirty=True)
		heading = d.find_current_heading()

		if not heading:
			return

		current_state = heading.todo

		# move cursor along with the inserted state only when current position
		# is in the heading; otherwite do nothing
		if heading.start_vim == lineno:
			if current_state is None and state is None:
				offset = 0
			elif current_state is None:
				offset = len(state)
			elif state is None:
				offset = -len(current_state)
			else:
				offset = len(current_state) - len(state)
			vim.current.window.cursor = (lineno, colno + offset)

		# set new headline
		heading.todo = state
		d.write_heading(heading)
Esempio n. 4
0
	def global_toggle_folding(cls, reverse=False):
		""" Toggle folding globally

		:reverse:	If False open folding by one level otherwise close it by one.
		"""
		d = ORGMODE.get_document()
		if reverse:
			foldlevel = int(vim.eval(u'&foldlevel'.encode(u'utf-8')))
			if foldlevel == 0:
				# open all folds because the user tries to close folds beyound 0
				vim.eval(u'feedkeys("zR", "n")'.encode(u'utf-8'))
			else:
				# vim can reduce the foldlevel on its own
				vim.eval(u'feedkeys("zm", "n")'.encode(u'utf-8'))
		else:
			found = False
			for h in d.headings:
				res = cls._fold_depth(h)
				if res:
					found = res[1]
				if found:
					break
			if not found:
				# no fold found and the user tries to advance the fold level
				# beyond maximum so close everything
				vim.eval(u'feedkeys("zM", "n")'.encode(u'utf-8'))
			else:
				# fold found, vim can increase the foldlevel on its own
				vim.eval(u'feedkeys("zr", "n")'.encode(u'utf-8'))

		return d
Esempio n. 5
0
	def _move_heading(cls, direction=DIRECTION_FORWARD, including_children=True):
		u""" Move heading up or down

		:returns: heading or None
		"""
		d = ORGMODE.get_document()
		heading = d.current_heading()
		if not heading or \
				direction == DIRECTION_FORWARD and not heading.next_sibling or \
				direction == DIRECTION_BACKWARD and not heading.previous_sibling:
			return None

		cursor_offset_within_the_heading_vim = vim.current.window.cursor[0] - (heading._orig_start + 1)

		if not including_children:
			heading.previous_sibling.children.extend(heading.children)
			del heading.children

		heading_insert_position = 1 if direction == DIRECTION_FORWARD else -1
		l = heading.get_parent_list()
		idx = heading.get_index_in_parent_list()
		if l is not None and idx is not None:
			l.insert(idx + heading_insert_position, heading)
		else:
			raise HeadingDomError('Current heading is not properly linked in DOM')

		d.write()

		vim.current.window.cursor = (heading.start_vim + cursor_offset_within_the_heading_vim, vim.current.window.cursor[1])

		return True
Esempio n. 6
0
    def parent_next_sibling(cls, mode):
        u"""
		Focus the parent's next sibling

		:returns: parent's next sibling heading or None
		"""
        heading = ORGMODE.get_document().current_heading()
        if not heading:
            if mode == u'visual':
                vim.command(u'normal gv'.encode(u'utf-8'))
            else:
                echo(u'No heading found')
            return

        if not heading.parent or not heading.parent.next_sibling:
            if mode == u'visual':
                vim.command(u'normal gv'.encode(u'utf-8'))
            else:
                echo(u'No parent heading found')
            return

        ns = heading.parent.next_sibling

        if mode == u'visual':
            cls._change_visual_selection(heading,
                                         ns,
                                         direction=DIRECTION_FORWARD,
                                         parent=False)
        elif mode == u'operator':
            vim.current.window.cursor = (ns.start_vim, 0)
        else:
            vim.current.window.cursor = (ns.start_vim, ns.level + 1)
        return ns
Esempio n. 7
0
    def parent_next_sibling(cls, mode):
        u"""
		Focus the parent's next sibling

		:returns: parent's next sibling heading or None
		"""
        heading = ORGMODE.get_document().current_heading()
        if not heading:
            if mode == u"visual":
                vim.command(u"normal! gv".encode(u"utf-8"))
            else:
                echo(u"No heading found")
            return

        if not heading.parent or not heading.parent.next_sibling:
            if mode == u"visual":
                vim.command(u"normal! gv".encode(u"utf-8"))
            else:
                echo(u"No parent heading found")
            return

        ns = heading.parent.next_sibling

        if mode == u"visual":
            cls._change_visual_selection(heading, ns, direction=Direction.FORWARD, parent=False)
        elif mode == u"operator":
            vim.current.window.cursor = (ns.start_vim, 0)
        else:
            vim.current.window.cursor = (ns.start_vim, ns.level + 1)
        return ns
Esempio n. 8
0
	def a_heading(cls, selection=u'inner', skip_children=False):
		u"""
		a heading text object
		"""
		heading = ORGMODE.get_document().current_heading()
		if heading:
			if selection != u'inner':
				heading = heading if not heading.parent else heading.parent

			line_start, col_start = [ int(i) for i in vim.eval(u'getpos("\'<")'.encode(u'utf-8'))[1:3] ]
			line_end, col_end = [ int(i) for i in vim.eval(u'getpos("\'>")'.encode(u'utf-8'))[1:3] ]

			start = line_start
			end = line_end

			if heading.start_vim < line_start:
				start = heading.start_vim
			if heading.end_vim > line_end and not skip_children:
				end = heading.end_vim
			elif heading.end_of_last_child_vim > line_end and skip_children:
				end = heading.end_of_last_child_vim

			swap_cursor = u'o' if vim.current.window.cursor[0] == line_start else u''

			vim.command((u'normal! %dgg%s%dgg$%s' % \
					(start, vim.eval(u'visualmode()'.encode(u'utf-8')), end, swap_cursor)).encode(u'utf-8'))
			if selection == u'inner':
				return u'OrgAInnerHeadingVisual' if not skip_children else u'OrgAInnerTreeVisual'
			else:
				return u'OrgAOuterHeadingVisual' if not skip_children else u'OrgAOuterTreeVisual'
		else:
			vim.command(u'normal! gv'.encode(u'utf-8'))
Esempio n. 9
0
	def _move_heading(cls, direction=Direction.FORWARD, including_children=True):
		u""" Move heading up or down

		:returns: heading or None
		"""
		d = ORGMODE.get_document()
		heading = d.current_heading()
		if (not heading) or \
				(direction == Direction.FORWARD and not heading.next_sibling) or \
				(direction == Direction.BACKWARD and not heading.previous_sibling):
			return None

		cursor_offset_within_the_heading_vim = vim.current.window.cursor[0] - (heading._orig_start + 1)

		if not including_children:
			heading.previous_sibling.children.extend(heading.children)
			del heading.children

		heading_insert_position = 0 if direction == Direction.FORWARD else -1
		l = heading.get_parent_list()
		idx = heading.get_index_in_parent_list()
		del l[idx]
		if l is not None and idx is not None:
			l.insert(idx + heading_insert_position, heading)
		else:
			raise HeadingDomError(u'Current heading is not properly linked in DOM')

		d.write()

		vim.current.window.cursor = (heading.start_vim + cursor_offset_within_the_heading_vim, vim.current.window.cursor[1])

		return True
Esempio n. 10
0
    def parent(cls, mode):
        u"""
		Focus parent heading

		:returns: parent heading or None
		"""
        heading = ORGMODE.get_document().current_heading()
        if not heading:
            if mode == u'visual':
                vim.command(u'normal gv'.encode(u'utf-8'))
            else:
                echo(u'No heading found')
            return

        if not heading.parent:
            if mode == u'visual':
                vim.command(u'normal gv'.encode(u'utf-8'))
            else:
                echo(u'No parent heading found')
            return

        p = heading.parent

        if mode == u'visual':
            cls._change_visual_selection(heading,
                                         p,
                                         direction=DIRECTION_BACKWARD,
                                         parent=True)
        else:
            vim.current.window.cursor = (p.start_vim, p.level + 1)
        return p
Esempio n. 11
0
	def set_tags(cls):
		u""" Set tags for current heading
		"""
		d = ORGMODE.get_document()
		heading = d.current_heading()
		if not heading:
			return

		# retrieve tags
		res = None
		if heading.tags:
			res = vim.eval(u'input("Tags: ", ":%s:", "customlist,Org_complete_tags")' % u':'.join(heading.tags))
		else:
			res = vim.eval(u'input("Tags: ", "", "customlist,Org_complete_tags")')

		if res is None:
			# user pressed <Esc> abort any further processing
			return

		# remove empty tags
		heading.tags = filter(lambda x: x.strip() != u'', res.decode(u'utf-8').strip().strip(u':').split(u':'))

		d.write()

		return u'OrgSetTags'
Esempio n. 12
0
	def parent(cls, mode):
		u"""
		Focus parent heading

		:returns: parent heading or None
		"""
		heading = ORGMODE.get_document().current_heading()
		if not heading:
			if mode == u'visual':
				vim.command(u'normal gv'.encode(u'utf-8'))
			else:
				echo(u'No heading found')
			return

		if not heading.parent:
			if mode == u'visual':
				vim.command(u'normal gv'.encode(u'utf-8'))
			else:
				echo(u'No parent heading found')
			return

		if mode == u'visual':
			cls._change_visual_selection(heading, heading.parent, direction=DIRECTION_BACKWARD, parent=True)
		else:
			vim.current.window.cursor = (heading.parent.start_vim, heading.parent.level + 1)
		return heading.parent
Esempio n. 13
0
	def _get_agendadocuments(self):
		u"""
		Return the org documents of the agenda files; return None if no
		agenda documents are defined.

		TODO: maybe turn this into an decorator?
		"""
		# load org files of agenda
		agenda_files = settings.get(u'org_agenda_files', u',')
		if not agenda_files or agenda_files == ',':
			echoe((u"No org_agenda_files defined. Use :let "
				u"g:org_agenda_files=['~/org/index.org'] to add " 
				u"files to the agenda view."))
			return

		agenda_files = [os.path.realpath(os.path.expanduser(f))
			for f in agenda_files]

		for agenda_file in agenda_files: 
			vim.command((u'badd %s' % agenda_file).encode(u'utf-8'))

		# determine the buffer nr of the agenda files
		agenda_nums = [get_bufnumber(fn) for fn in agenda_files]

		# collect all documents of the agenda files and create the agenda
		return [ORGMODE.get_document(i) for i in agenda_nums if i is not None]
Esempio n. 14
0
	def _get_agendadocuments(self):
		u"""
		Return the org documents of the agenda files; return None if no
		agenda documents are defined.

		TODO: maybe turn this into an decorator?
		"""
		# load org files of agenda
		agenda_files = settings.get(u'org_agenda_files', u',')
		if not agenda_files or agenda_files == ',':
			echoe((u"No org_agenda_files defined. Use :let "
				u"g:org_agenda_files=['~/org/index.org'] to add " 
				u"files to the agenda view."))
			return

		agenda_files = [os.path.expanduser(f) for f in agenda_files]

		for agenda_file in agenda_files: 
			vim.command((u'badd %s' % agenda_file).encode(u'utf-8'))

		# determine the buffer nr of the agenda files
		agenda_nums = [get_bufnumber(fn) for fn in agenda_files]

		# collect all documents of the agenda files and create the agenda
		return [ORGMODE.get_document(i) for i in agenda_nums if i is not None]
Esempio n. 15
0
	def parent_next_sibling(cls, mode):
		u"""
		Focus the parent's next sibling

		:returns: parent's next sibling heading or None
		"""
		heading = ORGMODE.get_document().current_heading()
		if not heading:
			if mode == u'visual':
				vim.command(u'normal gv'.encode(u'utf-8'))
			else:
				echo(u'No heading found')
			return

		if not heading.parent or not heading.parent.next_sibling:
			if mode == u'visual':
				vim.command(u'normal gv'.encode(u'utf-8'))
			else:
				echo(u'No parent heading found')
			return

		ns = heading.parent.next_sibling

		if mode == u'visual':
			cls._change_visual_selection(heading, ns, direction=DIRECTION_FORWARD, parent=False)
		elif mode == u'operator':
			vim.current.window.cursor = (ns.start_vim, 0)
		else:
			vim.current.window.cursor = (ns.start_vim, ns.level + 1)
		return ns
Esempio n. 16
0
	def jump_to_first_character(cls):
		heading = ORGMODE.get_document().current_heading()
		if not heading:
			vim.eval(u'feedkeys("^", "n")'.encode(u'utf-8'))
			return

		vim.current.window.cursor = (vim.current.window.cursor[0], heading.level + 1)
Esempio n. 17
0
    def parent(cls, mode):
        u"""
		Focus parent heading

		:returns: parent heading or None
		"""
        heading = ORGMODE.get_document().current_heading()
        if not heading:
            if mode == u"visual":
                vim.command(u"normal! gv".encode(u"utf-8"))
            else:
                echo(u"No heading found")
            return

        if not heading.parent:
            if mode == u"visual":
                vim.command(u"normal! gv".encode(u"utf-8"))
            else:
                echo(u"No parent heading found")
            return

        p = heading.parent

        if mode == u"visual":
            cls._change_visual_selection(heading, p, direction=Direction.BACKWARD, parent=True)
        else:
            vim.current.window.cursor = (p.start_vim, p.level + 1)
        return p
Esempio n. 18
0
	def edit_at_first_character(cls):
		heading = ORGMODE.get_document().current_heading()
		if not heading:
			vim.eval(u'feedkeys("I", "n")'.encode(u'utf-8'))
			return

		vim.current.window.cursor = (vim.current.window.cursor[0], heading.level + 1)
		vim.command(u'startinsert'.encode(u'utf-8'))
Esempio n. 19
0
    def jump_to_first_character(cls):
        heading = ORGMODE.get_document().current_heading()
        if not heading:
            vim.eval(u'feedkeys("^", "n")'.encode(u'utf-8'))
            return

        vim.current.window.cursor = (vim.current.window.cursor[0],
                                     heading.level + 1)
Esempio n. 20
0
	def setUp(self):
		global counter
		counter += 1
		vim.CMDHISTORY = []
		vim.CMDRESULTS = {}
		vim.EVALHISTORY = []
		vim.EVALRESULTS = {
				# no org_todo_keywords for b
				u'exists("b:org_todo_keywords")'.encode(u'utf-8'): '0'.encode(u'utf-8'),
				# global values for org_todo_keywords
				u'exists("g:org_todo_keywords")'.encode(u'utf-8'): '1'.encode(u'utf-8'),
				u'g:org_todo_keywords'.encode(u'utf-8'): [u'TODO'.encode(u'utf-8'), u'DONE'.encode(u'utf-8'), u'|'.encode(u'utf-8')],
				u'exists("g:org_improve_split_heading")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("b:org_improve_split_heading")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("g:org_debug")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("b:org_debug")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("*repeat#set()")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'b:changedtick'.encode(u'utf-8'): (u'%d' % counter).encode(u'utf-8'),
				u'&ts'.encode(u'utf-8'): u'8'.encode(u'utf-8'),
				u'exists("g:org_tag_column")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("b:org_tag_column")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u"v:count".encode(u'utf-8'): u'0'.encode(u'utf-8')}
		if not u'EditStructure' in ORGMODE.plugins:
			ORGMODE.register_plugin(u'EditStructure')
		self.editstructure = ORGMODE.plugins[u'EditStructure']
		vim.current.buffer[:] = [ i.encode(u'utf-8') for i in u"""
* Überschrift 1
Text 1

Bla bla
** Überschrift 1.1
Text 2

Bla Bla bla
** Überschrift 1.2
Text 3

**** Überschrift 1.2.1.falsch

Bla Bla bla bla
*** Überschrift 1.2.1
* Überschrift 2
* Überschrift 3
  asdf sdf
""".split(u'\n')]
Esempio n. 21
0
    def edit_at_first_character(cls):
        heading = ORGMODE.get_document().current_heading()
        if not heading or heading.start_vim != vim.current.window.cursor[0]:
            vim.eval(u'feedkeys("I", "n")'.encode(u'utf-8'))
            return

        vim.current.window.cursor = (vim.current.window.cursor[0],
                                     heading.level + 1)
        vim.command(u'startinsert'.encode(u'utf-8'))
Esempio n. 22
0
	def realign_all_tags(cls):
		u"""
		Updates tags when user finishes editing a heading
		"""
		d = ORGMODE.get_document()
		for heading in d.all_headings():
			heading.set_dirty_heading()

		d.write()
Esempio n. 23
0
    def _move_heading(cls,
                      direction=Direction.FORWARD,
                      including_children=True):
        u""" Move heading up or down

		:returns: heading or None
		"""
        d = ORGMODE.get_document()
        current_heading = d.current_heading()
        if not current_heading or \
          (direction == Direction.FORWARD and not current_heading.next_sibling) or \
          (direction == Direction.BACKWARD and not current_heading.previous_sibling):
            return None

        cursor_offset = vim.current.window.cursor[0] - (
            current_heading._orig_start + 1)
        l = current_heading.get_parent_list()
        if l is None:
            raise HeadingDomError(
                u'Current heading is not properly linked in DOM')

        if not including_children:
            if current_heading.previous_sibling:
                npl = current_heading.previous_sibling.children
                for child in current_heading.children:
                    npl.append(child, taint=False)
            elif current_heading.parent:
                # if the current heading doesn't have a previous sibling it
                # must be the first heading
                np = current_heading.parent
                for child in current_heading.children:
                    cls._append_heading(child, np)
            else:
                # if the current heading doesn't have a parent, its children
                # must be added as top level headings to the document
                npl = l
                for child in current_heading.children[::-1]:
                    npl.insert(0, child, taint=False)
            current_heading.children.remove_slice(
                0, len(current_heading.children), taint=False)

        idx = current_heading.get_index_in_parent_list()
        if idx is None:
            raise HeadingDomError(
                u'Current heading is not properly linked in DOM')

        offset = 1 if direction == Direction.FORWARD else -1
        del l[idx]
        l.insert(idx + offset, current_heading)

        d.write()

        vim.current.window.cursor = (current_heading.start_vim + cursor_offset, \
          vim.current.window.cursor[1])

        return True
Esempio n. 24
0
	def _change_heading_level(cls, level, including_children=True, on_heading=False):
		u"""
		Change level of heading realtively with or without including children.
		"""
		d = ORGMODE.get_document()
		h = d.current_heading()
		if not h or on_heading and h.start_vim != vim.current.window.cursor[0]:
			# TODO figure out the actually pressed keybinding and feed these
			# keys instead of making keys up like this
			if level > 0:
				if including_children:
					vim.eval((u'feedkeys(">]]", "n")').encode(u'utf-8'))
				elif on_heading:
					vim.eval(u'feedkeys(">>", "n")'.encode(u'utf-8'))
				else:
					vim.eval(u'feedkeys(">}", "n")'.encode(u'utf-8'))
			else:
				if including_children:
					vim.eval(u'feedkeys("<]]", "n")'.encode(u'utf-8'))
				elif on_heading:
					vim.eval(u'feedkeys("<<", "n")'.encode(u'utf-8'))
				else:
					vim.eval(u'feedkeys("<}", "n")'.encode(u'utf-8'))
			# return True because otherwise apply_count will not work
			return True

		# don't allow demotion below level 1
		if h.level == 1 and level < 1:
			return False

		# reduce level of demotion to a minimum heading level of 1
		if (h.level + level) < 1:
			level = 1

		def indent(heading, ic):
			if not heading:
				return
			heading.level += level

			if ic:
				for child in heading.children:
					indent(child, ic)

		# save cursor position
		c = vim.current.window.cursor[:]

		# indent the promoted/demoted heading
		indent_end_vim = h.end_of_last_child_vim if including_children else h.end_vim
		indent(h, including_children)
		d.write()
		if indent_end_vim != h.start_vim:
			vim.command((u'normal %dggV%dgg=' % (h.start_vim, indent_end_vim)).encode(u'utf-8'))
		# restore cursor position
		vim.current.window.cursor = (c[0], c[1] + level)

		return True
Esempio n. 25
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 not prompt_pos 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
Esempio n. 26
0
	def test_demote_last_heading(self):
		vim.current.buffer[:] = """
* Überschrift 2
* Überschrift 3""".split('\n')
		vim.current.window.cursor = (3, 0)
		h = ORGMODE.get_document().current_heading()
		self.assertNotEqual(self.editstructure.demote_heading(), None)
		self.assertEqual(h.end, 2)
		self.assertFalse(vim.CMDHISTORY)
		self.assertEqual(vim.current.buffer[2], '** Überschrift 3')
		self.assertEqual(vim.current.window.cursor, (3, 1))
Esempio n. 27
0
	def realign_tags(cls):
		u"""
		Updates tags when user finished editing a heading
		"""
		d = ORGMODE.get_document(allow_dirty=True)
		heading = d.find_current_heading()
		if not heading:
			return

		if vim.current.window.cursor[0] == heading.start_vim:
			heading.set_dirty_heading()
			d.write_heading(heading, including_children=False)
Esempio n. 28
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)
		lineno, colno = vim.current.window.cursor

		# 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
		current_state = heading.todo

		# get new state
		new_state = Todo._get_next_state(current_state, todo_states, \
				direction=direction, interactive=interactive, next_set=next_set)

		# move cursor along with the inserted state only when current position
		# is in the heading; otherwite do nothing
		if heading.start_vim == lineno:
			if current_state is None and new_state is None:
				offset = 0
			elif current_state is None:
				offset = len(new_state)
			elif new_state is None:
				offset = -len(current_state)
			else:
				offset = len(current_state) - len(new_state)
			vim.current.window.cursor = (lineno, colno + offset)

		# set new headline
		heading.todo = new_state

		# plug
		plug = u'OrgTodoForward'
		if direction == DIRECTION_BACKWARD:
			plug = u'OrgTodoBackward'

		d.write_heading(heading)

		return plug
Esempio n. 29
0
    def _move_heading(cls, direction=Direction.FORWARD, including_children=True):
        u""" Move heading up or down

		:returns: heading or None
		"""
        d = ORGMODE.get_document()
        current_heading = d.current_heading()
        if (
            not current_heading
            or (direction == Direction.FORWARD and not current_heading.next_sibling)
            or (direction == Direction.BACKWARD and not current_heading.previous_sibling)
        ):
            return None

        cursor_offset = vim.current.window.cursor[0] - (current_heading._orig_start + 1)
        l = current_heading.get_parent_list()
        if l is None:
            raise HeadingDomError(u"Current heading is not properly linked in DOM")

        if not including_children:
            if current_heading.previous_sibling:
                npl = current_heading.previous_sibling.children
                for child in current_heading.children:
                    npl.append(child, taint=False)
            elif current_heading.parent:
                # if the current heading doesn't have a previous sibling it
                # must be the first heading
                np = current_heading.parent
                for child in current_heading.children:
                    cls._append_heading(child, np)
            else:
                # if the current heading doesn't have a parent, its children
                # must be added as top level headings to the document
                npl = l
                for child in current_heading.children[::-1]:
                    npl.insert(0, child, taint=False)
            current_heading.children.remove_slice(0, len(current_heading.children), taint=False)

        idx = current_heading.get_index_in_parent_list()
        if idx is None:
            raise HeadingDomError(u"Current heading is not properly linked in DOM")

        offset = 1 if direction == Direction.FORWARD else -1
        del l[idx]
        l.insert(idx + offset, current_heading)

        d.write()

        vim.current.window.cursor = (current_heading.start_vim + cursor_offset, vim.current.window.cursor[1])

        return True
	def setUp(self):
		global counter
		counter += 1
		vim.CMDHISTORY = []
		vim.CMDRESULTS = {}
		vim.EVALHISTORY = []
		vim.EVALRESULTS = {
				u'exists("g:org_debug")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("g:org_debug")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("*repeat#set()")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'b:changedtick'.encode(u'utf-8'): (u'%d' % counter).encode(u'utf-8'),
				u'&ts'.encode(u'utf-8'): u'8'.encode(u'utf-8'),
				u'exists("g:org_tag_column")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u'exists("b:org_tag_column")'.encode(u'utf-8'): u'0'.encode(u'utf-8'),
				u"v:count".encode(u'utf-8'): u'0'.encode(u'utf-8')}
		if not u'EditStructure' in ORGMODE.plugins:
			ORGMODE.register_plugin(u'EditStructure')
		self.editstructure = ORGMODE.plugins[u'EditStructure']
		vim.current.buffer = [ i.encode(u'utf-8') for i in u"""
* Überschrift 1
Text 1

Bla bla
** Überschrift 1.1
Text 2

Bla Bla bla
** Überschrift 1.2
Text 3

**** Überschrift 1.2.1.falsch

Bla Bla bla bla
*** Überschrift 1.2.1
* Überschrift 2
* Überschrift 3
  asdf sdf
""".split(u'\n')]
	def setUp(self):
		vim.CMDHISTORY = []
		vim.CMDRESULTS = {}
		vim.EVALHISTORY = []
		vim.EVALRESULTS = {
				'exists("g:org_debug")': 0,
				'exists("b:org_debug")': 0,
				'exists("*repeat#set()")': 0,
				'exists("b:org_leader")': 0,
				'exists("g:org_leader")': 0,
				'exists("g:org_tags_column")': 0,
				'exists("b:org_tags_column")': 0,
				'exists("b:org_tags_completion_ignorecase")': 0,
				'exists("g:org_tags_completion_ignorecase")': 0,
				"v:count": 0}
		if not 'TagsProperties' in ORGMODE.plugins:
			ORGMODE.register_plugin('TagsProperties')
		self.showhide = ORGMODE.plugins['TagsProperties']
		vim.current.buffer = """
* Überschrift 1
Text 1

Bla bla
** Überschrift 1.1
Text 2

Bla Bla bla
** Überschrift 1.2
Text 3

**** Überschrift 1.2.1.falsch

Bla Bla bla bla
*** Überschrift 1.2.1
* Überschrift 2
* Überschrift 3
  asdf sdf
""".split('\n')
    def test_demote_last_heading(self):
        vim.current.buffer[:] = [
            i.encode(u'utf-8') for i in u"""
* Überschrift 2
* Überschrift 3""".split('\n')
        ]
        vim.current.window.cursor = (3, 0)
        h = ORGMODE.get_document().current_heading()
        self.assertNotEqual(self.editstructure.demote_heading(), None)
        self.assertEqual(h.end, 2)
        self.assertFalse(vim.CMDHISTORY)
        self.assertEqual(vim.current.buffer[2],
                         u'** Überschrift 3'.encode(u'utf-8'))
        self.assertEqual(vim.current.window.cursor, (3, 1))
Esempio n. 33
0
    def test_demote_last_heading(self):
        vim.current.buffer[:] = [
            i.encode(u"utf-8")
            for i in u"""
* Überschrift 2
* Überschrift 3""".split(
                "\n"
            )
        ]
        vim.current.window.cursor = (3, 0)
        h = ORGMODE.get_document().current_heading()
        self.assertNotEqual(self.editstructure.demote_heading(), None)
        self.assertEqual(h.end, 2)
        self.assertFalse(vim.CMDHISTORY)
        self.assertEqual(vim.current.buffer[2], u"** Überschrift 3".encode(u"utf-8"))
        self.assertEqual(vim.current.window.cursor, (3, 1))
Esempio n. 34
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:
			# pass todo states to new window
			ORGTODOSTATES[d.bufnr] = todo_states
			if bool(int(vim.eval(( u'bufexists("org:todo/%d")' % (d.bufnr, ) ).encode(u'utf-8')))):
				# if the buffer already exists, reuse it
				vim.command((u'sbuffer org:todo/%d' % (d.bufnr, )).encode(u'utf-8'))
			else:
				# create a new window
				vim.command((u'keepalt %dsp org:todo/%d' % (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
Esempio n. 35
0
	def complete_tags(cls):
		u""" build a list of tags and store it in variable b:org_tag_completion
		"""
		d = ORGMODE.get_document()
		heading = d.current_heading()
		if not heading:
			return

		leading_portion = vim.eval(u'a:ArgLead').decode(u'utf-8')
		cursor = int(vim.eval(u'a:CursorPos'))

		# extract currently completed tag
		idx_orig = leading_portion.rfind(u':', 0, cursor)
		if idx_orig == -1:
			idx = 0
		else:
			idx = idx_orig

		current_tag = leading_portion[idx: cursor].lstrip(u':')
		head = leading_portion[:idx + 1]
		if idx_orig == -1:
			head = u''
		tail = leading_portion[cursor:]

		# extract all tags of the current file
		all_tags = set()
		for h in d.all_headings():
			for t in h.tags:
				all_tags.add(t)

		ignorecase = bool(int(settings.get(u'org_tag_completion_ignorecase', int(vim.eval(u'&ignorecase')))))
		possible_tags = []
		current_tags = heading.tags
		for t in all_tags:
			if ignorecase:
				if t.lower().startswith(current_tag.lower()):
					possible_tags.append(t)
			elif t.startswith(current_tag):
				possible_tags.append(t)

		vim.command((u'let b:org_complete_tags = [%s]' % u', '.join([u'"%s%s:%s"' % (head, i, tail) for i in possible_tags])).encode(u'utf-8'))
Esempio n. 36
0
    def a_heading(cls, selection=u'inner', skip_children=False):
        u"""
		a heading text object
		"""
        heading = ORGMODE.get_document().current_heading()
        if heading:
            if selection != u'inner':
                heading = heading if not heading.parent else heading.parent

            line_start, col_start = [
                int(i)
                for i in vim.eval(u'getpos("\'<")'.encode(u'utf-8'))[1:3]
            ]
            line_end, col_end = [
                int(i)
                for i in vim.eval(u'getpos("\'>")'.encode(u'utf-8'))[1:3]
            ]

            start = line_start
            end = line_end

            if heading.start_vim < line_start:
                start = heading.start_vim
            if heading.end_vim > line_end and not skip_children:
                end = heading.end_vim
            elif heading.end_of_last_child_vim > line_end and skip_children:
                end = heading.end_of_last_child_vim

            swap_cursor = u'o' if vim.current.window.cursor[
                0] == line_start else u''

            vim.command((u'normal! %dgg%s%dgg$%s' % \
              (start, vim.eval(u'visualmode()'.encode(u'utf-8')), end, swap_cursor)).encode(u'utf-8'))
            if selection == u'inner':
                return u'OrgAInnerHeadingVisual' if not skip_children else u'OrgAInnerTreeVisual'
            else:
                return u'OrgAOuterHeadingVisual' if not skip_children else u'OrgAOuterTreeVisual'
        else:
            vim.command(u'normal! gv'.encode(u'utf-8'))
Esempio n. 37
0
    def set_todo_state(cls, state):
        u""" Set todo state for buffer.

		:bufnr:		Number of buffer the todo state should be updated for
		:state:		The new todo state
		"""
        lineno, colno = vim.current.window.cursor
        d = ORGMODE.get_document(allow_dirty=True)
        heading = d.find_current_heading()

        if not heading:
            return

        current_state = heading.todo

        # set new headline
        heading.todo = state
        d.write_heading(heading)

        # move cursor along with the inserted state only when current position
        # is in the heading; otherwite do nothing
        if heading.start_vim == lineno and colno > heading.level:
            if current_state is not None and \
              colno <= heading.level + len(current_state):
                # the cursor is actually on the todo keyword
                # move it back to the beginning of the keyword in that case
                vim.current.window.cursor = (lineno, heading.level + 1)
            else:
                # the cursor is somewhere in the text, move it along
                if current_state is None and state is None:
                    offset = 0
                elif current_state is None and state is not None:
                    offset = len(state) + 1
                elif current_state is not None and state is None:
                    offset = -len(current_state) - 1
                else:
                    offset = len(state) - len(current_state)
                vim.current.window.cursor = (lineno, colno + offset)
Esempio n. 38
0
	def set_todo_state(cls, state):
		u""" Set todo state for buffer.

		:bufnr:		Number of buffer the todo state should be updated for
		:state:		The new todo state
		"""
		lineno, colno = vim.current.window.cursor
		d = ORGMODE.get_document(allow_dirty=True)
		heading = d.find_current_heading()

		if not heading:
			return

		current_state = heading.todo

		# set new headline
		heading.todo = state
		d.write_heading(heading)

		# move cursor along with the inserted state only when current position
		# is in the heading; otherwite do nothing
		if heading.start_vim == lineno and colno > heading.level:
			if current_state is not None and \
					colno <= heading.level + len(current_state):
				# the cursor is actually on the todo keyword
				# move it back to the beginning of the keyword in that case
				vim.current.window.cursor = (lineno, heading.level + 1)
			else:
				# the cursor is somewhere in the text, move it along
				if current_state is None and state is None:
					offset = 0
				elif current_state is None and state is not None:
					offset = len(state) + 1
				elif current_state is not None and state is None:
					offset = -len(current_state) - 1
				else:
					offset = len(state) - len(current_state)
				vim.current.window.cursor = (lineno, colno + offset)
Esempio n. 39
0
	def list_timeline(cls):
		"""
		List a timeline of the current buffer to get an overview of the
		current file.
		"""
		raw_agenda = ORGMODE.agenda_manager.get_timestamped_items(
				[ORGMODE.get_document()])

		# create buffer at bottom
		cmd = [u'setlocal filetype=orgagenda']
		cls._switch_to(u'AGENDA', cmd)

		cls.line2doc = {}
		# format text of agenda
		final_agenda = []
		for i, h in enumerate(raw_agenda):
			tmp = u"%s %s" % (h.todo, h.title)
			final_agenda.append(tmp)
			cls.line2doc[len(final_agenda)] = (get_bufname(h.document.bufnr), h.document.bufnr, h.start)

		# show agenda
		vim.current.buffer[:] = [ i.encode(u'utf-8') for i in final_agenda ]
		vim.command(u'setlocal nomodifiable conceallevel=2 concealcursor=nc'.encode(u'utf-8'))
Esempio n. 40
0
	def list_timeline(cls):
		"""
		List a timeline of the current buffer to get an overview of the
		current file.
		"""
		raw_agenda = ORGMODE.agenda_manager.get_timestamped_items(
				[ORGMODE.get_document()])

		# create buffer at bottom
		cmd = [u'setlocal filetype=orgagenda']
		cls._switch_to(u'AGENDA', cmd)

		cls.line2doc = {}
		# format text of agenda
		final_agenda = []
		for i, h in enumerate(raw_agenda):
			tmp = u"%s %s" % (h.todo, h.title)
			final_agenda.append(tmp)
			cls.line2doc[len(final_agenda)] = (get_bufname(h.document.bufnr), h.document.bufnr, h.start)

		# show agenda
		vim.current.buffer[:] = [ i.encode(u'utf-8') for i in final_agenda ]
		vim.command(u'setlocal nomodifiable conceallevel=2 concealcursor=nc'.encode(u'utf-8'))
Esempio n. 41
0
    def i_heading(cls,
                  mode=u'visual',
                  selection=u'inner',
                  skip_children=False):
        u"""
		inner heading text object
		"""
        heading = ORGMODE.get_document().current_heading()
        if heading:
            if selection != u'inner':
                heading = heading if not heading.parent else heading.parent

            line_start, col_start = [
                int(i)
                for i in vim.eval(u'getpos("\'<")'.encode(u'utf-8'))[1:3]
            ]
            line_end, col_end = [
                int(i)
                for i in vim.eval(u'getpos("\'>")'.encode(u'utf-8'))[1:3]
            ]

            if mode != u'visual':
                line_start = vim.current.window.cursor[0]
                line_end = line_start

            start = line_start
            end = line_end
            move_one_character_back = u'' if mode == u'visual' else u'h'

            if heading.start_vim < line_start:
                start = heading.start_vim
            if heading.end_vim > line_end and not skip_children:
                end = heading.end_vim
            elif heading.end_of_last_child_vim > line_end and skip_children:
                end = heading.end_of_last_child_vim

            if mode != u'visual' and not vim.current.buffer[end - 1]:
                end -= 1
                move_one_character_back = u''

            swap_cursor = u'o' if vim.current.window.cursor[
                0] == line_start else u''

            if selection == u'inner' and vim.current.window.cursor[
                    0] != line_start:
                h = ORGMODE.get_document().current_heading()
                if h:
                    heading = h

            visualmode = vim.eval(u'visualmode()').decode(
                u'utf-8') if mode == u'visual' else u'v'

            if line_start == start and line_start != heading.start_vim:
                if col_start in (0, 1):
                    vim.command((u'normal! %dgg0%s%dgg$%s%s' % \
                      (start, visualmode, end, move_one_character_back, swap_cursor)).encode(u'utf-8'))
                else:
                    vim.command((u'normal! %dgg0%dl%s%dgg$%s%s' % \
                      (start, col_start - 1, visualmode, end, move_one_character_back, swap_cursor)).encode(u'utf-8'))
            else:
                vim.command((u'normal! %dgg0%dl%s%dgg$%s%s' % \
                  (start, heading.level + 1, visualmode, end, move_one_character_back, swap_cursor)).encode(u'utf-8'))

            if selection == u'inner':
                if mode == u'visual':
                    return u'OrgInnerHeadingVisual' if not skip_children else u'OrgInnerTreeVisual'
                else:
                    return u'OrgInnerHeadingOperator' if not skip_children else u'OrgInnerTreeOperator'
            else:
                if mode == u'visual':
                    return u'OrgOuterHeadingVisual' if not skip_children else u'OrgOuterTreeVisual'
                else:
                    return u'OrgOuterHeadingOperator' if not skip_children else u'OrgOuterTreeOperator'
        elif mode == u'visual':
            vim.command(u'normal! gv'.encode(u'utf-8'))
Esempio n. 42
0
    def _focus_heading(cls,
                       mode,
                       direction=DIRECTION_FORWARD,
                       skip_children=False):
        u"""
		Focus next or previous heading in the given direction

		:direction: True for next heading, False for previous heading
		:returns: next heading or None
		"""
        d = ORGMODE.get_document()
        current_heading = d.current_heading()
        heading = current_heading
        focus_heading = None
        # FIXME this is just a piece of really ugly and unmaintainable code. It
        # should be rewritten
        if not heading:
            if direction == DIRECTION_FORWARD and d.headings \
              and vim.current.window.cursor[0] < d.headings[0].start_vim:
                # the cursor is in the meta information are, therefore focus
                # first heading
                focus_heading = d.headings[0]
            if not (heading or focus_heading):
                if mode == u'visual':
                    # restore visual selection when no heading was found
                    vim.command(u'normal gv'.encode(u'utf-8'))
                else:
                    echo(u'No heading found')
                return
        elif direction == DIRECTION_BACKWARD:
            if vim.current.window.cursor[0] != heading.start_vim:
                # the cursor is in the body of the current heading, therefore
                # the current heading will be focused
                if mode == u'visual':
                    line_start, col_start = [
                        int(i) for i in vim.eval(u'getpos("\'<")'.encode(
                            u'utf-8'))[1:3]
                    ]
                    line_end, col_end = [
                        int(i) for i in vim.eval(u'getpos("\'>")'.encode(
                            u'utf-8'))[1:3]
                    ]
                    if line_start >= heading.start_vim and line_end > heading.start_vim:
                        focus_heading = heading
                else:
                    focus_heading = heading

        # so far no heading has been found that the next focus should be on
        if not focus_heading:
            if not skip_children and direction == DIRECTION_FORWARD and heading.children:
                focus_heading = heading.children[0]
            elif direction == DIRECTION_FORWARD and heading.next_sibling:
                focus_heading = heading.next_sibling
            elif direction == DIRECTION_BACKWARD and heading.previous_sibling:
                focus_heading = heading.previous_sibling
                if not skip_children:
                    while focus_heading.children:
                        focus_heading = focus_heading.children[-1]
            else:
                if direction == DIRECTION_FORWARD:
                    focus_heading = current_heading.next_heading
                else:
                    focus_heading = current_heading.previous_heading

        noheadingfound = False
        if not focus_heading:
            if mode in (u'visual', u'operator'):
                # the cursor seems to be on the last or first heading of this
                # document and performes another next/previous operation
                focus_heading = heading
                noheadingfound = True
            else:
                if direction == DIRECTION_FORWARD:
                    echo(u'Already focussing last heading')
                else:
                    echo(u'Already focussing first heading')
                return

        if mode == u'visual':
            cls._change_visual_selection(current_heading,
                                         focus_heading,
                                         direction=direction,
                                         noheadingfound=noheadingfound)
        elif mode == u'operator':
            if direction == DIRECTION_FORWARD and vim.current.window.cursor[
                    0] >= focus_heading.start_vim:
                vim.current.window.cursor = (
                    focus_heading.end_vim,
                    len(vim.current.buffer[focus_heading.end].decode(u'utf-8'))
                )
            else:
                vim.current.window.cursor = (focus_heading.start_vim, 0)
        else:
            vim.current.window.cursor = (focus_heading.start_vim,
                                         focus_heading.level + 1)
        if noheadingfound:
            return
        return focus_heading
Esempio n. 43
0
	def new_heading(cls, below=None, insert_mode=False, end_of_last_child=False):
		"""
		:below:				True, insert heading below current heading, False,
							insert heading above current heading, None, special
							behavior for insert mode, use the current text as
							heading
		:insert_mode:		True, if action is performed in insert mode
		:end_of_last_child:	True, insert heading at the end of last child,
							otherwise the newly created heading will "take
							over" the current heading's children
		"""
		d = ORGMODE.get_document()
		h = d.current_heading()
		cursor = vim.current.window.cursor[:]
		if not h:
			# the user is in meta data region
			pos = cursor[0] - 1
			heading = Heading(body=d.meta_information[pos:])
			d.headings.insert(0, heading)
			del d.meta_information[pos:]
			d.write()
			vim.current.window.cursor = (pos + 1, heading.level + 1)
			return

		heading = Heading(level=h.level)

		# it's weird but this is the behavior of original orgmode
		if below is None:
			below = cursor[1] != 0 or end_of_last_child

		heading_insert_position = 0
		if below:
			heading_insert_position = 1
			if not end_of_last_child:
				# append heading at the end of current heading but also take
				# over the children of current heading
				heading.children = h.children[:]
				del h.children

		# insert newly created heading
		l = h.get_parent_list()
		idx = h.get_index_in_parent_list()
		if l is not None and idx is not None:
			l.insert(idx + heading_insert_position, heading)
		else:
			raise HeadingDomError('Current heading is not properly linked in DOM')

		d.write()

		# if cursor is currently on a heading, insert parts of it into the
		# newly created heading
		# TODO implement me
		#if insert_mode and not end_of_last_child and cursor[0] == h.start_vim:
		#	if cursor[1] > h.level:
		#		tmp1 = vim.current.buffer[cursor[0] - 1][:cursor[1]]
		#		tmp2 = vim.current.buffer[cursor[0] - 1][cursor[1]:]
		#		vim.current.buffer[cursor[0] - 1] = tmp1
		#	else:
		#		tmp2 = u''
		#	if below:
		#		vim.current.buffer[cursor[0]:cursor[0]] = [(u'%s %s' % (u'*' * level, tmp2.lstrip())).encode(u'utf-8')]
		#		vim.current.window.cursor = (cursor[0] + 1, level + 1)
		#	else:
		#		# this can only happen at column 0
		#		vim.current.buffer[cursor[0] - 1:cursor[0] - 1] = [(u'%s ' % (u'*' * level, )).encode(u'utf-8')]
		#		vim.current.window.cursor = (cursor[0], level + 1)

		if insert_mode:
			vim.command((u'exe "normal %dgg"|startinsert!' % (heading.start_vim, )).encode(u'utf-8'))
		else:
			vim.current.window.cursor = (cursor[0], cursor[1] + heading.level + 1)

		# return newly created heading
		return heading
Esempio n. 44
0
    def _change_heading_level(cls,
                              level,
                              including_children=True,
                              on_heading=False,
                              insert_mode=False):
        u"""
		Change level of heading realtively with or without including children.

		:level:					the number of levels to promote/demote heading
		:including_children:	True if should should be included in promoting/demoting
		:on_heading:			True if promoting/demoting should only happen when the cursor is on the heading
		:insert_mode:			True if vim is in insert mode
		"""
        d = ORGMODE.get_document()
        current_heading = d.current_heading()
        if not current_heading or on_heading and current_heading.start_vim != vim.current.window.cursor[
                0]:
            # TODO figure out the actually pressed keybinding and feed these
            # keys instead of making keys up like this
            if level > 0:
                if insert_mode:
                    vim.eval(u'feedkeys("\<C-t>", "n")'.encode(u'utf-8'))
                elif including_children:
                    vim.eval(u'feedkeys(">]]", "n")'.encode(u'utf-8'))
                elif on_heading:
                    vim.eval(u'feedkeys(">>", "n")'.encode(u'utf-8'))
                else:
                    vim.eval(u'feedkeys(">}", "n")'.encode(u'utf-8'))
            else:
                if insert_mode:
                    vim.eval(u'feedkeys("\<C-d>", "n")'.encode(u'utf-8'))
                elif including_children:
                    vim.eval(u'feedkeys("<]]", "n")'.encode(u'utf-8'))
                elif on_heading:
                    vim.eval(u'feedkeys("<<", "n")'.encode(u'utf-8'))
                else:
                    vim.eval(u'feedkeys("<}", "n")'.encode(u'utf-8'))
            # return True because otherwise apply_count will not work
            return True

        # don't allow demotion below level 1
        if current_heading.level == 1 and level < 1:
            return False

        # reduce level of demotion to a minimum heading level of 1
        if (current_heading.level + level) < 1:
            level = 1

        def indent(heading, ic):
            if not heading:
                return
            heading.level += level

            if ic:
                for child in heading.children:
                    indent(child, ic)

        # save cursor position
        c = vim.current.window.cursor[:]

        # indent the promoted/demoted heading
        indent_end_vim = current_heading.end_of_last_child_vim if including_children else current_heading.end_vim
        indent(current_heading, including_children)

        # when changing the level of a heading, its position in the DOM
        # needs to be updated. It's likely that the heading gets a new
        # parent and new children when demoted or promoted

        # find new parent
        p = current_heading.parent
        pl = current_heading.get_parent_list()
        ps = current_heading.previous_sibling
        nhl = current_heading.level

        if level > 0:
            # demotion
            # subheading or top level heading
            if ps and nhl > ps.level:
                pl.remove(current_heading, taint=False)
                # find heading that is the new parent heading
                oh = ps
                h = ps
                while nhl > h.level:
                    oh = h
                    if h.children:
                        h = h.children[-1]
                    else:
                        break
                np = h if nhl > h.level else oh

                # append current heading to new heading
                np.children.append(current_heading, taint=False)

                # if children are not included, distribute them among the
                # parent heading and it's siblings
                if not including_children:
                    for h in current_heading.children[:]:
                        if h and h.level <= nhl:
                            cls._append_heading(h, np)
                            current_heading.children.remove(h, taint=False)
        else:
            # promotion
            if p and nhl <= p.level:
                idx = current_heading.get_index_in_parent_list() + 1
                # find the new parent heading
                oh = p
                h = p
                while nhl <= h.level:
                    # append new children to current heading
                    for child in h.children[idx:]:
                        cls._append_heading(child, current_heading)
                    h.children.remove_slice(idx, len(h.children), taint=False)
                    idx = h.get_index_in_parent_list() + 1
                    if h.parent:
                        h = h.parent
                    else:
                        break
                ns = oh.next_sibling
                while ns and ns.level > current_heading.level:
                    nns = ns.next_sibling
                    cls._append_heading(ns, current_heading)
                    ns = nns

                # append current heading to new parent heading / document
                pl.remove(current_heading, taint=False)
                if nhl > h.level:
                    h.children.insert(idx, current_heading, taint=False)
                else:
                    d.headings.insert(idx, current_heading, taint=False)

        d.write()
        if indent_end_vim != current_heading.start_vim:
            vim.command(
                (u'normal %dggV%dgg=' %
                 (current_heading.start_vim, indent_end_vim)).encode(u'utf-8'))
        # restore cursor position
        vim.current.window.cursor = (c[0], c[1] + level)

        return True
Esempio n. 45
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 not prompt_pos 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
Esempio n. 46
0
	def toggle_folding(cls):
		u""" Toggle folding similar to the way orgmode does

		This is just a convenience function, don't hesitate to use the z*
		keybindings vim offers to deal with folding!
		"""
		d = ORGMODE.get_document()
		heading = d.current_heading()
		if not heading:
			vim.eval(u'feedkeys("<Tab>", "n")'.encode(u'utf-8'))
			return

		cursor = vim.current.window.cursor[:]

		if int(vim.eval((u'foldclosed(%d)' % heading.start_vim).encode(u'utf-8'))) != -1:
			# open closed fold
			p = heading.number_of_parents
			if not p:
				p = heading.level
			vim.command((u'normal %dzo' % p).encode(u'utf-8'))
			vim.current.window.cursor = cursor
			return heading

		found_fold = False
		open_depth = 0

		def fold_depth(h):
			if int(vim.eval((u'foldclosed(%d)' % h.start_vim).encode(u'utf-8'))) != -1:
				return (h.number_of_parents, True)
			else:
				res = [h.number_of_parents + 1]
				found = False

				for c in h.children:
					d, f = fold_depth(c)
					res.append(d)
					found |= f

				return (max(res), found)

		def open_fold(h):
			if h.number_of_parents <= open_depth:
				vim.command((u'normal %dgg%dzo' % (h.start_vim, open_depth)).encode(u'utf-8'))
			if h.children:
				for c in h.children:
					open_fold(c)

		# find deepest fold
		open_depth, found_fold = fold_depth(heading)

		# recursively open folds
		for child in heading.children:
			# find deepest fold
			if found_fold:
				open_fold(child)

		if not found_fold:
			vim.command((u'%d,%dfoldclose!' % (heading.start_vim, heading.end_of_last_child_vim)).encode(u'utf-8'))

			if heading.number_of_parents:
				# restore cursor position, it might have been changed by open_fold
				vim.current.window.cursor = cursor

				p = heading.number_of_parents
				if not p:
					p = heading.level
				# reopen fold again beacause the former closing of the fold closed all levels, including parents!
				vim.command((u'normal %dzo' % (p, )).encode(u'utf-8'))

		# restore cursor position
		vim.current.window.cursor = cursor
		return heading
Esempio n. 47
0
    def _focus_heading(cls,
                       mode,
                       direction=DIRECTION_FORWARD,
                       skip_children=False):
        u"""
		Focus next or previous heading in the given direction

		:direction: True for next heading, False for previous heading
		:returns: next heading or None
		"""
        d = ORGMODE.get_document()
        current_heading = d.current_heading()
        heading = current_heading
        focus_heading = None
        if not heading:
            if direction == DIRECTION_FORWARD and d.headings \
              and vim.current.window.cursor[0] < d.headings[0].start_vim:
                focus_heading = d.headings[0]
            if not (heading or focus_heading):
                if mode == u'visual':
                    # restore visual selection when no heading was found
                    vim.command(u'normal gv'.encode(u'utf-8'))
                else:
                    echo(u'No heading found')
                return
        elif direction == DIRECTION_BACKWARD:
            if vim.current.window.cursor[0] != heading.start_vim:
                if mode == u'visual':
                    # TODO maybe this has to be changed!
                    line_start, col_start = [
                        int(i) for i in vim.eval(u'getpos("\'<")'.encode(
                            u'utf-8'))[1:3]
                    ]
                    line_end, col_end = [
                        int(i) for i in vim.eval(u'getpos("\'>")'.encode(
                            u'utf-8'))[1:3]
                    ]
                    if line_start >= heading.start_vim and line_end > heading.start_vim:
                        focus_heading = heading
                else:
                    focus_heading = heading

        if not focus_heading:
            if not skip_children and direction == DIRECTION_FORWARD and heading.children:
                focus_heading = heading.children[0]
            elif direction == DIRECTION_FORWARD and heading.next_sibling:
                focus_heading = heading.next_sibling
            elif direction == DIRECTION_BACKWARD and heading.previous_sibling:
                focus_heading = heading.previous_sibling
                if not skip_children:
                    while focus_heading.children:
                        focus_heading = focus_heading.children[-1]
            else:
                while heading.level > 1:
                    if heading.parent:
                        if direction == DIRECTION_FORWARD and heading.parent.next_sibling:
                            focus_heading = heading.parent.next_sibling
                            break
                        elif direction == DIRECTION_BACKWARD:
                            focus_heading = heading.parent
                            break
                        else:
                            heading = heading.parent
                    else:
                        break

        noheadingfound = False
        if not focus_heading:
            if mode in (u'visual', u'operator'):
                # the cursor seems to be on the last or first heading of this
                # document and performes another next/previous-operation
                focus_heading = heading
                noheadingfound = True
            else:
                if direction == DIRECTION_FORWARD:
                    echo(u'Already focussing last heading')
                else:
                    echo(u'Already focussing first heading')
                return

        if mode == u'visual':
            cls._change_visual_selection(current_heading,
                                         focus_heading,
                                         mode,
                                         direction=direction,
                                         noheadingfound=noheadingfound)
        elif mode == u'operator':
            if direction == DIRECTION_FORWARD and vim.current.window.cursor[
                    0] >= focus_heading.start_vim:
                vim.current.window.cursor = (
                    focus_heading.end_vim,
                    len(vim.current.buffer[focus_heading.end]))
            else:
                vim.current.window.cursor = (focus_heading.start_vim, 0)
        else:
            vim.current.window.cursor = (focus_heading.start_vim,
                                         focus_heading.level + 1)
        if noheadingfound:
            return
        return focus_heading
Esempio n. 48
0
	def toggle_folding(cls, reverse=False):
		u""" Toggle folding similar to the way orgmode does

		This is just a convenience function, don't hesitate to use the z*
		keybindings vim offers to deal with folding!

		:reverse:	If False open folding by one level otherwise close it by one.
		"""
		d = ORGMODE.get_document()
		heading = d.current_heading()
		if not heading:
			vim.eval(u'feedkeys("<Tab>", "n")'.encode(u'utf-8'))
			return

		cursor = vim.current.window.cursor[:]

		if int(vim.eval((u'foldclosed(%d)' % heading.start_vim).encode(u'utf-8'))) != -1:
			if not reverse:
				# open closed fold
				p = heading.number_of_parents
				if not p:
					p = heading.level
				vim.command((u'normal! %dzo' % p).encode(u'utf-8'))
			else:
				# reverse folding opens all folds under the cursor
				vim.command((u'%d,%dfoldopen!' % (heading.start_vim, heading.end_of_last_child_vim)).encode(u'utf-8'))
			vim.current.window.cursor = cursor
			return heading

		def open_fold(h):
			if h.number_of_parents <= open_depth:
				vim.command((u'normal! %dgg%dzo' % (h.start_vim, open_depth)).encode(u'utf-8'))
			for c in h.children:
				open_fold(c)

		def close_fold(h):
			for c in h.children:
				close_fold(c)
			if h.number_of_parents >= open_depth - 1 and \
					int(vim.eval((u'foldclosed(%d)' % h.start_vim).encode(u'utf-8'))) == -1:
				vim.command((u'normal! %dggzc' % (h.start_vim, )).encode(u'utf-8'))

		# find deepest fold
		open_depth, found_fold = cls._fold_depth(heading)

		if not reverse:
			# recursively open folds
			if found_fold:
				for child in heading.children:
					open_fold(child)
			else:
				vim.command((u'%d,%dfoldclose!' % (heading.start_vim, heading.end_of_last_child_vim)).encode(u'utf-8'))

				if heading.number_of_parents:
					# restore cursor position, it might have been changed by open_fold
					vim.current.window.cursor = cursor

					p = heading.number_of_parents
					if not p:
						p = heading.level
					# reopen fold again beacause the former closing of the fold closed all levels, including parents!
					vim.command((u'normal! %dzo' % (p, )).encode(u'utf-8'))
		else:
			# close the last level of folds
			close_fold(heading)

		# restore cursor position
		vim.current.window.cursor = cursor
		return heading
Esempio n. 49
0
    def new_heading(cls,
                    below=None,
                    insert_mode=False,
                    end_of_last_child=False):
        u"""
		:below:				True, insert heading below current heading, False,
							insert heading above current heading, None, special
							behavior for insert mode, use the current text as
							heading
		:insert_mode:		True, if action is performed in insert mode
		:end_of_last_child:	True, insert heading at the end of last child,
							otherwise the newly created heading will "take
							over" the current heading's children
		"""
        d = ORGMODE.get_document()
        current_heading = d.current_heading()
        cursor = vim.current.window.cursor[:]
        if not current_heading:
            # the user is in meta data region
            pos = cursor[0] - 1
            heading = Heading(title=d.meta_information[pos],
                              body=d.meta_information[pos + 1:])
            d.headings.insert(0, heading)
            del d.meta_information[pos:]
            d.write()
            vim.command((u'exe "normal %dgg"|startinsert!' %
                         (heading.start_vim, )).encode(u'utf-8'))
            return heading

        heading = Heading(level=current_heading.level)

        # it's weird but this is the behavior of original orgmode
        if below is None:
            below = cursor[1] != 0 or end_of_last_child

        # insert newly created heading
        l = current_heading.get_parent_list()
        idx = current_heading.get_index_in_parent_list()
        if l is not None and idx is not None:
            l.insert(idx + (1 if below else 0), heading)
        else:
            raise HeadingDomError(
                u'Current heading is not properly linked in DOM')

        if below and not end_of_last_child:
            # append heading at the end of current heading and also take
            # over the children of current heading
            for child in current_heading.children:
                heading.children.append(child, taint=False)
            current_heading.children.remove_slice(0, len(current_heading.children), \
              taint=False)

        # if cursor is currently on a heading, insert parts of it into the
        # newly created heading
        if insert_mode and cursor[1] != 0 and cursor[
                0] == current_heading.start_vim:
            offset = cursor[1] - current_heading.level - 1 - (len(current_heading.todo) \
              + 1 if current_heading.todo else 0)
            if offset < 0:
                offset = 0
            if int(settings.get(u'org_improve_split_heading', u'1')) and \
              offset > 0 and len(current_heading.title) == offset + 1 \
              and current_heading.title[offset - 1] not in (u' ', u'\t'):
                offset += 1
            heading.title = current_heading.title[offset:]
            current_heading.title = current_heading.title[:offset]
            heading.body = current_heading.body[:]
            current_heading.body = []

        d.write()
        vim.command((u'exe "normal %dgg"|startinsert!' %
                     (heading.start_vim, )).encode(u'utf-8'))

        # return newly created heading
        return heading