Guest User

Untitled

a guest
Jul 16th, 2018
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.75 KB | None | 0 0
  1. ;; -*-mode:Emacs-Lisp;buffer-cleanup-p:t-*-
  2. ;; Time-stamp: <2010-09-15 08:54:34 dky>
  3. ;;-----------------------------------------------------------------------------
  4. ;; File : emacsserver.el
  5. ;; Auth : Dhruva Krishnamurthy (dhruvakm@gmail.com)
  6. ;; Status : Development (flaky)
  7. ;; Usage :
  8. ;; o As server:
  9. ;; (require 'emacsserver)
  10. ;; (emacsserver-start "magic")
  11. ;; o As client:
  12. ;; emacs --batch --load emacsserver.el
  13. ;; --eval "(emacsclient-command '(find-file \"~/_emacs\") \"magic\")"
  14. ;;
  15. ;; TODO :
  16. ;; o Does not work on XEmacs ('make-network-process not available)
  17. ;; o Code cleanup, optimize, document and misc stuff
  18. ;;-----------------------------------------------------------------------------
  19. ;; This is not available on XEmacs and Emacs prior to 21.4
  20. (if (not (featurep 'make-network-process))
  21. (error "Incompatible version of [X]Emacs"))
  22.  
  23. (defvar emacsclient-hash
  24. (make-hash-table :test 'eq)
  25. "emacsserver: Internal client connection info")
  26.  
  27. (defvar emacsserver-hash
  28. (make-hash-table)
  29. "emacsserver: Internal server details")
  30.  
  31. ;;-----------------------------------------------------------------------------
  32. ;; GNU Emacs server code
  33. ;;-----------------------------------------------------------------------------
  34.  
  35. ;;-----------------------------------------------------------------------------
  36. ;; emacsserver-start
  37. ;;-----------------------------------------------------------------------------
  38. (defun emacsserver-start (&optional magic port)
  39. "emacsserver: Starts a server on specified port and binds to localhost"
  40. (interactive)
  41. (catch 'ret
  42. (let ((server-port (if (integerp port)
  43. port
  44. 55555))
  45. (key (if magic
  46. magic
  47. "houdini")))
  48.  
  49. ;; Prevent running another server on same port
  50. ;; in the current emacs session
  51. (if (gethash server-port emacsserver-hash)
  52. (throw 'ret nil))
  53.  
  54. ;; Store a hash of port->(magic,server proc) for client auth
  55. (puthash server-port (cons key (make-network-process
  56. :name "emacsserver"
  57. :buffer nil
  58. :type nil
  59. :server t
  60. :service server-port
  61. :local (vector 127 0 0 1 server-port)
  62. :noquery t
  63. :filter 'emacsserver-filter
  64. :sentinel 'emacsserver-sentinel
  65. :keepalive t))
  66. emacsserver-hash))
  67. (throw 'ret t)))
  68.  
  69. ;;-----------------------------------------------------------------------------
  70. ;; emacsserver-filter
  71. ;; Do the actual auth'ing
  72. ;; Message format: (magic (expr to be evaluated))
  73. ;;-----------------------------------------------------------------------------
  74. (defun emacsserver-filter (proc mesg)
  75. "emacsserver: Server side message processing with auth"
  76. (catch 'ret
  77. (let ((cwd default-directory)
  78. (auth (gethash proc emacsclient-hash))
  79. (serv (gethash (aref (process-contact proc ':local) 4)
  80. emacsserver-hash)))
  81. (if (not (listp serv))
  82. (throw 'ret nil))
  83.  
  84. ;; Try auth'ing till the connection is auth'ed
  85. (if (not auth)
  86. (if (string= (car serv) (caar (read-from-string mesg)))
  87. (progn
  88. (puthash proc t emacsclient-hash)
  89. (setq auth t))))
  90.  
  91. (if (not auth)
  92. (throw 'ret nil))
  93.  
  94. ;; Eval the code to be executed
  95. (eval (car (cdar (read-from-string mesg))))
  96. ;; Change back from client's default-dir to server's default-dir
  97. (cd cwd))
  98. (throw 'ret t)))
  99.  
  100. ;;-----------------------------------------------------------------------------
  101. ;; emacsserver-sentinel
  102. ;;-----------------------------------------------------------------------------
  103. (defun emacsserver-sentinel (proc mesg)
  104. "emacsserver: Populate emacs client connections in a hash pending auth'ing"
  105. (emacsclient-refresh)
  106. (if (eq (process-status proc) 'open)
  107. (puthash proc nil emacsclient-hash)))
  108.  
  109. ;;-----------------------------------------------------------------------------
  110. ;; emacsserver-kill
  111. ;;-----------------------------------------------------------------------------
  112. (defun emacsserver-kill ()
  113. "emacsserver: Kill all emacs client & server instances"
  114. (interactive)
  115. (emacsclient-kill) ; Clear the clients first
  116. (maphash '(lambda (key val)
  117. (delete-process (cdr val))) emacsserver-hash)
  118. (clrhash emacsserver-hash)
  119. (if (interactive-p)
  120. (message "Emacs client & server processes cleared")))
  121.  
  122. ;;-----------------------------------------------------------------------------
  123. ;; emacsserver-enum
  124. ;;-----------------------------------------------------------------------------
  125. (defun emacsserver-enum ()
  126. "emacsserver: Enumerate server instances"
  127. (interactive)
  128. (maphash '(lambda (key val)
  129. (princ (format "Server process:%s,Auth:%s" (cdr val) (car val))))
  130. emacsserver-hash))
  131.  
  132. ;;-----------------------------------------------------------------------------
  133. ;; emacsclient-refresh
  134. ;;-----------------------------------------------------------------------------
  135. (defun emacsclient-refresh ()
  136. "emacsserver: Refreshes client instance hash by clearing dead connections"
  137. (interactive)
  138. (maphash '(lambda (key val)
  139. (if (/= (process-exit-status key) 0)
  140. (remhash key emacsclient-hash)))
  141. emacsclient-hash)
  142. (if (interactive-p)
  143. (message "Emacs client processes refreshed")))
  144.  
  145. ;;-----------------------------------------------------------------------------
  146. ;; emacsclient-enum
  147. ;;-----------------------------------------------------------------------------
  148. (defun emacsclient-enum ()
  149. "emacsserver: Enumerate client instances"
  150. (interactive)
  151. (emacsclient-refresh)
  152. (maphash '(lambda (key val)
  153. (princ (format "Client process:%s, Auth:%s" key val)))
  154. emacsclient-hash))
  155.  
  156. ;;-----------------------------------------------------------------------------
  157. ;; emacsclient-kill
  158. ;;-----------------------------------------------------------------------------
  159. (defun emacsclient-kill ()
  160. "emacsserver: Kill all emacs client instances"
  161. (interactive)
  162. (maphash '(lambda (key val)
  163. (delete-process key)) emacsclient-hash)
  164. (clrhash emacsclient-hash)
  165. (if (interactive-p)
  166. (message "Emacs client processes cleared")))
  167.  
  168. ;;-----------------------------------------------------------------------------
  169. ;; emacsclient-command
  170. ;;-----------------------------------------------------------------------------
  171. (defun emacsclient-command (expr &optional magic port)
  172. "emacsserver: Dispatches a expression to emacs server. The message follows
  173. the format (magic (cd client-dir) (progn (expr)))"
  174. (catch 'ret
  175. (let ((emacsclient (make-network-process
  176. :name "emacsclient"
  177. :buffer nil
  178. :type nil
  179. :host "127.0.0.1"
  180. :service 55555
  181. :noquery t
  182. :keepalive t))
  183. (key (if magic
  184. magic
  185. "houdini")))
  186. (if emacsclient
  187. (progn
  188. (process-send-string
  189. emacsclient (concat
  190. "(" key
  191. "(progn (cd " (prin1-to-string default-directory) ")"
  192. (prin1-to-string expr) "))"))
  193. (throw 'ret t))
  194. (throw 'ret nil)))
  195. (throw 'ret nil))
  196. t)
  197.  
  198. ;;-----------------------------------------------------------------------------
  199. (provide 'emacsserver)
  200. ;;-----------------------------------------------------------------------------
Add Comment
Please, Sign In to add comment