emacs-config/elpa/lice-20191011.631/lice.el
2020-04-28 12:47:35 +02:00

207 lines
6.6 KiB
EmacsLisp

;;; lice.el --- License And Header Template
;; Copyright (C) 2012 Taiki Sugawara
;; Author: Taiki Sugawara <buzz.taiki@gmail.com>
;; Keywords: template, license, tools
;; URL: https://github.com/buzztaiki/lice-el
;; This program 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 of the License, or
;; (at your option) any later version.
;; This program 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.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Overview
;; --------
;; `lice.el` provides following features:
;; - License template management.
;; - File header insertion.
;; Usage
;; -----
;; Usage is very easy, put `lice.el` in your emacs system, and open a new
;; file, and run:
;; M-x lice
;; Then, `lice.el` tell to use which license (default is gpl-3.0). You
;; can select license on minibuffer completion.
;; When you select license, and enter the `RET`, license and copyright is
;; putted into a text.
;; More Information
;; ----------------
;; See the `README.md` file for more information.
;;; Code:
(require 'cl-lib)
(require 'newcomment)
(defconst lice:version "0.2")
(defconst lice:system-template-directory
(expand-file-name "template"
(or (and load-file-name (file-name-directory load-file-name))
default-directory)))
(defvar lice:custom-template-directory
(expand-file-name "lice" user-emacs-directory))
(defgroup lice nil
"License And Header Template"
:prefix "lice:"
:group 'tools
:link '(url-link "https://github.com/buzztaiki/lice-el"))
(define-widget 'lice:comment-style 'choice
"The comment style selection widget."
:args `(,@(cl-loop for x in comment-styles
collect `(const
:tag ,(replace-regexp-in-string
"-" " " (capitalize (symbol-name (car x))))
,(car x)))
(other :tag "Mode Default" nil)))
(defcustom lice:license-directories
(list lice:system-template-directory lice:custom-template-directory)
"The location of License template directories"
:group 'lice
:type '(repeat directory))
(defcustom lice:comment-style 'extra-line
"The comment style for license insertion.
When nil, `comment-style' value is used."
:group 'lice
:type 'lice:comment-style)
(defcustom lice:default-license "gpl-3.0"
"The default license name"
:group 'lice
:safe 'stringp
:type 'string)
(defcustom lice:copyright-holder (user-full-name)
"The copyright holder"
:group 'lice
:safe 'stringp
:type 'string)
(defcustom lice:header-spec '(lice:insert-copyright
lice:insert-license)
"The license header spec.
Each element should be function.
These functions should take one argument, license object, and
should insert header string fragment."
:group 'lice
:type '(repeat function))
(defcustom lice:mode-comments
(append
(cl-loop for mode in '(c-mode c++-mode java-mode groovy-mode)
collect (list mode
:comment-start "/*"
:comment-end "*/"))
'((nxml-mode :comment-continue " ")))
"The definition of mode specific comments.
Each elements are follows:
\(MODE . PROPERTIES))
Mode is a major-mode which is applied PROPERTIES.
PROPERTIES is a plist whitch has following properties:
:comment-start - `comment-start' of this MODE.
:comment-end - `comment-end' of this MODE.
:comment-style - `comment-style' of this MODE.
:comment-continue - `comment-continue' of this MODE.
"
:group 'lice
:type '(repeat (cons :format "%v" :indent 9
(function :tag "Mode" :size 20)
(sexp :tag ""
:value-to-internal (lambda (widget value)
(prin1-to-string value))))))
(defvar lice:license-history nil)
(defun lice:licenses ()
"Return a license list.
Each element are follows:
\(SIMPLE-NAME . FILE)"
(cl-loop for dir in lice:license-directories
with licenses
if (and dir (file-directory-p dir))
append (lice:directory-licenses dir) into licenses
finally return (sort licenses
(lambda (a b) (string< (car a) (car b))))))
(defun lice:directory-licenses (dir)
(cl-loop for file in (directory-files dir t)
with licenses
for name = (file-name-nondirectory file)
if (and (file-regular-p file) (not (assoc name licenses)))
collect (cons name file)))
;;;###autoload
(defun lice (name)
"Insert license and headers.
NAME is a template name for insertion."
(interactive (list (lice:read-license)))
(let ((license (assoc name (lice:licenses))))
(unless license
(error "Unknown license name: %s" name))
(save-restriction
(narrow-to-region (point) (point))
(cl-loop for component in lice:header-spec
do (progn (funcall component license)
(goto-char (point-max))))
(lice:comment-region (point-min) (point-max) major-mode)
(goto-char (point-max)))))
(defun lice:insert-copyright (license)
(insert (format "Copyright (C) %s %s\n\n"
(format-time-string "%Y") lice:copyright-holder)))
(defun lice:insert-license (license)
(insert-file-contents (cdr license)))
(defun lice:read-license ()
(completing-read (format "License Name (%s): " lice:default-license)
(lice:licenses)
nil t nil 'lice:license-history
lice:default-license))
(defun lice:mode-comment (mode)
(and mode
(or (cdr (assq mode lice:mode-comments))
(lice:mode-comment (get mode 'derived-mode-parent)))))
(defun lice:comment-region (start end mode)
(let* ((comment (lice:mode-comment mode))
(comment-start (or (plist-get comment :comment-start) comment-start))
(comment-end (or (plist-get comment :comment-end) comment-end))
(comment-style (or (plist-get comment :comment-style)
lice:comment-style
comment-style))
(comment-continue (or (plist-get comment :comment-continue) comment-continue)))
(save-restriction
(narrow-to-region start end)
(comment-region (point-min) (point-max))
(delete-trailing-whitespace (point-min) (point-max)))))
(provide 'lice)
;;; lice.el ends here