# -*- coding: utf-8 -*- priority -50 ########################################################################### # General Stuff # ########################################################################### global !p import vim from os import path as ospath from string import Template import re from collections import Counter from vimsnippets import complete #http://docutils.sourceforge.net/docs/ref/rst/roles.html TEXT_ROLES = ['emphasis','literal','code','math', 'pep-reference','rfc-reference', 'strong','subscript','superscript', 'title-reference','raw'] TEXT_ROLES_REGEX = r'\.\.\srole::?\s(w+)' #http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions SPECIFIC_ADMONITIONS = ["attention", "caution", "danger", "error", "hint", "important", "note", "tip", "warning"] #http://docutils.sourceforge.net/docs/ref/rst/directives.html DIRECTIVES = ['topic','sidebar','math','epigraph', 'parsed-literal','code','highlights', 'pull-quote','compound','container','table','csv-table', 'list-table','class','sectnum', 'role','default-role','unicode', 'raw'] NONE_CONTENT_DIRECTIVES = ['rubric', 'contents', 'header', 'footer', 'date', 'include', 'title'] INCLUDABLE_DIRECTIVES = ['image', 'figure', 'include'] # CJK chars # http://stackoverflow.com/questions/2718196/find-all-chinese-text-in-a-string-using-python-and-regex CJK_RE = re.compile(u'[⺀-⺙⺛-⻳⼀-⿕々〇〡-〩〸-〺〻㐀-䶵一-鿃豈-鶴侮-頻並-龎]', re.UNICODE) def has_cjk(s): """Detect if s contains CJK characters.""" return CJK_RE.search(s) is not None def real_filename(filename): """pealeextension name off if possible # i.e. "foo.bar.png will return "foo.bar" """ return ospath.splitext(filename)[0] def check_file_exist(rst_path, relative_path): """ For RST file, it can just include files as relative path. :param rst_path: absolute path to rst file :param relative_path: path related to rst file :return: relative file's absolute path if file exist """ abs_path = ospath.join(ospath.dirname(rst_path), relative_path) if ospath.isfile(abs_path): return abs_path try: rst_char_len = vim.strwidth # Requires Vim 7.3+ except AttributeError: from unicodedata import east_asian_width def rst_char_len(s): """Return the required over-/underline length for s.""" result = 0 for c in s: result += 2 if east_asian_width(c) in ('W', 'F') else 1 return result def make_items(times, leading='+'): """ make lines with leading char multitimes :param: times, how many times you need :param: leading, leading character """ times = int(times) if leading == 1: msg = "" for x in range(1, times+1): msg += "%s. Item\n" % x return msg else: return ("%s Item\n" % leading) * times def look_up_directives(regex, fpath): """ find all directive args in given file :param: regex, the regex that needs to match :param: path, to path to rst file :return: list, empty list if nothing match """ try: with open(fpath) as source: match = re.findall(regex, source.read()) except IOError: match = [] return match def get_popular_code_type(): """ find most popular code type in the given rst :param path: file to detect :return: string, most popular code type in file """ buf = "".join(vim.current.buffer) types = re.findall(r'[:|\.\.\s]code::?\s(\w+)', buf) try: popular_type = Counter(types).most_common()[0][0] except IndexError: popular_type = "lua" # Don't break default return popular_type endglobal snippet part "Part" b `!p snip.rv = rst_char_len(t[1])*'#'` ${1:${VISUAL:Part name}} `!p snip.rv = rst_char_len(t[1])*'#'` $0 endsnippet snippet chap "Chapter" b `!p snip.rv = rst_char_len(t[1])*'*'` ${1:${VISUAL:Chapter name}} `!p snip.rv = rst_char_len(t[1])*'*'` $0 endsnippet snippet sec "Section" b ${1:${VISUAL:Section name}} `!p snip.rv = rst_char_len(t[1])*'='` $0 endsnippet snippet ssec "Subsection" b ${1:${VISUAL:Subsection name}} `!p snip.rv = rst_char_len(t[1])*'-'` $0 endsnippet snippet sssec "Subsubsection" b ${1:${VISUAL:Subsubsection name}} `!p snip.rv = rst_char_len(t[1])*'^'` $0 endsnippet snippet para "Paragraph" b ${1:${VISUAL:Paragraph name}} `!p snip.rv = rst_char_len(t[1])*'"'` $0 endsnippet snippet em "Emphasize string" i `!p # dirty but works with CJK character detection if has_cjk(vim.current.line): snip.rv ="\ "`*${1:${VISUAL:Em}}*`!p if has_cjk(vim.current.line): snip.rv ="\ " else: snip.rv = " " `$0 endsnippet snippet st "Strong string" i `!p if has_cjk(vim.current.line): snip.rv ="\ "`**${1:${VISUAL:Strong}}**`!p if has_cjk(vim.current.line): snip.rv ="\ " else: snip.rv = " " `$0 endsnippet snippet "li(st)? (?P\d+)" "List" br $0 `!p # usage: li 4 # which will extand into a unordered list contains 4 items snip.rv = make_items(match.groupdict()['num']) ` endsnippet snippet "ol(st)? (?P\d+)" "Order List" br $0 `!p # usage: ol 4 # which will extand into a ordered list contains 4 items snip.rv = make_items(match.groupdict()['num'], 1) ` endsnippet ########################################################################### # More Specialized Stuff. # ########################################################################### snippet cb "Code Block" b .. code-block:: ${1:`!p snip.rv = get_popular_code_type()`} ${2:${VISUAL:code}} $0 endsnippet # match snippets : # img, inc, fig snippet id "Includable Directives" b `!p real_name=real_filename(ospath.basename(t[2])) di=t[1][:2] link="" content="" if di == 'im': link = "|{0}|".format(real_name) if di == 'fi': content=""" :alt: {0} {0}""".format(real_name) ` ..`!p snip.rv = " %s" % link if link else ""` $1`!p snip.rv=complete(t[1], INCLUDABLE_DIRECTIVES) `:: ${2:${VISUAL:file}}`!p if content: snip.rv +=" "+content` `!p # Tip of whether file is exist in comment type if not check_file_exist(path, t[2]): snip.rv='.. FILE {0} does not exist'.format(t[2]) else: snip.rv="" `$0 endsnippet snippet di "Directives" b .. $1`!p snip.rv=complete(t[1], DIRECTIVES)`:: $2 ${3:${VISUAL:Content}} $0 endsnippet snippet nd "None Content Directives" b .. $1`!p snip.rv=complete(t[1], NONE_CONTENT_DIRECTIVES)`:: $2 $0 endsnippet snippet sa "Specific Admonitions" b .. $1`!p snip.rv =complete(t[1], SPECIFIC_ADMONITIONS)`:: ${2:${VISUAL:Content}} $0 endsnippet #it will be trigger at start of line or after a word snippet ro "Text Roles" w \ :$1`!p snip.rv=complete(t[1], TEXT_ROLES+look_up_directives(TEXT_ROLES_REGEX, path))`:\`$2\`\ endsnippet snippet eu "Embedded URI" i `!p if has_cjk(vim.current.line): snip.rv = "\ "`\`${1:${VISUAL:Text}} <${2:URI}>\`_`!p if has_cjk(vim.current.line): snip.rv ="\ " else: snip.rv = "" `$0 endsnippet snippet fnt "Footnote or Citation" i [${1:Label}]_ $0 .. [$1] ${2:Reference} endsnippet ############ # Sphinx # ############ snippet sid "SideBar" b .. sidebar:: ${1:SideBar Title} ${2:${VISUAL:SideBar Content}} endsnippet # vim:ft=snippets: