Тут кусок кода из slime, видно, что люди понимают то, что они делают. Главная тут make-connection, как с ней поиграться можно? Какими ещё знаниями нужно обладать чтобы написать этот код? Помимо того, что для соединения нам надо знать имя сайта и его IP адрес, в данном случае localhost, да, и порт на котором будет подключение.
Почитав код я что-то понял, а с чем-то надо поиграться, а как не знаю, чего-то не хватает, подскажите, где, как поиграться? А там глядишь и найду чего не хватает.
;;;; Connections
;;;
;;; Connection structures represent the network connections between
;;; Emacs and Lisp. Each has a socket stream, a set of user I/O
;;; streams that redirect to Emacs, and optionally a second socket
;;; used solely to pipe user-output to Emacs (an optimization). This
;;; is also the place where we keep everything that needs to be
;;; freed/closed/killed when we disconnect.
(defstruct (connection
(:constructor %make-connection)
(:conc-name connection.)
(:print-function print-connection))
;; The listening socket. (usually closed)
(socket (missing-arg) :type t :read-only t)
;; Character I/O stream of socket connection. Read-only to avoid
;; race conditions during initialization.
(socket-io (missing-arg) :type stream :read-only t)
;; Optional dedicated output socket (backending `user-output' slot).
;; Has a slot so that it can be closed with the connection.
(dedicated-output nil :type (or stream null))
;; Streams that can be used for user interaction, with requests
;; redirected to Emacs.
(user-input nil :type (or stream null))
(user-output nil :type (or stream null))
(user-io nil :type (or stream null))
;; Bindings used for this connection (usually streams)
(env '() :type list)
;; A stream that we use for *trace-output*; if nil, we user user-output.
(trace-output nil :type (or stream null))
;; A stream where we send REPL results.
(repl-results nil :type (or stream null))
;; Cache of macro-indentation information that has been sent to Emacs.
;; This is used for preparing deltas to update Emacs's knowledge.
;; Maps: symbol -> indentation-specification
(indentation-cache (make-hash-table :test 'eq) :type hash-table)
;; The list of packages represented in the cache:
(indentation-cache-packages '())
;; The communication style used.
(communication-style nil :type (member nil :spawn :sigio :fd-handler))
)
(defun print-connection (conn stream depth)
(declare (ignore depth))
(print-unreadable-object (conn stream :type t :identity t)))
(defstruct (singlethreaded-connection (:include connection)
(:conc-name sconn.))
;; The SIGINT handler we should restore when the connection is
;; closed.
saved-sigint-handler
;; A queue of events. Not all events can be processed in order and
;; we need a place to stored them.
(event-queue '() :type list)
;; A counter that is incremented whenever an event is added to the
;; queue. This is used to detected modifications to the event queue
;; by interrupts. The counter wraps around.
(events-enqueued 0 :type fixnum))
(defstruct (multithreaded-connection (:include connection)
(:conc-name mconn.))
;; In multithreaded systems we delegate certain tasks to specific
;; threads. The `reader-thread' is responsible for reading network
;; requests from Emacs and sending them to the `control-thread'; the
;; `control-thread' is responsible for dispatching requests to the
;; threads that should handle them; the `repl-thread' is the one
;; that evaluates REPL expressions. The control thread dispatches
;; all REPL evaluations to the REPL thread and for other requests it
;; spawns new threads.
reader-thread
control-thread
repl-thread
auto-flush-thread
indentation-cache-thread
;; List of threads that are currently processing requests. We use
;; this to find the newest/current thread for an interrupt. In the
;; future we may store here (thread . request-tag) pairs so that we
;; can interrupt specific requests.
(active-threads '() :type list)
)
(defvar *emacs-connection* nil
"The connection to Emacs currently in use.")
(defun make-connection (socket stream style)
(let ((conn (funcall (ecase style
(:spawn
#'make-multithreaded-connection)
((:sigio nil :fd-handler)
#'make-singlethreaded-connection))
:socket socket
:socket-io stream
:communication-style style)))
(run-hook *new-connection-hook* conn)
(send-to-sentinel `(:add-connection ,conn))
conn))
(defslimefun ping (tag)
tag)
(defun safe-backtrace ()
(ignore-errors
(call-with-debugging-environment
(lambda () (backtrace 0 nil)))))
(define-condition swank-error (error)
((backtrace :initarg :backtrace :reader swank-error.backtrace)
(condition :initarg :condition :reader swank-error.condition))
(:report (lambda (c s) (princ (swank-error.condition c) s)))
(:documentation "Condition which carries a backtrace."))
(defun signal-swank-error (condition &optional (backtrace (safe-backtrace)))
(error 'swank-error :condition condition :backtrace backtrace))
(defvar *debug-on-swank-protocol-error* nil
"When non-nil invoke the system debugger on errors that were
signalled during decoding/encoding the wire protocol. Do not set this
to T unless you want to debug swank internals.")
(defmacro with-swank-error-handler ((connection) &body body)
"Close the connection on internal `swank-error's."
(let ((conn (gensym)))
`(let ((,conn ,connection))
(handler-case
(handler-bind ((swank-error
(lambda (condition)
(when *debug-on-swank-protocol-error*
(invoke-default-debugger condition)))))
(progn . ,body))
(swank-error (condition)
(close-connection ,conn
(swank-error.condition condition)
(swank-error.backtrace condition)))))))
(defmacro with-panic-handler ((connection) &body body)
"Close the connection on unhandled `serious-condition's."
(let ((conn (gensym)))
`(let ((,conn ,connection))
(handler-bind ((serious-condition
(lambda (condition)
(close-connection ,conn condition (safe-backtrace))
(abort condition))))
. ,body))))
(add-hook *new-connection-hook* 'notify-backend-of-connection)
(defun notify-backend-of-connection (connection)
(declare (ignore connection))
(emacs-connected))