summaryrefslogtreecommitdiff
path: root/sphinx/roles.py
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2018-04-28 11:39:13 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2018-04-28 12:56:01 +0900
commit622119a9d4e1294ce9718e490983edf58b50e6ac (patch)
tree6ce01e6f920033950142de62eb6b1ebdb507177e /sphinx/roles.py
parent93837bb01ecb185d8ee64b1f794f010c510b32e1 (diff)
downloadsphinx-git-622119a9d4e1294ce9718e490983edf58b50e6ac.tar.gz
Fix #789: ``:samp:`` role supports to escape curly braces with backslash
Diffstat (limited to 'sphinx/roles.py')
-rw-r--r--sphinx/roles.py47
1 files changed, 37 insertions, 10 deletions
diff --git a/sphinx/roles.py b/sphinx/roles.py
index 2971c8fc3..453eb5aa0 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -284,6 +284,7 @@ def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
_litvar_re = re.compile('{([^}]+)}')
+parens_re = re.compile(r'(\\*{|\\*})')
def emph_literal_role(typ, rawtext, text, lineno, inliner,
@@ -296,17 +297,43 @@ def emph_literal_role(typ, rawtext, text, lineno, inliner,
else:
typ = typ.lower()
- text = utils.unescape(text)
- pos = 0
retnode = nodes.literal(role=typ.lower(), classes=[typ])
- for m in _litvar_re.finditer(text): # type: ignore
- if m.start() > pos:
- txt = text[pos:m.start()]
- retnode += nodes.Text(txt, txt)
- retnode += nodes.emphasis(m.group(1), m.group(1))
- pos = m.end()
- if pos < len(text):
- retnode += nodes.Text(text[pos:], text[pos:])
+ parts = list(parens_re.split(utils.unescape(text)))
+ stack = ['']
+ for part in parts:
+ matched = parens_re.match(part)
+ if matched:
+ backslashes = len(part) - 1
+ if backslashes % 2 == 1: # escaped
+ stack[-1] += "\\" * int((backslashes - 1) / 2) + part[-1]
+ elif part[-1] == '{': # rparen
+ stack[-1] += "\\" * int(backslashes / 2)
+ if len(stack) >= 2 and stack[-2] == "{":
+ # nested
+ stack[-1] += "{"
+ else:
+ # start emphasis
+ stack.append('{')
+ stack.append('')
+ else: # lparen
+ stack[-1] += "\\" * int(backslashes / 2)
+ if len(stack) == 3 and stack[1] == "{" and len(stack[2]) > 0:
+ # emphasized word found
+ if stack[0]:
+ retnode += nodes.Text(stack[0], stack[0])
+ retnode += nodes.emphasis(stack[2], stack[2])
+ stack = ['']
+ else:
+ # emphasized word not found; the rparen is not a special symbol
+ stack.append('}')
+ stack = [''.join(stack)]
+ else:
+ stack[-1] += part
+ if ''.join(stack):
+ # remaining is treated as Text
+ text = ''.join(stack)
+ retnode += nodes.Text(text, text)
+
return [retnode], []