@@ -949,15 +949,57 @@ returned."
949949; ; Pipe to $SHELL to work around mackosecks GUI Emacs $PATH issues.
950950(defcustom clojure-swank-command
951951 (if (or (locate-file " lein" exec-path) (locate-file " lein.bat" exec-path))
952- " lein jack-in %s %s "
953- " echo \" lein jack-in %s %s \" | $SHELL -l" )
952+ " lein jack-in %s"
953+ " echo \" lein jack-in %s\" | $SHELL -l" )
954954 " The command used to start swank via clojure-jack-in.
955955For remote swank it is lein must be in your PATH and the remote
956956proc is launched via sh rather than bash, so it might be necessary
957- to specific the full path to it. The arguments are port, hostname."
957+ to specific the full path to it. The argument is the port to connect on.
958+ Localhost is assumed."
958959 :type 'string
959960 :group 'clojure-mode )
960961
962+ (defcustom clojure-generate-remote-swank-command-function
963+ 'clojure-generate-remote-swank-command-ssh-tunnel
964+ " A function that is called to determine the swank command that
965+ `clojure-jack-in` will execute and the hostname/port that slime
966+ should connect to for remote projects that are opened via tramp.
967+
968+ The arguments are dir, hostname, and port. The return value should be an `alist` of the form
969+ (:cmd \" command string\" :hostname \" hostname\" :port 1234)"
970+ :type 'function
971+ :group 'clojure-mode )
972+
973+ (defun clojure-generate-local-swank-command-default (dir hostname port )
974+ (if (not (string-equal " localhost" hostname))
975+ (error (concat
976+ " If you need to jack-in to remote projects/jvms over tramp, "
977+ " you need to define a custom `clojure-generate-swank-command-function`" ))
978+ (list :cmd (format clojure-swank-command port)
979+ :hostname hostname
980+ :port port)))
981+
982+ (defun clojure-generate-remote-swank-command-ssh-tunnel (dir hostname port )
983+ (destructuring-bind (_method user host localname)
984+ (append (tramp-dissect-file-name dir) nil )
985+ (list :cmd (format-spec
986+ " ssh -L %p:localhost:%p -l '%u' '%h' 'cd \' %d\' ; lein jack-in \' %p\' '"
987+ `((?p . , port )
988+ (?h . , host )
989+ (?u . ,(or user (getenv " USER" )))
990+ (?d . , localname )))
991+ :hostname " localhost"
992+ :port port)))
993+
994+ (defun clojure-generate-swank-cmd (dir hostname port )
995+ (if (file-remote-p dir)
996+ (if (functionp clojure-generate-remote-swank-command-function)
997+ (funcall clojure-generate-remote-swank-command-function dir hostname port)
998+ (error (concat
999+ " If you need to jack-in to remote projects/jvms over tramp "
1000+ " you need to define a custom `clojure-generate-remote-swank-command-function`" )))
1001+ (clojure-generate-local-swank-command-default dir hostname port)))
1002+
9611003(defun clojure-jack-in-sentinel (process event )
9621004 (let ((debug-on-error t ))
9631005 (error " Could not start swank server: %s "
@@ -985,54 +1027,63 @@ to specific the full path to it. The arguments are port, hostname."
9851027 (set-process-query-on-exit-flag process nil ))
9861028 (kill-buffer swank-buffer-name))))
9871029
988- (defun clojure-generate-swank-connection-name (dir hostname port )
1030+ (defun clojure-generate-swank-connection-name (dir hostname )
9891031 " swank" )
9901032
991- (defun clojure-jack-in-start-process (swank-connection-name swank-buffer-name hostname port )
992- ; ; the buffer has to be created before the proc:
1033+ (defun clojure-jack-in-start-process (swank-connection-name swank-buffer-name dir hostname )
1034+ ; ; The buffer has to be created before the proc if
1035+ ; ; `start-file-process-shell-command` is used. It doesn't hurt to do
1036+ ; ; it now even if `start-process-shell-command` is used:
9931037 (get-buffer-create swank-buffer-name)
9941038
995- (let ((swank-cmd (format clojure-swank-command port hostname)))
996- (lexical-let* ((proc (start-file-process-shell-command
997- swank-connection-name
998- swank-buffer-name
999- swank-cmd))
1000- (hostname hostname)
1001- (port port)
1002- (connect-callback (lambda () (slime-connect hostname port))))
1003- (set-process-sentinel proc 'clojure-jack-in-sentinel )
1004- (set-process-query-on-exit-flag proc nil )
1005- (set-process-filter proc
1006- (lambda (process output )
1007- (with-current-buffer (process-buffer process)
1008- (insert output))
1009- (when (string-match " proceed to jack in" output)
1010- (clojure-eval-bootstrap-region process)
1011- (with-current-buffer
1012- ; ; this block is an attempt to avoid
1013- ; ; creating duplicate repl windows
1014- (or
1015- (get-buffer " *slime-repl clojure*" )
1016- (get-buffer " *slime-repl nil*" )
1017- (current-buffer ))
1018- (funcall connect-callback)
1019- (when (string-match " slime-repl" (buffer-name ))
1020- (goto-char (point-max ))))
1021- (set-process-sentinel process nil )
1022- (set-process-filter process nil )))))))
1039+ (let ((port (- 65535 (mod (caddr (current-time )) 4096 ))))
1040+ (destructuring-bind (&key cmd hostname port)
1041+ (clojure-generate-swank-cmd dir hostname port)
1042+ (lexical-let* ((proc (start-process-shell-command
1043+ ; ; this command runs locally
1044+ ; ; `start-file-process-shell-command` would
1045+ ; ; run remote for tramp buffers
1046+ swank-connection-name
1047+ swank-buffer-name
1048+ cmd))
1049+ (dir dir)
1050+ (hostname hostname)
1051+ (port port)
1052+ (connect-callback (lambda () (slime-connect hostname port))))
1053+ (set-process-sentinel proc 'clojure-jack-in-sentinel )
1054+ (set-process-query-on-exit-flag proc nil )
1055+ (set-process-filter proc
1056+ (lambda (process output )
1057+ (with-current-buffer (process-buffer process)
1058+ (insert output))
1059+ (when (string-match " proceed to jack in" output)
1060+ (clojure-eval-bootstrap-region process)
1061+ (with-current-buffer
1062+ ; ; this block is an attempt to avoid
1063+ ; ; creating duplicate repl windows
1064+ (or
1065+ (get-buffer " *slime-repl clojure*" )
1066+ (get-buffer " *slime-repl nil*" )
1067+ (current-buffer ))
1068+ (funcall connect-callback)
1069+ (when (string-match " slime-repl" (buffer-name ))
1070+ ; ; this is most likely an old repl
1071+ ; ; buffer that existed prior to the
1072+ ; ; jack-in call.
1073+ (setq default-directory dir)
1074+ (goto-char (point-max ))))
1075+ (set-process-sentinel process nil )
1076+ (set-process-filter process nil ))))))))
10231077
10241078;;;### autoload
10251079(defun clojure-jack-in ()
10261080 (interactive )
10271081 (setq slime-net-coding-system 'utf-8-unix )
1028- (let* ((port (- 65535 (mod (caddr (current-time )) 4096 )))
1029- (dir default-directory)
1082+ (let* ((dir default-directory)
10301083 (hostname (if (file-remote-p default-directory)
1031- tramp-current-host
1032- " localhost" ))
1033- (swank-connection-name
1034- (clojure-generate-swank-connection-name dir hostname port))
1035- (swank-buffer-name (format " *%s * " swank-connection-name)))
1084+ tramp-current-host " localhost" ))
1085+ (connection-name (clojure-generate-swank-connection-name dir hostname))
1086+ (swank-buffer-name (format " *%s * " connection-name)))
10361087
10371088 (when (and (functionp 'slime-disconnect )
10381089 (slime-current-connection)
@@ -1041,9 +1092,7 @@ to specific the full path to it. The arguments are port, hostname."
10411092 )
10421093 (slime-disconnect))
10431094 (clojure-kill-swank-buffer swank-buffer-name)
1044- (clojure-jack-in-start-process swank-connection-name
1045- swank-buffer-name
1046- hostname port))
1095+ (clojure-jack-in-start-process connection-name swank-buffer-name dir hostname))
10471096 (message " Starting swank server... " ))
10481097
10491098(defun clojure-find-ns ()
0 commit comments