debian-changelog-mode.el 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. ;; debian-changelog.el --- change log maintenance for Debian-style changelogs
  2. ;; Keywords: maint
  3. ;; Copyright (C) 1996 Ian Jackson
  4. ;; Copyright (C) 1997 Klee Dienes
  5. ;; This file is part of dpkg.
  6. ;;
  7. ;; It is free software; you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation; either version 2, or (at your option)
  10. ;; any later version.
  11. ;;
  12. ;; dpkg is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;;
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with your Debian installation, in /usr/share/common-licenses/GPL.
  19. ;; If not, write to the Free Software Foundation, 675 Mass Ave,
  20. ;; Cambridge, MA 02139, USA.
  21. (require 'add-log)
  22. (defun debian-changelog-setheadervalue (re str)
  23. (let (a b v k
  24. (lineend (save-excursion (end-of-line) (point))))
  25. (save-excursion
  26. (goto-char (point-min))
  27. (re-search-forward re lineend)
  28. (setq a (match-beginning 1)
  29. b (match-end 1))
  30. (goto-char a)
  31. (delete-region a b)
  32. (insert str))))
  33. (defun debian-changelog-getheadervalue (re)
  34. (let ((lineend (save-excursion (end-of-line) (point))))
  35. (save-excursion
  36. (goto-char (point-min))
  37. (re-search-forward re lineend)
  38. (buffer-substring-no-properties (match-beginning 1) (match-end 1)))))
  39. (defvar debian-changelog-mode-map nil
  40. "Keymap for Debian changelog major mode.")
  41. (if debian-changelog-mode-map
  42. nil
  43. (setq debian-changelog-mode-map (make-sparse-keymap))
  44. (define-key debian-changelog-mode-map "\C-c\C-a" 'debian-changelog-add-entry)
  45. (define-key debian-changelog-mode-map "\C-c\C-f"
  46. 'debian-changelog-finalise-last-version)
  47. (define-key debian-changelog-mode-map "\C-c\C-c" 'debian-changelog-finalise-and-save)
  48. (define-key debian-changelog-mode-map "\C-c\C-v" 'debian-changelog-add-version)
  49. (define-key debian-changelog-mode-map "\C-c\C-d" 'debian-changelog-distribution)
  50. (define-key debian-changelog-mode-map "\C-c\C-u" 'debian-changelog-urgency)
  51. (define-key debian-changelog-mode-map "\C-c\C-e"
  52. 'debian-changelog-unfinalise-last-version))
  53. (defun debian-changelog-add-entry ()
  54. "Add a new change entry to a debian-style changelog."
  55. (interactive)
  56. (if (eq (debian-changelog-finalised-p) t)
  57. (error (substitute-command-keys "most recent version has been finalised - use \\[debian-changelog-unfinalise-last-version] or \\[debian-changelog-add-version]")))
  58. (goto-char (point-min))
  59. (re-search-forward "\n --")
  60. (backward-char 5)
  61. (if (prog1 (looking-at "\n") (forward-char 1))
  62. nil
  63. (insert "\n"))
  64. (insert " * ")
  65. (save-excursion (insert "\n")))
  66. (defun debian-changelog-distribution (arg)
  67. "Delete the current distribution and prompt for a new one."
  68. (interactive "P")
  69. (let* ((curstr
  70. (debian-changelog-getheadervalue ") \\(.*\\)\\;"))
  71. (str (completing-read
  72. "Select distribution: "
  73. '(("stable" 1)
  74. ("frozen" 2)
  75. ("unstable" 3)
  76. ("stable frozen unstable" 4)
  77. ("stable unstable frozen" 4)
  78. ("unstable stable frozen" 4)
  79. ("unstable frozen stable" 4)
  80. ("frozen unstable stable" 4)
  81. ("frozen stable unstable" 4)
  82. ("frozen unstable" 5)
  83. ("unstable frozen" 5)
  84. ("stable frozen" 6)
  85. ("frozen stable" 6)
  86. ("stable unstable" 7)
  87. ("unstable stable" 7))
  88. nil t nil)))
  89. (if (not (equal str ""))
  90. (debian-changelog-setheadervalue ") \\(.*\\)\\;" str))))
  91. (defun debian-changelog-urgency (arg)
  92. "Delete the current urgency and prompt for a new one."
  93. (interactive "P")
  94. (let* ((urgency-regex "\\;[^\n]* urgency=\\(\\sw+\\)")
  95. (curstr
  96. (debian-changelog-getheadervalue urgency-regex))
  97. (str (completing-read
  98. "Select urgency: "
  99. '(("low" 1) ("medium" 2) ("high" 3))
  100. nil t nil)))
  101. (if (not (equal str ""))
  102. (debian-changelog-setheadervalue urgency-regex str))))
  103. (defun debian-changelog-finalised-p ()
  104. "Check whether the most recent debian-style changelog entry is
  105. finalised yet (ie, has a maintainer name and email address and a
  106. release date."
  107. (save-excursion
  108. (goto-char (point-min))
  109. (if (re-search-forward "\n\\S-" (point-max) t)
  110. (progn
  111. (if (re-search-backward "\n --" (point-min) t)
  112. (forward-char 4)
  113. (beginning-of-line)
  114. (insert " --\n\n")
  115. (backward-char 2))
  116. (cond
  117. ((looking-at "[ \n]+\\S-[^\n\t]+\\S- <[^ \t\n<>]+> \\S-[^\t\n]+\\S-[ \t]*\n")
  118. t)
  119. ((looking-at "[ \t]*\n")
  120. nil)
  121. (t
  122. "finalisation line has bad format (not ` -- maintainer <email> date')")))
  123. t)))
  124. (defun debian-changelog-add-version ()
  125. "Add a new version section to a debian-style changelog file."
  126. (interactive)
  127. (let ((f (debian-changelog-finalised-p)))
  128. (and (stringp f) (error f))
  129. (or f (error "previous version not yet finalised")))
  130. (goto-char (point-min))
  131. (let ((headstring
  132. (if (looking-at "\\(\\S-+ ([^()\n\t ]*[^0-9\n\t()]\\)\\([0-9]+\\)\\()[^\n]*\\)")
  133. (concat (match-string 1)
  134. (number-to-string (+ 1 (string-to-number (match-string 2))))
  135. (match-string 3))
  136. (let ((pkg (read-string "Package name: "))
  137. (ver (read-string "New version (including any revision): ")))
  138. (concat pkg " (" ver ") unstable; urgency=low")))))
  139. (insert headstring "\n\n * ")
  140. (save-excursion
  141. (if (re-search-backward ") \\([^\n]*\\);[^\n]* urgency=\\(\\sw+\\)" (point-min) t)
  142. (progn (goto-char (match-beginning 2))
  143. (delete-region (point) (match-end 2))
  144. (insert "low")
  145. (goto-char (match-beginning 1))
  146. (delete-region (point) (match-end 1))
  147. (insert "unstable"))))
  148. (save-excursion (insert "\n\n --\n\n"))))
  149. (defun debian-changelog-finalise-and-save ()
  150. "Finalise, if necessary, and then save a debian-style changelog file."
  151. (interactive)
  152. (let ((f (debian-changelog-finalised-p)))
  153. (and (stringp f) (error f))
  154. (or f (debian-changelog-finalise-last-version)))
  155. (save-buffer))
  156. (defun debian-changelog-date-string ()
  157. "Return RFC-822 format date string"
  158. (let* ((dp "822-date")
  159. (cp (point))
  160. (ret (call-process "822-date" nil t))
  161. (np (point))
  162. (out nil))
  163. (cond ((not (or (eq ret nil) (eq ret 0)))
  164. (setq out (buffer-substring-no-properties cp np))
  165. (delete-region cp np)
  166. (error (concat "error from " dp ": " out)))
  167. (t
  168. (backward-char)
  169. (or (looking-at "\n")
  170. (error (concat "error from " dp ": expected newline after date string")))
  171. (setq out (buffer-substring-no-properties cp (- np 1)))
  172. (delete-region cp np)
  173. out))))
  174. (defun debian-changelog-finalise-last-version ()
  175. "Remove the `finalisation' information (maintainer's name and email
  176. address and release date) so that new entries can be made."
  177. (interactive)
  178. (or add-log-full-name (setq add-log-full-name (user-full-name)))
  179. (or add-log-mailing-address (setq add-log-mailing-address user-mail-address))
  180. (and (debian-changelog-finalised-p) (debian-changelog-unfinalise-last-version))
  181. (save-excursion
  182. (goto-char (point-min))
  183. (re-search-forward "\n --\\([ \t]*\\)")
  184. (delete-region (match-beginning 1) (match-end 1))
  185. (insert " " add-log-full-name " <" add-log-mailing-address "> "
  186. (debian-changelog-date-string))))
  187. (defun debian-changelog-unfinalise-last-version ()
  188. "Remove the `finalisation' information (maintainer's name and email
  189. address and release date) so that new entries can be made."
  190. (interactive)
  191. (if (debian-changelog-finalised-p) nil
  192. (error "most recent version is not finalised"))
  193. (save-excursion
  194. (goto-char (point-min))
  195. (re-search-forward "\n --")
  196. (let ((dels (point)))
  197. (end-of-line)
  198. (delete-region dels (point)))))
  199. (defun debian-changelog-mode ()
  200. "Major mode for editing Debian-style change logs.
  201. Runs `debian-changelog-mode-hook' if it exists.
  202. Key bindings:
  203. \\{debian-changelog-mode-map}
  204. Hint: If you want to use your debian.org email address for debian/changelog
  205. entries without using it for the rest of your email, put
  206. (add-hook 'debian-changelog-mode-hook 'my-debian-changelog-mode-hook)
  207. (defun my-debian-changelog-mode-hook ()
  208. (make-local-variable 'add-log-mailing-address)
  209. (setq add-log-mailing-address \"myname@debian.org\"))
  210. in your ~/.emacs file. This is better than including a local setting
  211. for add-log-mailing-address in the changelog itself both because you
  212. only have to set it up once and because it works in the presense of
  213. NMUs."
  214. (interactive)
  215. (kill-all-local-variables)
  216. (text-mode)
  217. (setq major-mode 'debian-changelog-mode
  218. mode-name "Debian changelog"
  219. left-margin 2
  220. fill-prefix " "
  221. fill-column 74)
  222. (use-local-map debian-changelog-mode-map)
  223. ;; Let each entry behave as one paragraph:
  224. (set (make-local-variable 'paragraph-start) "\\*")
  225. (set (make-local-variable 'paragraph-separate) "\\*\\|\\s-*$|\\S-")
  226. ;; Let each version behave as one page.
  227. ;; Match null string on the heading line so that the heading line
  228. ;; is grouped with what follows.
  229. (set (make-local-variable 'page-delimiter) "^\\<")
  230. (set (make-local-variable 'version-control) 'never)
  231. (run-hooks 'debian-changelog-mode-hook))
  232. (provide 'debian-changelog)