Ejemplo n.º 1
0
 def restart_euslisp_process(self):
     program = self.euslisp.program
     init_file = self.euslisp.init_file
     color = self.euslisp.color
     self.euslisp.stop()
     self.euslisp = EuslispProcess(program, init_file, color=color)
     self.euslisp.start()
Ejemplo n.º 2
0
 def __init__(self, *args, **kwargs):
     self.euslisp = EuslispProcess(*args, **kwargs)
     self.close_request = Event()
     self.euslisp.start()
     self.command_id = None
     self.package = None
     self.debugger = []
Ejemplo n.º 3
0
 def restart_euslisp_process(self):
     program = self.euslisp.program
     init_file = self.euslisp.init_file
     on_output = self.euslisp.on_output
     color = self.euslisp.color
     self.euslisp.stop()
     self.euslisp = EuslispProcess(program,
                                   init_file,
                                   on_output=on_output,
                                   color=color)
     self.euslisp.start()
     # get rid of the first abort request on the reploop
     self.euslisp.reset()
     self.euslisp.accumulate_output = False
Ejemplo n.º 4
0
class EuslimeHandler(object):
    def __init__(self, *args, **kwargs):
        self.euslisp = EuslispProcess(*args, **kwargs)
        self.close_request = Event()
        self.euslisp.start()
        self.command_id = None
        self.package = None
        self.debugger = []

    def restart_euslisp_process(self):
        program = self.euslisp.program
        init_file = self.euslisp.init_file
        color = self.euslisp.color
        self.euslisp.stop()
        self.euslisp = EuslispProcess(program, init_file, color=color)
        self.euslisp.start()

    def maybe_new_prompt(self):
        new_prompt = self.euslisp.exec_internal('(slime::slime-prompt)')
        if new_prompt:
            yield [Symbol(":new-package")] + new_prompt

    def arglist(self, func, cursor=None, form=None):
        if not isinstance(func, unicode) and not isinstance(func, str):
            log.debug("Expected string at: %s" % func)
            return None
        cmd = '(slime::autodoc "{0}" {1} (lisp:quote {2}))'.format(
            qstr(func), dumps_lisp(cursor), dumps_lisp(form))
        result = self.euslisp.exec_internal(cmd)
        if isinstance(result, str):
            return [result, False]
        elif result:
            return [dumps(result), True]
        return None

    def _emacs_return_string(self, process, count, msg):
        self.euslisp.input(msg)
        yield [Symbol(":read-string"), 0, 1]

    def _emacs_interrupt(self, process):
        raise KeyboardInterrupt

    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_create_repl(self, sexp):
        res = self.euslisp.exec_internal('(slime::slime-prompt)')
        yield EuslispResult(res)

    def swank_repl_create_repl(self, *sexp):
        return self.swank_create_repl(sexp)

    def swank_buffer_first_change(self, filename):
        yield EuslispResult(False)

    def swank_eval(self, sexp):
        yield [Symbol(":read-string"), 0, 1]
        try:
            for out in self.euslisp.eval(sexp):
                if isinstance(out, EuslispResult):
                    yield [Symbol(":read-aborted"), 0, 1]
                    for val in self.maybe_new_prompt():
                        yield val
                yield out
        except Exception as e:
            yield [Symbol(":read-aborted"), 0, 1]
            raise e

    def swank_interactive_eval(self, sexp):
        return self.swank_eval(sexp)

    def swank_interactive_eval_region(self, sexp):
        return self.swank_eval(sexp)

    def swank_repl_listener_eval(self, sexp):
        if self.debugger:
            return self.swank_throw_to_toplevel()
        return self.swank_eval(sexp)

    def swank_pprint_eval(self, sexp):
        return self.swank_eval(sexp)

    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_operator_arglist(self, func, pkg):
        #  (swank:operator-arglist "format" "USER")
        result = self.arglist(func)
        if result:
            result = result[0]
        yield EuslispResult(result)

    def swank_completions(self, start, pkg):
        if start and start[0] == ':':
            return self.swank_completions_for_keyword(start, None)
        else:
            return self.swank_simple_completions(start, pkg)
        # return self.swank_fuzzy_completions(start, pkg, ':limit', 300,
        #                                     ':time-limit-in-msec', 1500)

    def swank_simple_completions(self, start, pkg):
        # (swank:simple-completions "vector-" (quote "USER"))
        cmd = '(slime::slime-find-symbol "{0}")'.format(qstr(start))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    def swank_fuzzy_completions(self, start, pkg, *args):
        # Unsupported. Use swank_simple_completions instead
        yield EuslispResult([None, None])

    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_completions_for_character(self, start):
        cmd = '(slime::slime-find-character "{0}")'.format(qstr(start))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    def swank_complete_form(self, *args):
        # (swank:complete-form
        #    (quote ("float-vector" swank::%cursor-marker%))
        return

    def swank_quit_lisp(self, *args):
        self.euslisp.stop()
        self.close_request.set()

    def swank_backtrace(self, start, end):
        res = self.euslisp.get_callstack(end)
        yield EuslispResult(res[start:])

    def swank_throw_to_toplevel(self):
        lvl = len(self.debugger)
        return self.swank_invoke_nth_restart_for_emacs(lvl, 0)

    def swank_invoke_nth_restart_for_emacs(self, level, num):
        deb = self.debugger.pop(level - 1)
        res_dict = deb.restarts_dict

        def check_key(key):
            return key in res_dict and num == res_dict[key]

        if check_key('RESTART'):
            self.debugger = []
            self.restart_euslisp_process()
        elif check_key('CONTINUE'):
            pass
        elif check_key('QUIT'):
            self.debugger = []
            self.euslisp.reset()
        else:
            log.error("Restart not found!")

        msg = deb.message.split(self.euslisp.delim)[0]
        msg = repr(msg.rsplit(' in ', 1)[0])
        yield [Symbol(':debug-return'), 0, level, Symbol('nil')]
        yield [Symbol(':return'), {'abort': 'NIL'}, self.command_id]
        for val in self.maybe_new_prompt():
            yield val
        yield [Symbol(':return'), {'abort': msg}, deb.id]

    def swank_swank_require(self, *sexp):
        return

    def swank_init_presentations(self, *sexp):
        return

    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_compile_notes_for_emacs(self, *args):
        return self.swank_compile_string_for_emacs(*args)

    def swank_compile_file_for_emacs(self, *args):
        return self.swank_compile_file_if_needed(*args)

    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_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)

    def swank_inspect_current_condition(self):
        # (swank:inspect-current-condition)
        return

    def swank_sldb_abort(self, *args):
        return

    def swank_sldb_out(self, *args):
        return

    def swank_frame_locals_and_catch_tags(self, *args):
        return

    def swank_find_definitions_for_emacs(self, keyword):
        return

    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_describe_function(self, func):
        return self.swank_describe_symbol(func)

    def swank_describe_definition_for_emacs(self, name, type):
        return self.swank_describe_symbol(name)

    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_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_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_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_set_default_directory(self, dir):
        cmd = '(lisp:progn (lisp:cd "{0}") (lisp:pwd))'.format(qstr(dir))
        yield EuslispResult(self.euslisp.exec_internal(cmd))
