Files
2026-08-03 18:42:47 +08:00

185 lines
6.3 KiB
Python

#A* -------------------------------------------------------------------
#B* This file contains source code for the PyMOL computer program
#C* Copyright (c) Schrodinger, LLC.
#D* -------------------------------------------------------------------
#E* It is unlawful to modify or remove this copyright notice.
#F* -------------------------------------------------------------------
#G* Please see the accompanying LICENSE file for further information.
#H* -------------------------------------------------------------------
#I* Additional authors of this source file include:
#-*
#-*
#-*
#Z* -------------------------------------------------------------------
if __name__=='pymol.shortcut':
from . import parsing
from .checking import is_string, is_list
if True:
def mkabbr(a, m=1):
b = a.split('_')
b[:-1] = [c[0:m] for c in b[:-1]]
return '_'.join(b)
class Shortcut:
def __call__(self):
return self
def __init__(self, keywords=(), filter_leading_underscore=1):
self.filter_leading_underscore = filter_leading_underscore
if filter_leading_underscore:
self.keywords = [x for x in keywords if x[:1]!='_']
else:
self.keywords = list(keywords)
self.shortcut = {}
self.abbr_dict = {}
self.rebuild()
def add_one(self,a):
# optimize symbols
hash = self.shortcut
abbr_dict = self.abbr_dict
for b in range(1,len(a)):
sub = a[0:b]
hash[sub] = 0 if sub in hash else a
if '_' in a:
for n in (1, 2):
abbr = mkabbr(a, n)
if a!=abbr:
if abbr in abbr_dict:
if a not in abbr_dict[abbr]:
abbr_dict[abbr].append(a)
else:
abbr_dict[abbr]=[a]
for b in range(abbr.find('_')+1,len(abbr)):
sub = abbr[0:b]
hash[sub] = 0 if sub in hash else a
def rebuild(self, keywords=None):
if keywords is not None:
if self.filter_leading_underscore:
self.keywords = [x for x in keywords if x[:1]!='_']
else:
self.keywords = list(keywords)
# optimize symbols
self.shortcut = {}
hash = self.shortcut
self.abbr_dict = {}
abbr_dict = self.abbr_dict
#
for a in self.keywords:
for b in range(1,len(a)):
sub = a[0:b]
hash[sub] = 0 if sub in hash else a
if '_' in a:
for n in (1, 2):
abbr = mkabbr(a, n)
if a!=abbr:
if abbr in abbr_dict:
abbr_dict[abbr].append(a)
else:
abbr_dict[abbr]=[a]
for b in range(abbr.find('_')+1,len(abbr)):
sub = abbr[0:b]
hash[sub] = 0 if sub in hash else a
self._rebuild_finalize()
def _rebuild_finalize(self):
hash = self.shortcut
for a, adk in self.abbr_dict.items():
if len(adk)==1:
hash[a]=adk[0]
for a in self.keywords:
hash[a]=a
def interpret(self,kee, mode=0):
'''
Returns None (no hit), str (one hit) or list (multiple hits)
kee = str: query string, setting prefix or shortcut
mode = 0/1: if mode=1, do prefix search even if kee has exact match
'''
if not len(kee): # empty string matches everything
return list(self.keywords)
try:
r = self.shortcut[kee]
except KeyError:
return None
if r and not mode:
return r
# prefix search
lst_set = set(a for a in self.keywords if a.startswith(kee))
for abbr, a_list in self.abbr_dict.items():
if abbr.startswith(kee):
lst_set.update(a_list)
# no match
if not lst_set:
return None
# single match: str
lst = list(lst_set)
if len(lst) == 1:
return lst[0]
# multiple matches: list
return lst
def has_key(self,kee):
return kee in self.shortcut
__contains__ = has_key
def __getitem__(self,kee):
return self.shortcut.get(kee, None)
def __delitem__(self,kee):
self.keywords.remove(kee)
self.rebuild()
def append(self,kee):
self.keywords.append(kee)
self.add_one(kee)
self._rebuild_finalize()
def auto_err(self,kee,descrip=None):
result = None
if kee not in self.shortcut:
if descrip is not None:
msg = "Error: unknown %s: '%s'." % (descrip, kee)
lst = self.interpret('')
if is_list(lst):
if len(lst)<100:
lst.sort()
lst = parsing.list_to_str_list(lst)
msg += " Choices:\n"
msg += "\n".join(lst)
raise parsing.QuietException(msg)
else:
result = self.interpret(kee)
if not is_string(result):
if descrip is not None:
lst = parsing.list_to_str_list(result)
msg = "Error: ambiguous %s:\n%s" % (descrip, '\n'.join(lst))
raise parsing.QuietException(msg)
return result
if __name__=='__main__':
sc = Shortcut(['warren','wasteland','electric','well'])
tv = sc.has_key('a')
print(tv==0,tv)
tv = sc.has_key('w')
print(tv==1,tv)
tv = sc.has_key('war')
print(tv==1,tv)
tv = sc.interpret('w')
print(sorted(tv)==['warren', 'wasteland', 'well'],tv)
tv = sc.interpret('e')
print(isinstance(tv, str), tv)