93 lines
3.1 KiB
Clojure
93 lines
3.1 KiB
Clojure
|
;;;; swank-clojure.clj --- Swank server for Clojure
|
||
|
;;;
|
||
|
;;; Copyright (C) 2008 Jeffrey Chu
|
||
|
;;;
|
||
|
;;; This file is licensed under the terms of the GNU General Public
|
||
|
;;; License as distributed with Emacs (press C-h C-c to view it).
|
||
|
;;;
|
||
|
;;; See README file for more information about installation
|
||
|
;;;
|
||
|
|
||
|
(ns swank.swank
|
||
|
(:use [swank.core]
|
||
|
[swank.core connection server]
|
||
|
[swank.util.concurrent thread]
|
||
|
[swank.util.net sockets]
|
||
|
[clojure.main :only [repl]])
|
||
|
(:require [swank.commands]
|
||
|
[swank.commands basic indent completion
|
||
|
contrib inspector])
|
||
|
(:import [java.lang System]
|
||
|
[java.io File])
|
||
|
(:gen-class))
|
||
|
|
||
|
(defn ignore-protocol-version [version]
|
||
|
(reset! protocol-version version))
|
||
|
|
||
|
(defn- connection-serve [conn]
|
||
|
(let [control
|
||
|
(dothread-swank
|
||
|
(thread-set-name "Swank Control Thread")
|
||
|
(try
|
||
|
(control-loop conn)
|
||
|
(catch Exception e
|
||
|
;; fail silently
|
||
|
nil))
|
||
|
(close-socket! (conn :socket)))
|
||
|
read
|
||
|
(dothread-swank
|
||
|
(thread-set-name "Read Loop Thread")
|
||
|
(try
|
||
|
(read-loop conn control)
|
||
|
(catch Exception e
|
||
|
;; This could be put somewhere better
|
||
|
(.println System/err "exception in read loop")
|
||
|
(.printStackTrace e)
|
||
|
(.interrupt control)
|
||
|
(dosync (alter connections (partial remove #{conn}))))))]
|
||
|
(dosync
|
||
|
(ref-set (conn :control-thread) control)
|
||
|
(ref-set (conn :read-thread) read))))
|
||
|
|
||
|
(defn start-server
|
||
|
"Start the server and write the listen port number to
|
||
|
PORT-FILE. This is the entry point for Emacs."
|
||
|
[port-file & opts]
|
||
|
(let [opts (apply hash-map opts)]
|
||
|
(setup-server (get opts :port 0)
|
||
|
(fn announce-port [port]
|
||
|
(announce-port-to-file port-file port)
|
||
|
(simple-announce port))
|
||
|
connection-serve
|
||
|
opts)))
|
||
|
|
||
|
(def #^{:private true} encodings-map
|
||
|
{"UTF-8" "utf-8-unix"
|
||
|
})
|
||
|
|
||
|
(defn- get-system-encoding []
|
||
|
(when-let [enc-name (.name (java.nio.charset.Charset/defaultCharset))]
|
||
|
(encodings-map enc-name)))
|
||
|
|
||
|
(defn start-repl
|
||
|
"Start the server wrapped in a repl. Use this to embed swank in your code."
|
||
|
([port & opts]
|
||
|
(let [stop (atom false)
|
||
|
opts (merge {:port (Integer. port)
|
||
|
:encoding (or (System/getProperty "swank.encoding")
|
||
|
(get-system-encoding)
|
||
|
"iso-latin-1-unix")}
|
||
|
(apply hash-map opts))]
|
||
|
(repl :read (fn [rprompt rexit]
|
||
|
(if @stop rexit
|
||
|
(do (reset! stop true)
|
||
|
`(start-server (-> "java.io.tmpdir"
|
||
|
(System/getProperty)
|
||
|
(File. "slime-port.txt")
|
||
|
(.getCanonicalPath))
|
||
|
~@(apply concat opts)))))
|
||
|
:need-prompt (constantly false))))
|
||
|
([] (start-repl 4005)))
|
||
|
|
||
|
(def -main start-repl)
|