3232(require 's )
3333(require 'f )
3434
35+
36+ ; ;; Connection predicates.
37+
38+ (defun pythonic-local-p ()
39+ " Determine local virtual environment."
40+ (not (pythonic-remote-p)))
41+
3542(defun pythonic-remote-p ()
36- " Determine remote or local virtual environment."
37- (tramp-tramp-file-p default-directory))
43+ " Determine remote virtual environment."
44+ (tramp-tramp-file-p (pythonic-aliased-path default-directory) ))
3845
3946(defun pythonic-remote-docker-p ()
4047 " Determine docker remote virtual environment."
4148 (and (pythonic-remote-p)
42- (s-starts-with-p " /docker: " (pythonic-remote-connection) )))
49+ (s-equals-p (pythonic-remote-method) " docker " )))
4350
4451(defun pythonic-remote-vagrant-p ()
4552 " Determine vagrant remote virtual environment."
4653 (and (pythonic-remote-p)
4754 (s-equals-p (pythonic-remote-host) " localhost" )
4855 (s-equals-p (pythonic-remote-user) " vagrant" )))
4956
57+
58+ ; ;; Connection properties.
59+
60+ (defun pythonic-remote-method ()
61+ " Get tramp method of the connection to the remote python interpreter."
62+ (tramp-file-name-method (tramp-dissect-file-name (pythonic-aliased-path default-directory))))
63+
5064(defun pythonic-remote-user ()
5165 " Get user of the connection to the remote python interpreter."
52- (tramp-file-name-user (tramp-dissect-file-name (pythonic-remote-connection ))))
66+ (tramp-file-name-user (tramp-dissect-file-name (pythonic-aliased-path default-directory ))))
5367
5468(defun pythonic-remote-host ()
5569 " Get host of the connection to the remote python interpreter."
56- (replace-regexp-in-string
57- " #.*\\ '" " "
58- (tramp-file-name-host (tramp-dissect-file-name (pythonic-remote-connection)))))
70+ (let ((hostname (tramp-file-name-host (tramp-dissect-file-name (pythonic-aliased-path default-directory)))))
71+ (replace-regexp-in-string " #.*\\ '" " " hostname)))
5972
6073(defun pythonic-remote-port ()
6174 " Get port of the connection to the remote python interpreter."
62- (let ((hostname (tramp-file-name-host (tramp-dissect-file-name (pythonic-remote-connection )))))
75+ (let ((hostname (tramp-file-name-host (tramp-dissect-file-name (pythonic-aliased-path default-directory )))))
6376 (when (s-contains-p " #" hostname)
6477 (string-to-number (replace-regexp-in-string " \\ `.*#" " " hostname)))))
6578
66- (defun pythonic-local-file-name (file )
67- " Local FILE name with out tramp prefix."
68- (if (tramp-tramp-file-p file)
69- (tramp-file-name-localname (tramp-dissect-file-name file))
70- file))
71-
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))
78-
79- (defun pythonic-real-directory-name (directory )
80- " Generate `default-directory' FROM-DIRECTORY."
81- (let ((default-directory (pythonic-real-file-name directory)))
82- (f-full default-directory)))
83-
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))))))
79+
80+ ; ;; File names.
81+
82+ (defvar pythonic-directory-aliases nil )
83+
84+ (defun pythonic-aliased-path (path )
85+ " Get aliased PATH."
86+ (let ((alias-tuple (cl-find-if
87+ (lambda (it )
88+ (or (f-same-p (car it) path)
89+ (f-ancestor-of-p (car it) path)))
90+ pythonic-directory-aliases)))
91+ (if (null alias-tuple)
92+ path
93+ (concat (cadr alias-tuple)
94+ (substring path (length (car alias-tuple)))))))
95+
96+ (defun pythonic-unaliased-path (alias )
97+ " Get real path from ALIAS."
98+ (let ((alias-tuple (cl-find-if
99+ (lambda (it )
100+ (or (f-same-p (cadr it) alias)
101+ (f-ancestor-of-p (cadr it) alias)))
102+ pythonic-directory-aliases)))
103+ (if (null alias-tuple)
104+ alias
105+ (concat (car alias-tuple)
106+ (substring alias (length (cadr alias-tuple)))))))
107+
108+ (defun pythonic-python-readable-file-name (filename )
109+ " Emacs to Python FILENAME conversion.
110+ Take FILENAME from the perspective of the localhost and translate
111+ it to the FILENAME Python process can read. Python can be
112+ running locally or remotely. FILENAME can have local or tramp
113+ format. Result will have local format."
114+ (let ((alias (pythonic-aliased-path filename)))
115+ (if (tramp-tramp-file-p alias)
116+ (tramp-file-name-localname (tramp-dissect-file-name alias))
117+ alias)))
118+
119+ (defun pythonic-emacs-readable-file-name (filename )
120+ " Python to Emacs FILENAME conversion.
121+ Take FILENAME from the perspective of the python interpreter and
122+ translate it to the FILENAME Emacs `find-file' command can
123+ understand. Python can be running locally or remotely. FILENAME
124+ should have local format. Result can have local or tramp
125+ format."
126+ (when (tramp-tramp-file-p filename)
127+ (error " %s can not be tramp path" filename))
128+ (if (pythonic-remote-p)
129+ (let* ((directory (pythonic-aliased-path default-directory))
130+ (connection (substring directory 0
131+ (- (length directory)
132+ (length (tramp-file-name-localname (tramp-dissect-file-name directory)))))))
133+ (pythonic-unaliased-path (concat connection filename)))
134+ filename))
135+
136+
137+ ; ;; Processes.
89138
90139(cl-defun pythonic-call-process (&key file buffer display args cwd )
91140 " Pythonic wrapper around `call-process' .
@@ -94,7 +143,7 @@ FILE is the input file. BUFFER is the output destination. DISPLAY
94143specifies to redisplay BUFFER on new output. ARGS is the list of
95144arguments passed to `call-process' . CWD will be working directory
96145for running process."
97- (let ((default-directory (pythonic-real-directory-name (or cwd " ~ " ))))
146+ (let ((default-directory (pythonic-aliased-path (or cwd default-directory ))))
98147 (python-shell-with-environment
99148 (apply 'process-file python-shell-interpreter file buffer display args))))
100149
@@ -108,7 +157,7 @@ process. FILTER must be a symbol of process filter function if
108157necessary. SENTINEL must be a symbol of process sentinel
109158function if necessary. QUERY-ON-EXIT will be corresponding
110159process flag."
111- (let ((default-directory (pythonic-real-directory-name (or cwd " ~ " ))))
160+ (let ((default-directory (pythonic-aliased-path (or cwd default-directory ))))
112161 (python-shell-with-environment
113162 (let ((process (apply 'start-file-process process buffer python-shell-interpreter args)))
114163 (when filter
@@ -118,12 +167,14 @@ process flag."
118167 (set-process-query-on-exit-flag process query-on-exit)
119168 process))))
120169
170+
171+ ; ;; Commands.
172+
121173;;;### autoload
122174(defun pythonic-activate (virtualenv )
123175 " Activate python VIRTUALENV."
124176 (interactive " DEnv: " )
125- (setq python-shell-virtualenv-root
126- (pythonic-local-file-name (pythonic-real-directory-name virtualenv))))
177+ (setq python-shell-virtualenv-root (pythonic-python-readable-file-name virtualenv)))
127178
128179;;;### autoload
129180(defun pythonic-deactivate ()
0 commit comments