Show More
@@ -61,11 +61,13 b' import keyword' | |||
|
61 | 61 | import os |
|
62 | 62 | import re |
|
63 | 63 | import sys |
|
64 | import unicodedata | |
|
65 | import string | |
|
64 | 66 | |
|
65 | from IPython.config.configurable import Configurable | |
|
67 | from IPython.config.configurable import Configurable | |
|
66 | 68 | from IPython.core.error import TryNext |
|
67 | 69 | from IPython.core.inputsplitter import ESC_MAGIC |
|
68 | from IPython.core.latex_symbols import latex_symbols | |
|
70 | from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol | |
|
69 | 71 | from IPython.utils import generics |
|
70 | 72 | from IPython.utils import io |
|
71 | 73 | from IPython.utils.decorators import undoc |
@@ -955,6 +957,88 b' class IPCompleter(Completer):' | |||
|
955 | 957 | |
|
956 | 958 | return [leading + k + suf for k in matches] |
|
957 | 959 | |
|
960 | def unicode_name_matches(self, text): | |
|
961 | u"""Match Latex-like syntax for unicode characters base | |
|
962 | on the name of the character. | |
|
963 | ||
|
964 | This does \\GREEK SMALL LETTER ETA -> η | |
|
965 | ||
|
966 | Works only on valid python 3 identifier, or on combining characters that | |
|
967 | will combine to form a valid identifier. | |
|
968 | ||
|
969 | Used on Python 3 only. | |
|
970 | """ | |
|
971 | slashpos = text.rfind('\\') | |
|
972 | if slashpos > -1: | |
|
973 | s = text[slashpos+1:] | |
|
974 | try : | |
|
975 | unic = unicodedata.lookup(s) | |
|
976 | # allow combining chars | |
|
977 | if ('a'+unic).isidentifier(): | |
|
978 | return '\\'+s,[unic] | |
|
979 | except KeyError as e: | |
|
980 | pass | |
|
981 | return u'', [] | |
|
982 | ||
|
983 | def back_unicode_name_matches(self, text): | |
|
984 | u"""Match unicode characters back to unicode name | |
|
985 | ||
|
986 | This does ☃ -> \\snowman | |
|
987 | ||
|
988 | Note that snowman is not a valid python3 combining character but will be expanded. | |
|
989 | Though it will not recombine back to the snowman character by the completion machinery. | |
|
990 | ||
|
991 | This will not either back-complete standard sequences like \n, \b ... | |
|
992 | ||
|
993 | Used on Python 3 only. | |
|
994 | """ | |
|
995 | if len(text)<2: | |
|
996 | return u'', () | |
|
997 | maybe_slash = text[-2] | |
|
998 | if maybe_slash != '\\': | |
|
999 | return u'', () | |
|
1000 | ||
|
1001 | char = text[-1] | |
|
1002 | # no expand on quote for completion in strings. | |
|
1003 | # nor backcomplete standard ascii keys | |
|
1004 | if char in string.ascii_letters or char in ['"',"'"]: | |
|
1005 | return u'', () | |
|
1006 | try : | |
|
1007 | unic = unicodedata.name(char) | |
|
1008 | return '\\'+char,['\\'+unic] | |
|
1009 | except KeyError as e: | |
|
1010 | pass | |
|
1011 | return u'', () | |
|
1012 | ||
|
1013 | def back_latex_name_matches(self, text): | |
|
1014 | u"""Match latex characters back to unicode name | |
|
1015 | ||
|
1016 | This does ->\\sqrt | |
|
1017 | ||
|
1018 | Used on Python 3 only. | |
|
1019 | """ | |
|
1020 | if len(text)<2: | |
|
1021 | return u'', () | |
|
1022 | maybe_slash = text[-2] | |
|
1023 | if maybe_slash != '\\': | |
|
1024 | return u'', () | |
|
1025 | ||
|
1026 | ||
|
1027 | char = text[-1] | |
|
1028 | # no expand on quote for completion in strings. | |
|
1029 | # nor backcomplete standard ascii keys | |
|
1030 | if char in string.ascii_letters or char in ['"',"'"]: | |
|
1031 | return u'', () | |
|
1032 | try : | |
|
1033 | latex = reverse_latex_symbol[char] | |
|
1034 | # '\\' replace the \ as well | |
|
1035 | return '\\'+char,[latex] | |
|
1036 | except KeyError as e: | |
|
1037 | pass | |
|
1038 | return u'', () | |
|
1039 | ||
|
1040 | ||
|
1041 | ||
|
958 | 1042 | def latex_matches(self, text): |
|
959 | 1043 | u"""Match Latex syntax for unicode characters. |
|
960 | 1044 | |
@@ -1057,11 +1141,21 b' class IPCompleter(Completer):' | |||
|
1057 | 1141 | cursor_pos = len(line_buffer) if text is None else len(text) |
|
1058 | 1142 | |
|
1059 | 1143 | if PY3: |
|
1060 | latex_text = text if not line_buffer else line_buffer[:cursor_pos] | |
|
1061 | latex_text, latex_matches = self.latex_matches(latex_text) | |
|
1062 | if latex_matches: | |
|
1063 | return latex_text, latex_matches | |
|
1064 | 1144 | |
|
1145 | base_text = text if not line_buffer else line_buffer[:cursor_pos] | |
|
1146 | latex_text, latex_matches = self.latex_matches(base_text) | |
|
1147 | if latex_matches: | |
|
1148 | return latex_text, latex_matches | |
|
1149 | name_text = '' | |
|
1150 | name_matches = [] | |
|
1151 | for meth in (self.unicode_name_matches, self.back_unicode_name_matches, self.back_latex_name_matches): | |
|
1152 | _name_text, _name_matches = meth(base_text) | |
|
1153 | if _name_text: | |
|
1154 | name_text = _name_text | |
|
1155 | name_matches.extend(_name_matches) | |
|
1156 | if name_text: | |
|
1157 | return name_text, name_matches | |
|
1158 | ||
|
1065 | 1159 | # if text is either None or an empty string, rely on the line buffer |
|
1066 | 1160 | if not text: |
|
1067 | 1161 | text = self.splitter.split_line(line_buffer, cursor_pos) |
@@ -1170,3 +1264,4 b' class IPCompleter(Completer):' | |||
|
1170 | 1264 | return self.matches[state] |
|
1171 | 1265 | except IndexError: |
|
1172 | 1266 | return None |
|
1267 |
@@ -1295,3 +1295,6 b' latex_symbols = {' | |||
|
1295 | 1295 | "\\mtteight" : "𝟾", |
|
1296 | 1296 | "\\mttnine" : "𝟿", |
|
1297 | 1297 | } |
|
1298 | ||
|
1299 | ||
|
1300 | reverse_latex_symbol = { v:k for k,v in latex_symbols.items()} |
@@ -76,6 +76,11 b' for line in valid_idents:' | |||
|
76 | 76 | s += ' "%s" : "%s",\n' % (line[0], line[1]) |
|
77 | 77 | s += "}\n" |
|
78 | 78 | |
|
79 | s += """ | |
|
80 | ||
|
81 | reverse_latex_symbol = { v:k for k,v in latex_symbols.items()} | |
|
82 | """ | |
|
83 | ||
|
79 | 84 | fn = os.path.join('..','IPython','core','latex_symbols.py') |
|
80 | 85 | print("Writing the file: %s" % fn) |
|
81 | 86 | with open(fn, 'w', encoding='utf-8') as f: |
General Comments 0
You need to be logged in to leave comments.
Login now