11; ;; pythonic.el --- Utility functions for writing pythonic emacs package. -*- lexical-binding : t ; -*-
22
3- ; ; Copyright (C) 2015-2016 by Artem Malyshev
3+ ; ; Copyright (C) 2015-2018 by Artem Malyshev
44
55; ; Author: Artem Malyshev <proofit404@gmail.com>
66; ; URL: https://github.com/proofit404/pythonic
77; ; Version: 0.1.1
8- ; ; Package-Requires: ((emacs "24") (cl-lib "0.5") (dash "2.11 ") (s "1.9") (f "0.17.2"))
8+ ; ; Package-Requires: ((emacs "25 ") (s "1.9") (f "0.17.2"))
99
1010; ; This program is free software; you can redistribute it and/or modify
1111; ; it under the terms of the GNU General Public License as published by
2727; ;; Code:
2828
2929(require 'python )
30- (require 'tramp )
31- (require 'tramp-sh )
3230(require 'cl-lib )
33- (require 'dash )
31+ (require 'tramp )
3432(require 's )
3533(require 'f )
3634
37- (defvaralias 'pythonic-environment
38- (if (boundp 'python-shell-virtualenv-root )
39- 'python-shell-virtualenv-root
40- 'python-shell-virtualenv-path )
41- " Alias to `python.el' virtualenv variable." )
42-
4335(defun pythonic-remote-p ()
4436 " Determine remote or local virtual environment."
45- (if pythonic-environment
46- (tramp-tramp-file-p pythonic-environment)
47- (tramp-tramp-file-p python-shell-interpreter)))
37+ (tramp-tramp-file-p default-directory))
4838
4939(defun pythonic-remote-docker-p ()
5040 " Determine docker remote virtual environment."
5141 (and (pythonic-remote-p)
52- (s-starts-with-p " /docker:" (pythonic-tramp -connection))))
42+ (s-starts-with-p " /docker:" (pythonic-remote -connection))))
5343
5444(defun pythonic-remote-vagrant-p ()
5545 " Determine vagrant remote virtual environment."
5949
6050(defun pythonic-remote-user ()
6151 " Get user of the connection to the remote python interpreter."
62- (tramp-file-name-user
63- (tramp-dissect-file-name
64- (pythonic-tramp-connection))))
52+ (tramp-file-name-user (tramp-dissect-file-name (pythonic-remote-connection))))
6553
6654(defun pythonic-remote-host ()
6755 " Get host of the connection to the remote python interpreter."
6856 (replace-regexp-in-string
6957 " #.*\\ '" " "
70- (tramp-file-name-host
71- (tramp-dissect-file-name
72- (pythonic-tramp-connection)))))
58+ (tramp-file-name-host (tramp-dissect-file-name (pythonic-remote-connection)))))
7359
7460(defun pythonic-remote-port ()
7561 " Get port of the connection to the remote python interpreter."
76- (let ((hostname (tramp-file-name-host
77- (tramp-dissect-file-name
78- (pythonic-tramp-connection)))))
62+ (let ((hostname (tramp-file-name-host (tramp-dissect-file-name (pythonic-remote-connection)))))
7963 (when (s-contains-p " #" hostname)
8064 (string-to-number (replace-regexp-in-string " \\ `.*#" " " hostname)))))
8165
82- (defun pythonic-file-name (file )
83- " Normalized FILE location with out tramp prefix."
66+ (defun pythonic-local- file-name (file )
67+ " Local FILE name with out tramp prefix."
8468 (if (tramp-tramp-file-p file)
85- (tramp-file-name-localname
86- (tramp-dissect-file-name file))
69+ (tramp-file-name-localname (tramp-dissect-file-name file))
8770 file))
8871
89- (defun pythonic-tramp-connection ()
90- " Tramp connection string or nil."
91- (-when-let* ((vars (--filter (tramp-tramp-file-p it)
92- (list pythonic-environment
93- python-shell-interpreter)))
94- (var (car vars)))
95- (substring var 0 (- (length var) (length (pythonic-file-name var))))))
96-
97- (defun pythonic-executable ()
98- " Python executable."
99- (let* ((windowsp (eq system-type 'windows-nt ))
100- (python (if windowsp " pythonw" " python" ))
101- (bin (if windowsp " Scripts" " bin" )))
102- (if pythonic-environment
103- (f-join (pythonic-file-name pythonic-environment) bin python)
104- (pythonic-file-name python-shell-interpreter))))
72+ (defun pythonic-real-file-name (file )
73+ " Probably Remote FILE name with tramp prefix."
74+ (if (and (pythonic-remote-p)
75+ (not (tramp-tramp-file-p file)))
76+ (concat (pythonic-remote-connection) file)
77+ file))
10578
106- (defun pythonic-default -directory ( &optional from- directory )
79+ (defun pythonic-real -directory-name ( directory )
10780 " Generate `default-directory' FROM-DIRECTORY."
108- (let ((default-directory
109- (concat (pythonic-tramp-connection)
110- (or from-directory " ~" ))))
81+ (let ((default-directory (pythonic-real-file-name directory)))
11182 (f-full default-directory)))
11283
113- (defun pythonic-set-process-environment ()
114- " Set process environment variables from `python-mode' settings.
115- It will use `python-shell-exec-path' for PATH variable,
116- `python-shell-extra-pythonpaths' for PYTHONPATH variable."
117- (if (pythonic-remote-p)
118- (progn
119- (pythonic-set-pythonpath-variable-tramp)
120- (pythonic-set-path-variable-tramp)
121- (pythonic-set-extra-variables-tramp))
122- (pythonic-set-pythonpath-variable)
123- (pythonic-set-path-variable)
124- (pythonic-set-extra-variables)))
125-
126- (defun pythonic-get-pythonpath ()
127- " Get appropriate PYTHONPATH variable for pythonic process."
128- (if (pythonic-remote-p)
129- (pythonic-get-pythonpath-variable-tramp)
130- (pythonic-get-pythonpath-variable)))
131-
132- (defun pythonic-get-pythonpath-variable ()
133- " Get PYTHONPATH variable from `python-shell-extra-pythonpaths' variable."
134- (s-join path-separator
135- (->> (or (getenv " PYTHONPATH" ) " " )
136- (s-split path-separator)
137- (-union python-shell-extra-pythonpaths)
138- (-remove 's-blank? )
139- (-distinct))))
140-
141- (defun pythonic-get-pythonpath-variable-tramp ()
142- " Get PYTHONPATH variable form `python-shell-extra-pythonpaths' on the remote host."
143- (let ((connection (tramp-dissect-file-name (pythonic-tramp-connection))))
144- (s-join path-separator
145- (--> (progn
146- (tramp-send-command connection " echo $PYTHONPATH" )
147- (with-current-buffer (tramp-get-connection-buffer connection)
148- (buffer-string )))
149- (s-trim it)
150- (s-split " :" it t )
151- (--remove (member it python-shell-extra-pythonpaths) it)
152- (append python-shell-extra-pythonpaths it)))))
153-
154- (defun pythonic-set-pythonpath-variable ()
155- " Set PYTHONPATH variable from `python-shell-extra-pythonpaths' variable."
156- (setenv " PYTHONPATH" (pythonic-get-pythonpath-variable)))
157-
158- (defun pythonic-set-pythonpath-variable-tramp ()
159- " Set PYTHONPATH variable from `python-shell-extra-pythonpaths' variable on remote host."
160- (tramp-send-command
161- (tramp-dissect-file-name (pythonic-tramp-connection))
162- (format
163- " export PYTHONPATH=%s"
164- (pythonic-get-pythonpath-variable-tramp))))
165-
166- (defun pythonic-get-path ()
167- " Return appropriate PATH variable for pythonic process."
168- (if (pythonic-remote-p)
169- (pythonic-get-path-variable-tramp)
170- (pythonic-get-path-variable)))
171-
172- (defun pythonic-get-path-variable ()
173- " Get PATH variable according to `python-shell-exec-path' ."
174- (s-join path-separator
175- (->> (or (getenv " PATH" ) " " )
176- (s-split path-separator)
177- (-union python-shell-exec-path)
178- (-remove 's-blank? )
179- (-distinct))))
180-
181- (defun pythonic-get-path-variable-tramp ()
182- " Get PATH variable on remote host according to `python-shell-exec-path' ."
183- (let* ((vec (tramp-dissect-file-name (pythonic-tramp-connection)))
184- (path (-distinct (append python-shell-exec-path (tramp-get-remote-path vec)))))
185- (s-join path-separator path)))
186-
187- (defun pythonic-set-path-variable ()
188- " Set PATH according to `python-shell-exec-path' ."
189- (setenv " PATH" (pythonic-get-path-variable)))
190-
191- (defun pythonic-set-path-variable-tramp ()
192- " Set PATH according to `python-shell-exec-path' on remote host."
193- (let* ((vec (tramp-dissect-file-name (pythonic-tramp-connection)))
194- (path (s-split path-separator (pythonic-get-path-variable-tramp))))
195- (tramp-set-connection-property vec " remote-path" path)
196- (tramp-set-remote-path vec)))
197-
198- (defun pythonic-set-extra-variables ()
199- " Set environment variables according to `python-shell-process-environment' ."
200- (dolist (env python-shell-process-environment)
201- (let ((env (s-split " =" env)))
202- (setenv (car env) (cadr env)))))
203-
204- (defun pythonic-set-extra-variables-tramp ()
205- " Set remote environment variables from `python-shell-process-environment' ."
206- (dolist (env python-shell-process-environment)
207- (tramp-send-command
208- (tramp-dissect-file-name (pythonic-tramp-connection))
209- (format " export %s " env))))
84+ (defun pythonic-remote-connection ()
85+ " Tramp connection string or nil."
86+ (when (pythonic-remote-p)
87+ (substring default-directory 0 (- (length default-directory)
88+ (length (pythonic-local-file-name default-directory))))))
21089
211- (cl-defun call-pythonic (&key file buffer display args cwd )
90+ (cl-defun pythonic- call-process (&key file buffer display args cwd )
21291 " Pythonic wrapper around `call-process' .
21392
21493FILE is the input file. BUFFER is the output destination. DISPLAY
21594specifies to redisplay BUFFER on new output. ARGS is the list of
21695arguments passed to `call-process' . CWD will be working directory
21796for running process."
218- (let ((default-directory (pythonic-default-directory cwd))
219- (process-environment (copy-sequence process-environment)))
220- (pythonic-set-process-environment)
221- (apply 'process-file (pythonic-executable) file buffer display args)))
97+ (let ((default-directory (pythonic-real-directory-name (or cwd " ~" ))))
98+ (python-shell-with-environment
99+ (apply 'process-file python-shell-interpreter file buffer display args))))
222100
223- (cl-defun start-pythonic (&key process buffer args cwd filter sentinel (query-on-exit t ))
101+ (cl-defun pythonic- start-process (&key process buffer args cwd filter sentinel (query-on-exit t ))
224102 " Pythonic wrapper around `start-process' .
225103
226104PROCESS is a name of the created process. BUFFER is a output
@@ -230,49 +108,28 @@ process. FILTER must be a symbol of process filter function if
230108necessary. SENTINEL must be a symbol of process sentinel
231109function if necessary. QUERY-ON-EXIT will be corresponding
232110process flag."
233- (let ((default-directory (pythonic-default-directory cwd))
234- (process-environment (copy-sequence process-environment))
235- (buffer (and buffer (get-buffer-create buffer))))
236- (pythonic-set-process-environment)
237- (let ((process (apply 'start-file-process process buffer (pythonic-executable) args)))
238- (when filter
239- (set-process-filter process filter))
240- (when sentinel
241- (set-process-sentinel process sentinel))
242- (set-process-query-on-exit-flag process query-on-exit)
243- (process-put process
244- 'pythonic
245- (list
246- :executable (pythonic-executable)
247- :connection (pythonic-tramp-connection)
248- :pythonpath (pythonic-get-pythonpath)
249- :path (pythonic-get-path)
250- :environment python-shell-process-environment))
251- process)))
252-
253- (defun pythonic-proper-environment-p (process )
254- " Determine if python environment has been changed since PROCESS was started."
255- (--if-let (process-get process 'pythonic )
256- (and
257- (equal (plist-get it :executable ) (pythonic-executable))
258- (equal (plist-get it :connection ) (pythonic-tramp-connection))
259- (equal (plist-get it :pythonpath ) (pythonic-get-pythonpath))
260- (equal (plist-get it :path ) (pythonic-get-path))
261- (equal (plist-get it :environment ) python-shell-process-environment))
262- (error " Process %s wasn't started with `start-pythonic' "
263- (process-name process))))
111+ (let ((default-directory (pythonic-real-directory-name (or cwd " ~" ))))
112+ (python-shell-with-environment
113+ (let ((process (apply 'start-file-process process buffer python-shell-interpreter args)))
114+ (when filter
115+ (set-process-filter process filter))
116+ (when sentinel
117+ (set-process-sentinel process sentinel))
118+ (set-process-query-on-exit-flag process query-on-exit)
119+ process))))
264120
265121;;;### autoload
266122(defun pythonic-activate (virtualenv )
267123 " Activate python VIRTUALENV."
268124 (interactive " DEnv: " )
269- (setq pythonic-environment virtualenv))
125+ (setq python-shell-virtualenv-root
126+ (pythonic-local-file-name (pythonic-real-directory-name virtualenv))))
270127
271128;;;### autoload
272129(defun pythonic-deactivate ()
273130 " Deactivate python virtual environment."
274131 (interactive )
275- (setq pythonic-environment nil ))
132+ (setq python-shell-virtualenv-root nil ))
276133
277134(provide 'pythonic )
278135
0 commit comments