def swank_autodoc(self, sexp, _=None, line_width=None): """ (:emacs-rex (swank:autodoc '("ql:quickload" "" swank::%cursor-marker%) :print-right-margin 102) "COMMON-LISP-USER" :repl-thread 19) (:return (:ok ("(quickload ===> systems <=== &key (verbose quicklisp-client:*quickload-verbose*) silent\n (prompt quicklisp-client:*quickload-prompt*) explain &allow-other-keys)" t)) 19) """ try: # unquote if isinstance(sexp, Quoted): # For instance in emacs 27 sexp = sexp.value() else: sexp = sexp[1] # [Symbol('quote'), [ ... ]] scope, cursor = current_scope(sexp) log.debug("scope: %s, cursor: %s" % (scope, cursor)) assert cursor > 0 func = scope[0] scope = scope[:-1] # remove marker result = self.arglist(func, cursor, scope) if result: yield EuslispResult(result) else: yield EuslispResult([Symbol(":not-available"), True]) except Exception: log.error(traceback.format_exc()) yield EuslispResult([Symbol(":not-available"), True])
def swank_set_package(self, name): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) if not check_lock(lock, 0.5): log.error('Could not acquire lock: %s' % lock) yield [ Symbol(":write-string"), "; No responses from inferior process\n" ] yield EuslispResult(False, response_type='abort') return lock.acquire() try: cmd = '(slime::set-package "{0}")'.format(qstr(name)) res = self.euslisp.exec_internal(cmd, force_repl_socket=True) yield EuslispResult(res) except AbortEvaluation: # the abort signal sometimes comes earlier than the # evaluation result, for example when attaching a gdb # instance and passing a SIGINT. # Retry the evaluation in such cases log.info('AbortEvaluation received during swank_set_package.' + ' Retrying...') res = self.euslisp.exec_internal(cmd, force_repl_socket=True) yield EuslispResult(res) finally: if lock.locked(): lock.release()
def swank_load_file(self, filename): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) lock.acquire() yield [Symbol(":write-string"), "Loading file: %s ...\n" % filename] try: cmd = '(lisp:load "{0}")'.format(qstr(filename)) for r in self.euslisp.eval(cmd): if isinstance(r, list): yield r yield [Symbol(":write-string"), "Loaded.\n"] yield EuslispResult(True) lock.release() except AbortEvaluation as e: if lock.locked(): lock.release() log.info('Aborting evaluation...') # Force-print the message, which is # by default only displayed on the minibuffer if e.message: yield [ Symbol(":write-string"), "; Evaluation aborted on {}\n".format(e.message), Symbol(":repl-result") ] yield EuslispResult(None) except Exception: if lock.locked(): lock.release() raise
def swank_eval(self, sexp): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) lock.acquire() try: for val in self.euslisp.eval(sexp): if isinstance(val, str): # Colors are not allowed in :repl-result formatting yield [ Symbol(":write-string"), no_color(val), Symbol(":repl-result") ] yield [ Symbol(":write-string"), "\n", Symbol(":repl-result") ] else: yield val if self.euslisp.read_mode or self.euslisp.read_busy: log.debug("Aborting read mode...") self.euslisp.read_mode = False self.euslisp.read_busy = False yield [Symbol(":read-aborted"), 0, 1] for val in self.maybe_new_prompt(): yield val yield EuslispResult(None) lock.release() except AbortEvaluation as e: log.info('Aborting evaluation...') if self.euslisp.read_mode: log.debug("Aborting read mode...") self.euslisp.read_mode = False yield [Symbol(":read-aborted"), 0, 1] for val in self.maybe_new_prompt(): yield val if lock.locked(): lock.release() if e.message: yield EuslispResult(e.message, response_type='abort') else: yield EuslispResult(None) except Exception as e: log.error(traceback.format_exc()) if self.euslisp.read_mode or self.euslisp.read_busy: log.debug("Aborting read mode...") self.euslisp.read_mode = False self.euslisp.read_busy = False yield [Symbol(":read-aborted"), 0, 1] if lock.locked(): lock.release() raise e
def swank_invoke_nth_restart_for_emacs(self, level, num): # if everything goes well, it should be the self.debugger[level -1] deb = next(x for x in self.debugger if x.level == level) res_dict = deb.restarts_dict clear_stack = False def check_key(key): return key in res_dict and num == res_dict[key] def debug_return(db): msg = db.message.split(self.euslisp.delim)[0] msg = repr(msg.rsplit(' in ', 1)[0]) yield [Symbol(':debug-return'), 0, db.level, Symbol('nil')] yield [Symbol(':return'), {'abort': msg}, db.id] if check_key('QUIT'): clear_stack = True self.euslisp.reset() elif check_key('CONTINUE'): pass elif check_key('RESTART'): clear_stack = True self.restart_euslisp_process() else: log.error("Restart number %s not found!" % num) yield EuslispResult(None) return yield EuslispResult(None, response_type='abort') if clear_stack: for val in self.maybe_new_prompt(): yield val for db in reversed(self.debugger): for val in debug_return(db): yield val self.debugger = [] else: self.debugger.remove(deb) # Only test for new prompts if we are exitting the debugger if not self.debugger: for val in self.maybe_new_prompt(): yield val for val in debug_return(deb): yield val # Pop previous debugger, if any if self.debugger: yield self.debugger[-1].make_debug_response()
def swank_completions_for_keyword(self, start, sexp): if sexp: sexp = unquote(sexp) scope, _ = current_scope(sexp) if scope: scope = scope[:-1] # remove marker if scope[-1] in ['', u'']: # remove null string scope = scope[:-1] else: scope = None # Try to eval from repl_socket to cope with thread special symbols lock = self.euslisp.euslime_connection_lock force_repl = True # But use internal_socket when repl is not available if lock.locked(): log.warning('Euslisp process is busy! ' + 'Calculating completions on internal process instead') lock = self.euslisp.euslime_internal_connection_lock force_repl = False else: log.debug('Acquiring lock: %s' % lock) lock.acquire() cmd = '(slime::slime-find-keyword "{}" (lisp:quote {}) "{}")'.format( qstr(start), dumps_lisp(scope), qstr(self.package)) try: result = self.euslisp.exec_internal(cmd, force_repl_socket=force_repl) yield EuslispResult(result) finally: if force_repl and lock.locked(): lock.release()
def swank_connection_info(self): version = self.euslisp.exec_internal('(slime::implementation-version)') name = self.euslisp.exec_internal( '(lisp:pathname-name lisp:*program-name*)') res = { 'pid': os.getpid(), 'style': False, 'encoding': { 'coding-systems': ['utf-8-unix', 'iso-latin-1-unix'], }, 'lisp-implementation': { 'type': name, 'name': name, 'version': version, 'program': False, }, 'machine': { 'type': platform.machine().upper(), 'version': platform.machine().upper(), }, 'package': { 'name': 'USER', 'prompt': name, }, 'version': "2.20", # swank version } yield EuslispResult(res)
def swank_apropos_list_for_emacs(self, key, external_only=None, case_sensitive=None, package=None): # ignore 'external_only' and 'case_sensitive' arguments package = package[-1] # unquote cmd = '(slime::slime-apropos-list "{0}" {1})'.format( qstr(key), dumps_lisp(package)) yield EuslispResult(self.euslisp.exec_internal(cmd))
def swank_connection_info(self): # Wait for euslisp connection self.euslisp.recv_socket_data() log.info("Successfully started Euslisp process!") version = self.euslisp.exec_internal('(slime::implementation-version)') name = self.euslisp.exec_internal('(pathname-name *program-name*)') res = { 'pid': os.getpid(), 'style': False, 'encoding': { 'coding-systems': ['utf-8-unix', 'iso-latin-1-unix'], }, 'lisp-implementation': { 'type': name, 'name': name, 'version': version, 'program': False, }, 'machine': { 'type': platform.machine().upper(), 'version': platform.machine().upper(), }, 'package': { 'name': 'USER', 'prompt': name, }, 'version': "2.20", # swank version } yield EuslispResult(res)
def swank_compile_file_if_needed(self, filename, loadp): # FIXME: This returns without checking/compiling the file errors = [] seconds = 0.01 yield EuslispResult([ Symbol(":compilation-result"), errors, True, seconds, loadp, filename ])
def swank_compile_string_for_emacs(self, cmd_str, *args): # (sexp buffer-name (:position 1) (:line 1) () ()) # FIXME: This does not compile actually, just eval instead. # Although compiling it would have effect on the Call Stack cmd_str = "(lisp:progn " + cmd_str + ")" messages = [] sexp = loads(cmd_str, nil=None) for exp in sexp[1:]: if len(exp) > 2: messages.append(dumps(exp[:2] + [None], none_as='...')) else: messages.append(dumps(exp)) lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) lock.acquire() try: for res in self.euslisp.eval(cmd_str): if isinstance(res, list): yield res for msg in messages: yield [Symbol(":write-string"), "; Loaded {}\n".format(msg)] errors = [] seconds = 0.01 yield EuslispResult([ Symbol(":compilation-result"), errors, True, seconds, None, None ]) lock.release() except AbortEvaluation as e: if lock.locked(): lock.release() log.info('Aborting evaluation...') # Force-print the message, which is # by default only displayed on the minibuffer if e.message: yield [ Symbol(":write-string"), "; Evaluation aborted on {}\n".format(e.message), Symbol(":repl-result") ] yield EuslispResult(None) except Exception: if lock.locked(): lock.release() raise
def swank_fuzzy_completions(self, start, pkg, *args): # Unsupported # Return a list of simple_completions in the fuzzy format gen = self.swank_simple_completions(start, pkg) simple_completions = gen.next().value if simple_completions: first_comp = simple_completions[0] simple_completions = [[x, 0, None, None] for x in first_comp] yield EuslispResult([simple_completions, None])
def swank_repl_clear_repl_variables(self): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) if lock.locked(): log.error('Could not acquire lock: %s' % lock) yield EuslispResult("'Process busy'", response_type='abort') return lock.acquire() try: cmd = '(slime::clear-repl-variables)' res = self.euslisp.exec_internal(cmd, force_repl_socket=True) yield EuslispResult(res) lock.release() finally: if lock.locked(): lock.release()
def swank_create_repl(self, sexp): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) lock.acquire() cmd = '(slime::slime-prompt)' try: res = self.euslisp.exec_internal(cmd, force_repl_socket=True) self.euslisp.accumulate_output = False yield EuslispResult(res) finally: if lock.locked(): lock.release()
def swank_load_file(self, filename): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) lock.acquire() yield [Symbol(":write-string"), "Loading file: %s ...\n" % filename] try: cmd = '(slime::load-file-and-tags "{0}")'.format(qstr(filename)) output_str = '' for r in self.euslisp.eval(cmd): if isinstance(r, list): # read-string yield r if isinstance(r, str): output_str += r res = loads(output_str, nil=None) if res == Symbol("lisp:nil") or res == Symbol("nil"): res = None yield [Symbol(":write-string"), "Loaded.\n"] yield EuslispResult(res) lock.release() except AbortEvaluation as e: if lock.locked(): lock.release() log.info('Aborting evaluation...') # Force-print the message, which is # by default only displayed on the minibuffer if e.message: yield [ Symbol(":write-string"), "; Evaluation aborted on {}\n".format(e.message), Symbol(":repl-result") ] yield EuslispResult(None) except Exception: if lock.locked(): lock.release() raise
def swank_repl_clear_repl_variables(self): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) lock.acquire() try: cmd = '(slime::clear-repl-variables)' res = self.euslisp.exec_internal(cmd, force_repl_socket=True) yield EuslispResult(res) lock.release() except Exception: if lock.locked(): lock.release() raise
def swank_set_package(self, name): lock = self.euslisp.euslime_connection_lock log.debug('Acquiring lock: %s' % lock) lock.acquire() try: cmd = '(slime::set-package "{0}")'.format(qstr(name)) res = self.euslisp.exec_internal(cmd, force_repl_socket=True) yield EuslispResult(res) lock.release() except Exception: if lock.locked(): lock.release() raise
def swank_completions_for_keyword(self, start, sexp): if sexp: sexp = sexp[1] # unquote scope, _ = current_scope(sexp) if scope: scope = scope[:-1] # remove marker if scope[-1] in ['', u'']: # remove null string scope = scope[:-1] else: scope = None cmd = '(slime::slime-find-keyword "{0}" (lisp:quote {1}))'.format( qstr(start), dumps_lisp(scope)) yield EuslispResult(self.euslisp.exec_internal(cmd))
def swank_autodoc(self, sexp, _=None, line_width=None): """ (:emacs-rex (swank:autodoc '("ql:quickload" "" swank::%cursor-marker%) :print-right-margin 102) "COMMON-LISP-USER" :repl-thread 19) (:return (:ok ("(quickload ===> systems <=== &key (verbose quicklisp-client:*quickload-verbose*) silent\n (prompt quicklisp-client:*quickload-prompt*) explain &allow-other-keys)" t)) 19) from swank-arglists.lisp: Return a list of two elements. First, a string representing the arglist for the deepest subform in RAW-FORM that does have an arglist. Second, a boolean value telling whether the returned string can be cached. """ try: sexp = unquote(sexp) scope, cursor = current_scope(sexp) log.debug("scope: %s, cursor: %s" % (scope, cursor)) assert cursor > 0 func = scope[0] scope = scope[:-1] # remove marker result = self.arglist(func, cursor, scope) if result: yield EuslispResult(result) else: yield EuslispResult([Symbol(":not-available"), True]) except Exception: log.error(traceback.format_exc()) yield EuslispResult([Symbol(":not-available"), True])
def swank_completions_for_keyword(self, start, sexp): if sexp: sexp = unquote(sexp) scope, _ = current_scope(sexp) if scope: scope = scope[:-1] # remove marker if scope[-1] in ['', u'']: # remove null string scope = scope[:-1] else: scope = None cmd = '(slime::slime-find-keyword "{}" (lisp:quote {}) "{}")'.format( qstr(start), dumps_lisp(scope), qstr(self.package)) # Eval from repl_socket to cope with thread special symbols result = self.euslisp.exec_internal(cmd, force_repl_socket=True) yield EuslispResult(result)
def swank_compile_string_for_emacs(self, cmd_str, *args): # (sexp buffer-name (:position 1) (:line 1) () ()) # FIXME: This does not compile actually, just eval instead. try: sexp = loads(cmd_str, nil=None) assert isinstance(sexp, list) except AssertionError: raise Exception('Invalid s-expression in %s' % cmd_str) self.euslisp.exec_internal(cmd_str) if len(sexp) > 2: msg = dumps(sexp[:2] + [None], none_as='...') else: msg = cmd_str yield [Symbol(":write-string"), "; Loaded {}".format(msg)] errors = [] seconds = 0.01 yield EuslispResult( [Symbol(":compilation-result"), errors, True, seconds, None, None])
def swank_compile_string_for_emacs(self, cmd_str, *args): # (sexp buffer-name (:position 1) (:line 1) () ()) # FIXME: This does not compile actually, just eval instead. # Although compiling it would have effect on the Call Stack cmd_str = "(lisp:progn " + cmd_str + ")" messages = [] sexp = loads(cmd_str, nil=None) for exp in sexp[1:]: if len(exp) > 2: messages.append(dumps(exp[:2] + [None], none_as='...')) else: messages.append(dumps(exp)) list(self.euslisp.eval(cmd_str)) for msg in messages: yield [Symbol(":write-string"), "; Loaded {}\n".format(msg)] errors = [] seconds = 0.01 yield EuslispResult([Symbol(":compilation-result"), errors, True, seconds, None, None])
def swank_set_default_directory(self, dir): cmd = '(lisp:progn (lisp:cd "{0}") (lisp:pwd))'.format(qstr(dir)) yield EuslispResult(self.euslisp.exec_internal(cmd))
def swank_set_package(self, name): cmd = '(slime::set-package "{0}")'.format(qstr(name)) yield EuslispResult(self.euslisp.exec_internal(cmd))
def swank_default_directory(self): res = self.euslisp.exec_internal('(lisp:pwd)') yield EuslispResult(res)
def swank_backtrace(self, start, end): res = self.euslisp.get_callstack(end) yield EuslispResult(res[start:])
def swank_list_all_package_names(self, nicknames=None): cmd = '(slime::slime-all-packages {0})'.format( dumps_lisp(nicknames)) yield EuslispResult(self.euslisp.exec_internal(cmd))
def swank_swank_expand_1(self, form): cmd = '(slime::slime-macroexpand (lisp:quote {0}))'.format(form) yield EuslispResult(self.euslisp.exec_internal(cmd))
def swank_describe_symbol(self, sym): cmd = '(slime::slime-describe-symbol "{0}")'.format( qstr(sym.strip())) yield EuslispResult(self.euslisp.exec_internal(cmd))
def swank_load_file(self, filename): yield [Symbol(":write-string"), "Loading file: %s ...\n" % filename] res = self.euslisp.exec_internal('(lisp:load "{0}")'.format( qstr(filename))) yield [Symbol(":write-string"), "Loaded.\n"] yield EuslispResult(res)