📄 psvn.el
字号:
(if (not (fboundp 'puthash))
(defalias 'puthash 'cl-puthash))
;;;###autoload
(defun svn-status (dir &optional arg)
"Examine the status of Subversion working copy in directory DIR.
If ARG then pass the -u argument to `svn status'."
(interactive (list (read-directory-name "SVN status directory: "
nil default-directory nil)))
(unless (file-directory-p dir)
(error "%s is not a directory" dir))
(if (not (file-exists-p (concat dir "/.svn/")))
(when (y-or-n-p
(concat dir
" does not seem to be a Subversion working copy (no .svn directory). "
"Run dired instead? "))
(dired dir))
(setq dir (file-name-as-directory dir))
(setq svn-status-directory-history (delete dir svn-status-directory-history))
(add-to-list 'svn-status-directory-history dir)
(unless (string= (buffer-name) "*svn-status*")
(message "psvn: Saving initial window configuration")
(setq svn-status-initial-window-configuration (current-window-configuration)))
(let* ((status-buf (get-buffer-create "*svn-status*"))
(proc-buf (get-buffer-create "*svn-process*")))
(save-excursion
(set-buffer status-buf)
(setq default-directory dir)
(set-buffer proc-buf)
(setq default-directory dir)
(if arg
(svn-run-svn t t 'status "status" "-vu")
(svn-run-svn t t 'status "status" "-v"))))))
(defun svn-status-use-history ()
(interactive)
(let* ((hist svn-status-directory-history)
(dir (read-from-minibuffer "svn-status on directory: "
(cadr svn-status-directory-history)
nil nil 'hist)))
(when (file-directory-p dir)
(svn-status dir))))
(defun svn-run-svn (run-asynchron clear-process-buffer cmdtype &rest arglist)
"Run svn with arguments ARGLIST.
If RUN-ASYNCHRON is t then run svn asynchronously.
If CLEAR-PROCESS-BUFFER is t then erase the contents of the
*svn-process* buffer before commencing.
CMDTYPE is a symbol such as 'mv, 'revert, or 'add, representing the
command to run.
ARGLIST is a list of arguments \(which must include the command name,
for example: '(\"revert\" \"file1\"\)"
(if (eq (process-status "svn") nil)
(progn
(when svn-status-edit-svn-command
(setq arglist (append arglist
(split-string
(read-from-minibuffer
(format "svn %s %S " cmdtype arglist)))))
(when (eq svn-status-edit-svn-command t)
(svn-status-toggle-edit-cmd-flag t))
(message "svn-run-svn %s: %S" cmdtype arglist))
(let* ((proc-buf (get-buffer-create "*svn-process*"))
(svn-proc))
(when (listp (car arglist))
(setq arglist (car arglist)))
(save-excursion
(set-buffer proc-buf)
(setq buffer-read-only nil)
(fundamental-mode)
(if clear-process-buffer
(delete-region (point-min) (point-max))
(goto-char (point-max)))
(setq svn-process-cmd cmdtype)
(setq svn-status-mode-line-process-status (format " running %s" cmdtype))
(svn-status-update-mode-line)
(sit-for 0.1)
(if run-asynchron
(progn
(setq svn-proc (apply 'start-process "svn" proc-buf "svn" arglist))
(set-process-sentinel svn-proc 'svn-process-sentinel))
;;(message "running synchron: svn %S" arglist)
(apply 'call-process "svn" nil proc-buf nil arglist)
(setq svn-status-mode-line-process-status "")
(svn-status-update-mode-line)))))
(error "You can only run one svn process at once!")))
(defun svn-process-sentinel (process event)
;;(princ (format "Process: %s had the event `%s'" process event)))
;;(save-excursion
(let ((act-buf (current-buffer)))
(set-buffer (process-buffer process))
(setq svn-status-mode-line-process-status "")
(svn-status-update-mode-line)
(cond ((string= event "finished\n")
(cond ((eq svn-process-cmd 'status)
;;(message "svn status finished")
(if (eq system-type 'windows-nt)
;; convert path separator as UNIX style
(save-excursion
(goto-char (point-min))
(while (search-forward "\\" nil t)
(replace-match "/"))))
(svn-parse-status-result)
(set-buffer act-buf)
(svn-status-update-buffer)
(when svn-status-update-previous-process-output
(set-buffer (process-buffer process))
(delete-region (point-min) (point-max))
(insert "Output from svn command:\n")
(insert svn-status-update-previous-process-output)
(goto-char (point-min))
(setq svn-status-update-previous-process-output nil)))
((eq svn-process-cmd 'log)
(svn-status-show-process-buffer-internal t)
(pop-to-buffer "*svn-process*")
(switch-to-buffer (get-buffer-create "*svn-log*"))
(let ((buffer-read-only nil))
(delete-region (point-min) (point-max))
(insert-buffer-substring "*svn-process*"))
(svn-log-view-mode)
(goto-char (point-min))
(forward-line 3)
(font-lock-fontify-buffer)
(message "svn log finished"))
((eq svn-process-cmd 'info)
(svn-status-show-process-buffer-internal t)
(message "svn info finished"))
((eq svn-process-cmd 'parse-info)
(svn-status-parse-info-result))
((eq svn-process-cmd 'blame)
(svn-status-show-process-buffer-internal t)
(message "svn blame finished"))
((eq svn-process-cmd 'commit)
(svn-status-remove-temp-file-maybe)
(svn-status-show-process-buffer-internal t)
(when (member 'commit svn-status-unmark-files-after-list)
(svn-status-unset-all-usermarks))
(svn-status-update)
(message "svn commit finished"))
((eq svn-process-cmd 'update)
(svn-status-show-process-buffer-internal t)
(svn-status-update)
(message "svn update finished"))
((eq svn-process-cmd 'add)
(svn-status-update)
(message "svn add finished"))
((eq svn-process-cmd 'mkdir)
(svn-status-update)
(message "svn mkdir finished"))
((eq svn-process-cmd 'revert)
(when (member 'revert svn-status-unmark-files-after-list)
(svn-status-unset-all-usermarks))
(svn-status-update)
(message "svn revert finished"))
((eq svn-process-cmd 'mv)
(svn-status-update)
(message "svn mv finished"))
((eq svn-process-cmd 'rm)
(svn-status-update)
(message "svn rm finished"))
((eq svn-process-cmd 'cleanup)
(message "svn cleanup finished"))
((eq svn-process-cmd 'proplist)
(svn-status-show-process-buffer-internal t)
(message "svn proplist finished"))
((eq svn-process-cmd 'proplist-parse)
(svn-status-property-parse-property-names))
((eq svn-process-cmd 'propset)
(svn-status-remove-temp-file-maybe)
(svn-status-update))
((eq svn-process-cmd 'propdel)
(svn-status-update))))
((string= event "killed\n")
(message "svn process killed"))
((string-match "exited abnormally" event)
(while (accept-process-output process 0 100))
;; find last error message and show it.
(goto-char (point-max))
(message "svn failed: %s"
(if (re-search-backward "^svn: \\(.*\\)" nil t)
(match-string 1)
event)))
(t
(message "svn process had unknown event: %s" event))
(svn-status-show-process-buffer-internal t))))
(defun svn-parse-rev-num (str)
(if (and str (stringp str)
(save-match-data (string-match "^[0-9]+" str)))
(string-to-number str)
-1))
(defun svn-parse-status-result ()
"Parse the *svn-process* buffer.
The results are used to build the `svn-status-info' variable."
(setq svn-status-head-revision nil)
(save-excursion
(let ((old-ui-information (svn-status-ui-information-hash-table))
(line-string)
(user-mark)
(svn-marks)
(svn-file-mark)
(svn-property-mark)
(svn-update-mark)
(local-rev)
(last-change-rev)
(author)
(path)
(user-elide nil)
(ui-status '(nil nil)) ; contains (user-mark user-elide)
(revision-width svn-status-default-revision-width)
(author-width svn-status-default-author-width))
(set-buffer "*svn-process*")
(setq svn-status-info nil)
(goto-char (point-min))
(while (< (point) (point-max))
(cond
((= (point-at-eol) (point-at-bol)) ;skip blank lines
nil)
((or (looking-at "Head revision:[ ]+\([0-9]+\)") ;svn version < 0.29
(looking-at "Status against revision:[ ]+\([0-9]+\)")); svn version >= 0.29
;; the above message appears for the main listing plus once for each svn:externals entry
(unless svn-status-head-revision
(setq svn-status-head-revision (match-string 1))))
((looking-at "Performing status on external item at '\(.*\)'")
;; The *next* line has info about the directory named in svn:externals
;; we should parse it, and merge the info with what we have already know
;; but for now just ignore the line completely
(forward-line)
)
(t
(setq svn-marks (buffer-substring (point) (+ (point) 8))
svn-file-mark (elt svn-marks 0) ; 1st column
svn-property-mark (elt svn-marks 1) ; 2nd column
;;svn-locked-mark (elt svn-marks 2) ; 3rd column
;;svn-added-with-history-mark (elt svn-marks 3); 4th column
;;svn-switched-mark (elt svn-marks 4) ; 5th column
svn-update-mark (elt svn-marks 7)) ; 8th column
(when (eq svn-property-mark ?\ ) (setq svn-property-mark nil))
(when (eq svn-update-mark ?\ ) (setq svn-update-mark nil))
(forward-char 8)
(skip-chars-forward " ")
(cond
((looking-at "\\([-?]\\|[0-9]+\\) +\\([-?]\\|[0-9]+\\) +\\([^ ]+\\) *\\(.+\\)")
(setq local-rev (svn-parse-rev-num (match-string 1))
last-change-rev (svn-parse-rev-num (match-string 2))
author (match-string 3)
path (match-string 4)))
((looking-at "\\(.*\\)")
(setq path (match-string 1)
local-rev -1
last-change-rev -1
author (if (eq svn-file-mark 88) "" "?"))) ;clear author of svn:externals dirs
(t
(error "Unknown status line format")))
(unless path (setq path "."))
(setq ui-status (or (gethash path old-ui-information) (list user-mark user-elide)))
(setq svn-status-info (cons (list ui-status
svn-file-mark
svn-property-mark
path
local-rev
last-change-rev
author
svn-update-mark)
svn-status-info))
(setq revision-width (max revision-width
(length (number-to-string local-rev))
(length (number-to-string last-change-rev))))
(setq author-width (max author-width (length author)))))
(forward-line 1))
;; With subversion 0.29.0 and above, `svn -u st' returns files in
;; a random order (especially if we have a mixed revision wc)
(setq svn-status-default-column
(+ 6 revision-width revision-width author-width
(if svn-status-short-mod-flag-p 3 0)))
(setq svn-status-line-format (format " %%c%%c %%%ds %%%ds %%-%ds"
revision-width
revision-width
author-width))
(setq svn-status-info (sort svn-status-info 'svn-status-sort-predicate)))))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -