-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathisortify.el
138 lines (119 loc) · 4.82 KB
/
isortify.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
;;; isortify.el --- (automatically) format python buffers using isort
;; Copyright (C) 2016-2018 Artem Malyshev
;; Author: Artem Malyshev <[email protected]>
;; Homepage: https://github.com/proofit404/isortify
;; Version: 0.0.1
;; Package-Requires: ((emacs "25") (pythonic "0.1.0"))
;; Keywords: convenience isort
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published
;; by the Free Software Foundation; either version 3, or (at your
;; option) any later version.
;;
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; For a full copy of the GNU General Public License
;; see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; Isortify uses isort to format a Python buffer. It can be called
;; explicitly on a certain buffer, but more conveniently, a minor-mode
;; 'isortify-mode' is provided that turns on automatically running isort
;; on a buffer before saving.
;;
;; Installation:
;;
;; Add isortify.el to your load-path.
;;
;; To automatically format all Python buffers before saving, add the function
;; isortify-mode to python-mode-hook:
;;
;; (add-hook 'python-mode-hook 'isortify-mode)
;;
;;; Code:
(require 'pythonic)
(defvar isortify-multi-line-output nil)
(defvar isortify-trailing-comma nil)
(defvar isortify-known-first-party nil)
(defvar isortify-known-third-party nil)
(defvar isortify-lines-after-imports nil)
(defvar isortify-line-width nil)
(defun isortify-call-bin (input-buffer output-buffer)
"Call process isort on INPUT-BUFFER saving the output to OUTPUT-BUFFER.
Return isort process the exit code."
(with-current-buffer input-buffer
(let ((process
(pythonic-start-process :process "isortify"
:buffer output-buffer
:sentinel (lambda (process event))
:args `("-m" "isort" ,@(isortify-call-args)))))
(process-send-region process (point-min) (point-max))
(process-send-eof process)
(process-send-eof process) ;; Close pipe twice on purpose to prevent deadlock.
(accept-process-output process nil nil t)
(while (process-live-p process)
(accept-process-output process nil nil t))
(process-exit-status process))))
(defun isortify-call-args ()
"Collect CLI arguments for isort process."
(let (args)
(when (string= "ipython" python-shell-interpreter)
(push "--" args))
(when isortify-multi-line-output
(push "--multi-line" args)
(push (number-to-string isortify-multi-line-output) args))
(when isortify-trailing-comma
(push "--trailing-comma" args))
(when isortify-known-first-party
(dolist (project isortify-known-first-party)
(push "--project" args)
(push project args)))
(when isortify-known-third-party
(dolist (thirdparty isortify-known-third-party)
(push "--thirdparty" args)
(push thirdparty args)))
(when isortify-lines-after-imports
(push "--lines-after-imports" args)
(push (number-to-string isortify-lines-after-imports) args))
(when isortify-line-width
(push "--line-width" args)
(push (number-to-string isortify-line-width) args))
(push "-" args)
(reverse args)))
;;;###autoload
(defun isortify-buffer (&optional display)
"Try to isortify the current buffer.
Show isort output, if isort exit abnormally and DISPLAY is t."
(interactive (list t))
(let* ((original-buffer (current-buffer))
(original-point (point))
(original-window-pos (window-start))
(tmpbuf (get-buffer-create "*isortify*")))
;; This buffer can be left after previous isort invocation. It
;; can contain error message of the previous run.
(with-current-buffer tmpbuf
(erase-buffer))
(condition-case err
(if (not (zerop (isortify-call-bin original-buffer tmpbuf)))
(error "Isort failed, see %s buffer for details" (buffer-name tmpbuf))
(with-current-buffer tmpbuf
(ansi-color-filter-region (point-min) (point-max))
(copy-to-buffer original-buffer (point-min) (point-max)))
(kill-buffer tmpbuf)
(goto-char original-point)
(set-window-start (selected-window) original-window-pos))
(error (message "%s" (error-message-string err))
(when display
(pop-to-buffer tmpbuf))))))
;;;###autoload
(define-minor-mode isortify-mode
"Automatically run isort before saving."
:lighter " Isort"
(if isortify-mode
(add-hook 'before-save-hook 'isortify-buffer nil t)
(remove-hook 'before-save-hook 'isortify-buffer t)))
(provide 'isortify)
;;; isortify.el ends here