Ejemplo n.º 5
0
class EuslimeHandler(object):
    def __init__(self, *args, **kwargs):
        self.euslisp = EuslispProcess(*args, **kwargs)
        self.close_request = Event()
        self.euslisp.start()
        self.package = None
        self.debugger = []

    def restart_euslisp_process(self):
        program = self.euslisp.program
        init_file = self.euslisp.init_file
        on_output = self.euslisp.on_output
        color = self.euslisp.color
        self.euslisp.stop()
        self.euslisp = EuslispProcess(program,
                                      init_file,
                                      on_output=on_output,
                                      color=color)
        self.euslisp.start()
        # get rid of the first abort request on the reploop
        self.euslisp.reset()
        self.euslisp.accumulate_output = False

    def maybe_new_prompt(self):
        cmd = '(slime::slime-prompt)'
        new_prompt = self.euslisp.exec_internal(cmd, force_repl_socket=True)
        if new_prompt:
            yield [Symbol(":new-package")] + new_prompt

    def arglist(self, func, cursor=None, form=None):
        if not isinstance(func, unicode) and not isinstance(func, str):
            log.debug("Expected string at: %s" % func)
            return None
        cmd = '(slime::autodoc "{0}" {1} (lisp:quote {2}))'.format(
            qstr(func), dumps_lisp(cursor), dumps_lisp(form))
        # Eval from repl_socket to cope with thread special symbols
        result = self.euslisp.exec_internal(cmd, force_repl_socket=True)
        if isinstance(result, str):
            return [result, False]
        elif result:
            return [dumps_vec(result), True]
        return None

    def _emacs_return_string(self, process, count, msg):
        self.euslisp.input(msg)
        if self.euslisp.read_busy:
            log.debug("Exitting read mode...")
            self.euslisp.read_busy = False
        if len(msg) % 128 == 0:
            # communicate when the message ends exactly at buffer end
            cmd = '(send slime::*slime-input-stream* :set-flag)'
            self.euslisp.exec_internal(cmd)
        if self.euslisp.read_mode:
            yield [Symbol(":read-string"), process, 1]

    def _emacs_interrupt(self, process):
        if self.euslisp.read_mode:
            # propagate the signal to all child processes
            os.kill(-os.getpgid(self.euslisp.process.pid), 2)
        else:
            # send the signal directly to the euslisp process
            self.euslisp.process.send_signal(signal.SIGINT)
        if isinstance(process, int):
            # during a :read-string call
            self.euslisp.read_busy = False
            yield [Symbol(":read-aborted"), process, 1]

    def swank_connection_info(self):
        cmd_version = '(slime::implementation-version)'
        cmd_name = '(lisp:pathname-name lisp:*program-name*)'
        version = self.euslisp.exec_internal(cmd_version)
        name = self.euslisp.exec_internal(cmd_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_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_repl_create_repl(self, *sexp):
        return self.swank_create_repl(sexp)

    def swank_buffer_first_change(self, filename):
        yield EuslispResult(False)

    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_interactive_eval(self, sexp):
        return self.swank_eval(sexp)

    def swank_interactive_eval_region(self, sexp):
        return self.swank_eval(sexp)

    def swank_repl_listener_eval(self, sexp):
        if self.debugger:
            return self.swank_throw_to_toplevel()
        return self.swank_eval(sexp)

    def swank_pprint_eval(self, sexp):
        return self.swank_eval(sexp)

    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_operator_arglist(self, func, pkg):
        #  (swank:operator-arglist "format" "USER")
        result = self.arglist(func)
        if result:
            result = result[0]
        yield EuslispResult(result)

    def swank_completions(self, start, pkg):
        if start and start[0] == ':':
            return self.swank_completions_for_keyword(start, None)
        else:
            return self.swank_simple_completions(start, pkg)
        # return self.swank_fuzzy_completions(start, pkg, ':limit', 300,
        #                                     ':time-limit-in-msec', 1500)

    def swank_simple_completions(self, start, pkg):
        # (swank:simple-completions "vector-" (quote "USER"))
        pkg = unquote(pkg)
        cmd = '(slime::slime-find-symbol "{0}" "{1}")'.format(
            qstr(start), qstr(pkg))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    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_fuzzy_completion_selected(self, original_string, completion):
        yield EuslispResult(None)

    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_completions_for_character(self, start):
        cmd = '(slime::slime-find-character "{0}")'.format(qstr(start))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    def swank_complete_form(self, *args):
        # (swank:complete-form
        #    (quote ("float-vector" swank::%cursor-marker%))
        return

    def swank_quit_lisp(self, *args):
        self.euslisp.stop()
        self.close_request.set()

    def swank_backtrace(self, start, end):
        res = self.euslisp.get_callstack(end)
        yield EuslispResult(res[start:])

    def swank_throw_to_toplevel(self):
        lvl = len(self.debugger)
        return self.swank_invoke_nth_restart_for_emacs(lvl, 0)

    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_sldb_return_from_frame(self, num, value):
        return

    def swank_restart_frame(self, num):
        return

    def swank_swank_require(self, *sexp):
        return

    def swank_swank_add_load_paths(self, *sexp):
        return

    def swank_init_presentations(self, *sexp):
        return

    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_compile_notes_for_emacs(self, *args):
        return self.swank_compile_string_for_emacs(*args)

    def swank_compile_file_for_emacs(self, *args):
        return self.swank_compile_file_if_needed(*args)

    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_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_inspect_current_condition(self):
        # (swank:inspect-current-condition)
        return

    def swank_sldb_abort(self, *args):
        return

    def swank_sldb_out(self, *args):
        return

    def swank_frame_locals_and_catch_tags(self, *args):
        # [RET] on sldb Backtrace entry
        # Display local bindings at the given frame
        # e.g. (:return (:ok (((:name "NUMBER" :id 0 :value "NIL")) nil)) 7)
        return

    def swank_find_definitions_for_emacs(self, keyword):
        return

    def swank_find_tag_name_for_emacs(self, name, pkg):
        cmd = '(slime::find-tag-name-for-emacs "{0}" "{1}")'.format(
            qstr(name), qstr(pkg))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    def swank_describe_symbol(self, sym):
        cmd = '(slime::slime-describe-symbol "{0}" "{1}")'.format(
            qstr(sym.strip()), qstr(self.package))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    def swank_describe_function(self, func):
        return self.swank_describe_symbol(func)

    def swank_describe_definition_for_emacs(self, name, type):
        return self.swank_describe_symbol(name)

    def swank_swank_expand_1(self, form):
        cmd = '(slime::slime-macroexpand "{0}" "{1}")'.format(
            qstr(form), qstr(self.package))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    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_apropos_list_for_emacs(self,
                                     key,
                                     external_only=None,
                                     case_sensitive=None,
                                     package=None):
        # ignore 'external_only' and 'case_sensitive' arguments
        package = unquote(package)
        cmd = '(slime::slime-apropos-list "{0}" {1})'.format(
            qstr(key), dumps_lisp(package))
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    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_clear_repl_results(self):
        return

    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_default_directory(self):
        cmd = '(lisp:pwd)'
        yield EuslispResult(self.euslisp.exec_internal(cmd))

    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))