aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorb-hodges <[email protected]>2018-01-24 15:36:08 -0600
committerRapptz <[email protected]>2018-03-06 01:11:36 -0500
commitea061ef9b2ba64524b91af6036a615352ff9ce1a (patch)
treed8e85d453009e825243afe5a39216e6a97f178bb
parent[commands] Add ability to have case insensitive commands. (diff)
downloaddiscord.py-ea061ef9b2ba64524b91af6036a615352ff9ce1a.tar.xz
discord.py-ea061ef9b2ba64524b91af6036a615352ff9ce1a.zip
[commands] Added handling for unicode quotes
-rw-r--r--discord/ext/commands/view.py57
1 files changed, 43 insertions, 14 deletions
diff --git a/discord/ext/commands/view.py b/discord/ext/commands/view.py
index acde0b75..65f96e18 100644
--- a/discord/ext/commands/view.py
+++ b/discord/ext/commands/view.py
@@ -108,13 +108,42 @@ class StringView:
# Parser
+# map from opening quotes to closing quotes
+_quotes = {
+ '"': '"',
+ "'": "'",
+ "«": "»",
+ "‘": "’",
+ "‚": "‛",
+ "“": "”",
+ "„": "‟",
+ "‹": "›",
+ "⹂": "⹂",
+ "「": "」",
+ "『": "』",
+ "〝": "〞",
+ "﹁": "﹂",
+ "﹃": "﹄",
+ """: """,
+ "'": "'",
+ "「": "」",
+ "«": "»",
+ "‹": "›",
+ "《": "》",
+ "〈": "〉",
+}
+_all_quotes = set(_quotes.keys()) | set(_quotes.values())
+
def quoted_word(view):
current = view.current
if current is None:
return None
- is_quoted = current == '"'
+ close_quote = _quotes.get(current)
+ is_quoted = bool(close_quote)
+ if is_quoted:
+ open_quote = current
result = [] if is_quoted else [current]
while not view.eof:
@@ -122,7 +151,7 @@ def quoted_word(view):
if not current:
if is_quoted:
# unexpected EOF
- raise BadArgument('Expected closing "')
+ raise BadArgument('Expected closing {}.'.format(close_quote))
return ''.join(result)
# currently we accept strings in the format of "hello world"
@@ -133,32 +162,32 @@ def quoted_word(view):
# string ends with \ and no character after it
if is_quoted:
# if we're quoted then we're expecting a closing quote
- raise BadArgument('Expected closing "')
+ raise BadArgument('Expected closing {}.'.format(close_quote))
# if we aren't then we just let it through
return ''.join(result)
- if next_char == '"':
+ if next_char in ((open_quote, close_quote) if is_quoted else _all_quotes):
# escaped quote
- result.append('"')
+ result.append(next_char)
else:
# different escape character, ignore it
view.undo()
result.append(current)
continue
+ if not is_quoted and current in _all_quotes:
+ # we aren't quoted
+ raise BadArgument('Unexpected quote mark in non-quoted string')
+
# closing quote
- if current == '"':
+ if is_quoted and current == close_quote:
next_char = view.get()
valid_eof = not next_char or next_char.isspace()
- if is_quoted:
- if not valid_eof:
- raise BadArgument('Expected space after closing quotation')
+ if not valid_eof:
+ raise BadArgument('Expected space after closing quotation')
- # we're quoted so it's okay
- return ''.join(result)
- else:
- # we aren't quoted
- raise BadArgument('Unexpected quote mark in non-quoted string')
+ # we're quoted so it's okay
+ return ''.join(result)
if current.isspace() and not is_quoted:
# end of word found