-
Notifications
You must be signed in to change notification settings - Fork 0
/
mistilteinn.el
267 lines (230 loc) · 8.09 KB
/
mistilteinn.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
;;; mistilteinn.el --- minor-mode for mistilteinn
;;; -*- coding: utf-8 -*-
;;
;;; Install:
;;
;; (1) Install mistilteinn system by rubygems.
;;
;; gem install mistilteinn
;;
;; (2) Copy this file to load-path
;;
;; (3) Add following code to .emacs
;;
;; (add-to-list 'load-path "~/workspaces/mistilteinn/")
;; (require 'mistilteinn)
;; ;; for minor mode
;; (global-mistilteinn-mode t)
;; ;; for anything
;; (defun anything-for-mistiltein ()
;; (interactive)
;; (anything-other-buffer
;; '(anything-c-source-git-ticket) "*mistiltein*"))
;; (define-key global-map (kbd "C-t") 'anything-for-mistiltein))
;;
;;; Setup for each project:
;;
;; To use mistilteinn, run `mistilteinn init` at each project dirctory.
;;
;; $ cd /path/to/project
;; $ git init
;; $ mistilteinn init
;; $ vim .mistilteinn/config.yaml
;;
;;; Web sites:
;;
;; stable verison: http://www.emacswiki.org/cgi-bin/wiki?mistilteinn.el
;; development version: https://github.com/mistilteinn/mistilteinn-emacs
;; mistilteinn website: http://mistilteinn.github.com
;;
;;; Author:
;;
;; @mzp
;; @mallowlabs
;; @suer
;;
;;; License:
;;
;; mistilteinn.el is free software; you can redistribute it and/or modify
;; it under the terms of MIT License.
;;; Code:
(require 'cl)
;;;; configure
;;; The definition of mistilteinn.
(defgroup mistilteinn nil
"New style development with git and emacs"
:group 'tools)
(defcustom mistilteinn-exclude-modes '(dummy1-mode dummy2-mode)
"Major modes `mistilteinn-minor-mode' cannot run."
:type '(list symbol)
:group 'mistilteinn)
(defcustom mistilteinn-inactive-ticket-regexp "\\[解決\\]"
"A regexp for inactive ticket regexp"
:type 'string
:group 'mistilteinn)
(defcustom mistilteinn-info-buffer "*mistilteinn-info*"
"Buffer name for information"
:type 'string
:group 'mistilteinn)
(defcustom mistilteinn-message-buffer "*mistilteinn-message*"
"Buffer name for message"
:type 'string
:group 'mistilteinn)
(defcustom mistilteinn-diff-buffer "*mistilteinn-diff*"
"Buffer name for diff"
:type 'string
:group 'mistilteinn)
(defface mistilteinn-inactive-ticket-face
'((t (:foreground "blue")))
"*Face used for inactive ticket"
:group 'mistilteinn)
(defface mistilteinn-active-ticket-face
'()
"*Face used for active ticket"
:group 'mistilteinn)
;;;; message buffer function
;;; Create message buffer and popup for user to input commit message etc.
(defun mi:close-message-buffer ()
"Close current message buffer."
(interactive)
(kill-buffer (current-buffer)))
(defun mi:strip-comment (s)
"strip comment heading #"
(replace-regexp-in-string "^#.*\n" "" s))
(defvar mi:commit (lambda () nil))
(make-variable-buffer-local 'mi:commit)
(defun mi:commit-message-buffer ()
"Commit current message buffer."
(interactive)
(funcall mi:commit (mi:strip-comment (buffer-string)))
(mi:close-message-buffer))
(defvar mi:message-keymap
(make-sparse-keymap)
"A keymap for message buffer. ")
(define-key mi:message-keymap (kbd "C-c C-c") 'mi:commit-message-buffer)
(define-key mi:message-keymap (kbd "C-c C-q") 'mi:close-message-buffer)
(defconst mi:message-help
"
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
")
(defconst mi:message-font-locks
'(("^\\(#.*\\)$" (1 font-lock-comment-face t)) ;; highlight comment
))
(defun mi:show-message-buffer (f)
"Show message buffer and callback `f' when user input is completed."
(let ((buffer (generate-new-buffer mistilteinn-message-buffer)))
(with-current-buffer buffer
;; restore window configure at kill buffer
(add-hook 'kill-buffer-hook
(lexical-let ((wc (current-window-configuration)))
#'(lambda ()
(set-window-configuration wc))) nil t)
(setq mi:commit f)
;; set keybind
(use-local-map mi:message-keymap)
;; set fontlock
(font-lock-add-keywords nil mi:message-font-locks)
(when global-font-lock-mode (font-lock-mode t))
;; add help message
(insert "# C-c C-c: commit; C-c C-q: close buffer\n")
(save-excursion (insert mi:message-help)))
(pop-to-buffer buffer)))
;;;; git command
(defun mistilteinn-git-now ()
"run git-now to create temporary commit"
(interactive)
(shell-command "git now --compact | head -1"))
(defun mi:git-now ()
(interactive)
(when mistilteinn-minor-mode
(mistilteinn-git-now)))
(defun mi:branch-list ()
"Get branch list for current repository."
(remove-if '(lambda (s) (string= "" s))
(mapcar '(lambda (s) (replace-regexp-in-string "^*? *" "" s))
(split-string (shell-command-to-string "git branch")
"\n"))))
(defun mistilteinn-git-master ()
"run git-master to masterize current topic branch"
(interactive)
(let* ((branch (completing-read "git-master (default master): " (mi:branch-list) nil nil "master" nil "master"))
(cmd (format "git master %s" branch)))
(shell-command cmd)))
(defun mistilteinn-git-ticket-create (subject)
"Create ticket."
(interactive "sSubject: ")
(shell-command (format "mistilteinn create \"%s\"" subject)))
(defun mi:git-fixup (s)
(shell-command (format "git now --fixup \"%s\"" s)))
(defun mi:git-diff (buf)
(shell-command "git now --diff" buf))
(defun mistilteinn-git-fixup ()
"run git-now --fixup to fixup now commit"
(interactive)
(mi:show-message-buffer 'mi:git-fixup))
(defun mistilteinn-git-diff ()
(interactive)
(when (buffer-live-p mistilteinn-diff-buffer)
(kill-buffer mistilteinn-diff-buffer))
(with-current-buffer (get-buffer-create mistilteinn-diff-buffer)
(diff-mode)
(mi:git-diff (current-buffer))))
;;;; anything
(defun mi:switch-topic-branch (str)
(let ((id (car (split-string str " "))))
(shell-command
(format "mistilteinn switch %s" id)
"*git-ticket*")))
(defun mi:highlight-ticket (tickets)
(loop for ticket in tickets
collect
(cond
((string-match mistilteinn-inactive-ticket-regexp ticket) (propertize ticket 'face 'mistilteinn-inactive-ticket-face))
(t (propertize ticket 'face 'mistilteinn-active-ticket-face)))))
(defvar anything-c-source-git-ticket
'((name . "Tickets")
(candidates-in-buffer)
(candidate-transformer mi:highlight-ticket)
(init . (lambda () (call-process-shell-command "mistilteinn list" nil (anything-candidate-buffer 'git-ticket))))
(action ("Switch topic branch" . mi:switch-topic-branch))))
;;;; minor mode
(defconst mistilteinn-minor-mode-map (make-sparse-keymap)
"Keymap for the mistilteinn minor mode.")
(define-key mistilteinn-minor-mode-map (kbd "C-c # c") 'mistilteinn-git-ticket-create)
(define-key mistilteinn-minor-mode-map (kbd "C-c # m") 'mistilteinn-git-master)
(define-key mistilteinn-minor-mode-map (kbd "C-c # n") 'mistilteinn-git-now)
(define-key mistilteinn-minor-mode-map (kbd "C-c # f") 'mistilteinn-git-fixup)
(define-key mistilteinn-minor-mode-map (kbd "C-c # d") 'mistilteinn-git-diff)
(define-minor-mode mistilteinn-minor-mode
"mistilteinn"
:lighter " mi"
:keymap mistilteinn-minor-mode-map
:group mistilteinn-mode
(funcall (if mistilteinn-minor-mode 'add-hook 'remove-hook)
'after-save-hook
'mi:git-now))
(defmacro mi:with-cd (path &rest body)
(let ((var (make-symbol "path")))
`(let ((,var default-directory))
(unwind-protect
(progn
(cd ,path)
,@body)
(cd ,var)))))
(defun mi:inside-p (path)
(and (file-exists-p path)
(file-directory-p path)
(mi:with-cd path
(equal "0"
(shell-command-to-string "mistilteinn is-inside; echo -n $?")))))
(defun mi:mode-switch ()
"Return t and enable mistilteinn-minor-mode if `mistilteinn-minor-mode' can called on current buffer."
(when (and (not (minibufferp (current-buffer)))
(not (memq major-mode mistilteinn-exclude-modes))
(mi:inside-p "."))
(mistilteinn-minor-mode t)))
(define-global-minor-mode global-mistilteinn-mode
mistilteinn-minor-mode mi:mode-switch)
(provide 'mistilteinn)
;;; mistilteinn.el ends here.