Source code for docx.text.tabstops

"""Tabstop-related proxy types."""

from __future__ import annotations

from typing import TYPE_CHECKING, Iterator, cast

from docx.enum.text import WD_TAB_ALIGNMENT, WD_TAB_LEADER
from docx.shared import ElementProxy

if TYPE_CHECKING:
    from docx.oxml.text.parfmt import CT_PPr, CT_TabStop, CT_TabStops
    from docx.shared import Length


[docs] class TabStops(ElementProxy): """A sequence of |TabStop| objects providing access to the tab stops of a paragraph or paragraph style. Supports iteration, indexed access, del, and len(). It is accesed using the :attr:`~.ParagraphFormat.tab_stops` property of ParagraphFormat; it is not intended to be constructed directly. """ def __init__(self, element: CT_PPr): super(TabStops, self).__init__(element, None) self._pPr = element def __delitem__(self, idx: int): """Remove the tab at offset `idx` in this sequence.""" tabs = self._pPr.tabs if tabs is None: raise IndexError("tab index out of range") try: tabs.remove(tabs.tab_lst[idx]) except IndexError: raise IndexError("tab index out of range") if len(tabs.tab_lst) == 0: self._pPr.remove(tabs) def __getitem__(self, idx: int) -> TabStop: """Enables list-style access by index.""" tabs = self._pPr.tabs if tabs is None: raise IndexError("TabStops object is empty") tab = tabs.tab_lst[idx] return TabStop(tab) def __iter__(self) -> Iterator[TabStop]: """Generate a TabStop object for each of the w:tab elements, in XML document order.""" tabs = self._pPr.tabs if tabs is not None: for tab in tabs.tab_lst: yield TabStop(tab) def __len__(self) -> int: tabs = self._pPr.tabs if tabs is None: return 0 return len(tabs.tab_lst)
[docs] def add_tab_stop( self, position: Length, alignment: WD_TAB_ALIGNMENT = WD_TAB_ALIGNMENT.LEFT, leader: WD_TAB_LEADER = WD_TAB_LEADER.SPACES, ) -> TabStop: """Add a new tab stop at `position`, a |Length| object specifying the location of the tab stop relative to the paragraph edge. A negative `position` value is valid and appears in hanging indentation. Tab alignment defaults to left, but may be specified by passing a member of the :ref:`WdTabAlignment` enumeration as `alignment`. An optional leader character can be specified by passing a member of the :ref:`WdTabLeader` enumeration as `leader`. """ tabs = self._pPr.get_or_add_tabs() tab = tabs.insert_tab_in_order(position, alignment, leader) return TabStop(tab)
[docs] def clear_all(self): """Remove all custom tab stops.""" self._pPr._remove_tabs() # pyright: ignore[reportPrivateUsage]
[docs] class TabStop(ElementProxy): """An individual tab stop applying to a paragraph or style. Accessed using list semantics on its containing |TabStops| object. """ def __init__(self, element: CT_TabStop): super(TabStop, self).__init__(element, None) self._tab = element @property def alignment(self) -> WD_TAB_ALIGNMENT: """A member of :ref:`WdTabAlignment` specifying the alignment setting for this tab stop. Read/write. """ return self._tab.val @alignment.setter def alignment(self, value: WD_TAB_ALIGNMENT): self._tab.val = value @property def leader(self) -> WD_TAB_LEADER | None: """A member of :ref:`WdTabLeader` specifying a repeating character used as a "leader", filling in the space spanned by this tab. Assigning |None| produces the same result as assigning `WD_TAB_LEADER.SPACES`. Read/write. """ return self._tab.leader @leader.setter def leader(self, value: WD_TAB_LEADER | None): self._tab.leader = value @property def position(self) -> Length: """A |Length| object representing the distance of this tab stop from the inside edge of the paragraph. May be positive or negative. Read/write. """ return self._tab.pos @position.setter def position(self, value: Length): tab = self._tab tabs = cast("CT_TabStops", tab.getparent()) self._tab = tabs.insert_tab_in_order(value, tab.val, tab.leader) tabs.remove(tab)