[PATCH] documentation: add kernel-dot.emacs.txt

From: Geyslan G. Bem
Date: Tue Feb 16 2016 - 14:03:01 EST


This patch adds kernel-dot-emacs.txt (elisp) which deliver best
indentation, comments and white space highlighting functionalities.

This also changes the CodingStyle and 00-INDEX files by referencing
the new kernel-dot-emacs.

Signed-off-by: Geyslan G. Bem <geyslan@xxxxxxxxx>
Reviewed-by: Tiago Natel de Moura <tiago4orion@xxxxxxxxx>
---

Notes:
This patch was done by suggestion of Jonathan Corbet:
http://thread.gmane.org/gmane.linux.documentation/35265/focus=35309

v2: fix c-cleanup-list scope

Documentation/00-INDEX | 2 +
Documentation/CodingStyle | 38 +----
Documentation/kernel-dot-emacs.txt | 285 +++++++++++++++++++++++++++++++++++++
3 files changed, 291 insertions(+), 34 deletions(-)
create mode 100644 Documentation/kernel-dot-emacs.txt

diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index cd077ca..d4c48f5 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -259,6 +259,8 @@ kernel-doc-nano-HOWTO.txt
- mini HowTo on generation and location of kernel documentation files.
kernel-docs.txt
- listing of various WWW + books that document kernel internals.
+kernel-dot-emacs.txt
+ - emacs dot file for kernel coding style.
kernel-parameters.txt
- summary listing of command line / boot prompt args for the kernel.
kernel-per-CPU-kthreads.txt
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index c06f817..4d64b58 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -501,40 +501,10 @@ typing - an infinite number of monkeys typing into GNU emacs would never
make a good program).

So, you can either get rid of GNU emacs, or change it to use saner
-values. To do the latter, you can stick the following in your .emacs file:
-
-(defun c-lineup-arglist-tabs-only (ignored)
- "Line up argument lists by tabs, not spaces"
- (let* ((anchor (c-langelem-pos c-syntactic-element))
- (column (c-langelem-2nd-pos c-syntactic-element))
- (offset (- (1+ column) anchor))
- (steps (floor offset c-basic-offset)))
- (* (max steps 1)
- c-basic-offset)))
-
-(add-hook 'c-mode-common-hook
- (lambda ()
- ;; Add kernel style
- (c-add-style
- "linux-tabs-only"
- '("linux" (c-offsets-alist
- (arglist-cont-nonempty
- c-lineup-gcc-asm-reg
- c-lineup-arglist-tabs-only))))))
-
-(add-hook 'c-mode-hook
- (lambda ()
- (let ((filename (buffer-file-name)))
- ;; Enable kernel mode for the appropriate files
- (when (and filename
- (string-match (expand-file-name "~/src/linux-trees")
- filename))
- (setq indent-tabs-mode t)
- (setq show-trailing-whitespace t)
- (c-set-style "linux-tabs-only")))))
-
-This will make emacs go better with the kernel coding style for C
-files below ~/src/linux-trees.
+values. To do the latter, you can stick the elisp code from
+Documentation/kernel-dot-emacs.txt in your emacs init file. This will make
+emacs go better with the kernel coding style for C files below
+~/src/linux-trees.

But even if you fail in getting emacs to do sane formatting, not
everything is lost: use "indent".
diff --git a/Documentation/kernel-dot-emacs.txt b/Documentation/kernel-dot-emacs.txt
new file mode 100644
index 0000000..55b3090
--- /dev/null
+++ b/Documentation/kernel-dot-emacs.txt
@@ -0,0 +1,285 @@
+;; Kernel dot emacs
+;; Based on the prior elisp from Documentantion/CodingStyle
+;;
+;; January, 2016
+;; Geyslan G. Bem <geyslan@xxxxxxxxx>
+
+;; This elisp does use of emacs functionalities which deliver to the
+;; user indentation, comments and white space highlighting.
+;;
+;; As known tabs are the higher law and the prior elisp code enforces
+;; that law for any lineup indentation.
+;;
+;; However some trees have specific rules about line continuation
+;; indentation. Even scripts/checkpatch.pl suggests the TABS+SPACES (lining up
+;; under the open paren) for lineup the sequential lines.
+;;
+;; In addition to allowing the automatic setup by tree, this elisp can easily
+;; be modified for new configurations. Eg.
+;;
+;; (when (or (string-match (concat source-path "/net") filename)
+;; (string-match (concat source-path "/drivers/net") filename))
+;; (setup-kernel-style 'extra-bottom-line t nil))
+;;
+;; The above model can be used for a new tree just changing the tree path
+;; and parameters of setup-kernel-style function.
+;;
+;; setup-kernel-style function sets the kernel-comment-style,
+;; kernel-lineup-tabs-only and kernel-lineup-maximum-tabs variables. They
+;; are used by the functions kernel-comment-dwim and kernel-lineup-arglist.
+;;
+;; The kernel-lineup-arglist function detects the maximum tabs allowed to
+;; lineup and if it must use tabs and spaces instead of only tabs.
+;;
+;; There are two cleanups for else and else if braces enabled when
+;; auto-newline is on. These are comfortable and avoid wrong coding
+;; style. For instance
+;;
+;; void spam(int i)
+;; {
+;; if (i == 7) {
+;; dosomething();
+;; ...
+;; }
+;; else
+;; {
+;; appears like this after the last open brace is typed:
+;;
+;; void spam(int i)
+;; {
+;; if (i == 7) {
+;; dosomething();
+;; ...
+;; } else {
+;;
+;; The same happens for else if opening braces.
+;;
+;; The function kernel-align-to-equals makes the aligning of variable
+;; initializations/assignments easier.
+;;
+;; int x = 10;
+;; char *str = "text";
+;; x = 100;
+;;
+;; After marked the region and pressed C-c a =
+;;
+;; int x = 10;
+;; char *str = "text";
+;; x = 100;
+;;
+;; Concerning to comments kernel-comment-dwim is an improved version of
+;; comment-dwim. It comment/uncomment lines, regions or adds a new
+;; indented comment after the code using the same key binding. Eg.
+;;
+;; void f(int x, int y);
+;;
+;; Press M-; in any position on the line for
+;;
+;; void f(int x, int y); /* */
+;;
+;; Press M-; again for
+;;
+;; /* void f(int x, int y); */
+;;
+;; Press M-; and again for
+;;
+;; void f(int x, int y);
+;;
+;; For multi-line comments the result is
+;;
+;; /*
+;; * void f1(int x, int y);
+;; * void f2(int x, int y);
+;; */
+;;
+;; Emacs doesn't provide yet a 'net' comment style by default. This code
+;; also does the magic when kernel-comment-style is set as 'extra-bottom-line.
+;;
+;; /* void f1(int x, int y);
+;; * void f2(int x, int y);
+;; */
+;;
+;; Until now the comment-region doesn't tabify the comment, generating
+;; spaces before the " * " comment-continue variable (this issue was
+;; reported and patched in the to be released emacs-25) however this code
+;; correctly tabify the commented result.
+;;
+;; kernel-comment-dwim also removes trailing white spaces created by the
+;; comment-region.
+;;
+;; Finally the white space highlighting is a must to alert about long
+;; lines, leading or trailing spaces and top or bottom empty lines.
+
+
+(defconst kernel-column-limit 80
+ "It is only 80, get over it.")
+
+(defvar kernel-source-path "~/src/linux-trees"
+ "The kernel source path.")
+
+(defvar kernel-comment-style 'extra-lines
+ "Default style is 'extra-lines.
+The another option is 'extra-bottom-line")
+(make-variable-buffer-local 'kernel-comment-style)
+
+(defvar kernel-lineup-tabs-only nil
+ "If it is non-nil the kernel lineup indentation will make use of tabs only.
+When nil lineup indentation will use TABS + SPACES.")
+(make-variable-buffer-local 'kernel-lineup-tabs-only)
+
+(defvar kernel-lineup-maximum-tabs nil
+ "If it is non-nil its value will be the maximum tabs steps in kernel lineup
+indentation.
+When nil there will not be such a limit.
+In both cases there is also the maximum limit forced by the
+`kernel-lineup-arglist' function in conjuction with the
+`kernel-column-limit' constant.")
+(make-variable-buffer-local 'kernel-lineup-maximum-tabs)
+
+(defun setup-kernel-style (comment-style lineup-tabs-only lineup-maximum-tabs)
+ (setq kernel-comment-style comment-style)
+ (setq kernel-lineup-tabs-only lineup-tabs-only)
+ (setq kernel-lineup-maximum-tabs lineup-maximum-tabs))
+
+(defun kernel-comment-dwim ()
+ "Comments or uncomments the region.
+If there's no active region adds/indents an one line comment or
+comments/uncomments the current line if the one line comment is
+empty."
+ (interactive)
+ (let (beg end)
+ (if (region-active-p)
+ (progn
+ (setq beg (region-beginning)
+ end (region-end))
+ (if (comment-only-p beg end)
+ (uncomment-region beg end)
+ (progn
+ (comment-region beg end)
+ (save-excursion
+ (goto-char beg)
+ ;; Remove extra top line
+ (when (equal kernel-comment-style 'extra-bottom-line)
+ (re-search-forward "/\\*\\s-*\n\\s-*\\(\\*\\)" end t)
+ (replace-match "/\\1"))
+ ;; Update end point
+ (goto-char beg)
+ (re-search-forward "\\*/" nil t)
+ (setq end (point))
+ ;; This error is fixed in version 25.
+ (when (< emacs-major-version 25)
+ (tabify beg end))
+ ;; Cleaning only trailing spaces inserted by comment-region.
+ ;; Existing ones are not touched.
+ (goto-char beg)
+ (while (re-search-forward
+ "\\(/+\\|^\\s-+\\)\\(\\*\\)\\(\\s-+$\\)" end t nil)
+ (replace-match "\\1\\2")
+ (save-excursion
+ (re-search-forward "\\*/" nil t 1)
+ (setq end (point))))))))
+ (progn
+ (setq beg (line-beginning-position)
+ end (line-end-position))
+ (if (save-excursion
+ (goto-char beg)
+ (looking-at "\\s-*$"))
+ (progn
+ (comment-indent)
+ (indent-according-to-mode))
+ (if (comment-only-p beg end)
+ (uncomment-region beg end)
+ (if (save-excursion
+ (goto-char beg)
+ (re-search-forward "/\\*\\s-+\\*/" end t 1))
+ (progn
+ (save-excursion
+ (goto-char beg)
+ (let (kill-ring)
+ (comment-kill nil)))
+ ;; Read end position directly
+ (comment-region beg (line-end-position)))
+ (comment-indent))))))))
+
+(defun kernel-align-to-equals (begin end)
+ "Align region to equal signs"
+ (interactive "r")
+ (align-regexp begin end "\\(\\s-*\\)=" 1 1 nil))
+
+(defun kernel-lineup-arglist (langelem)
+ ""
+ (let* ((ret (c-lineup-arglist langelem))
+ (anchor (c-langelem-pos c-syntactic-element))
+ (column (c-langelem-2nd-pos c-syntactic-element))
+ (offset (- (1+ column) anchor))
+ (newcol (c-langelem-col langelem t))
+ (steps (floor offset c-basic-offset)))
+ (if (not kernel-lineup-tabs-only)
+ ret
+ (progn
+ (when (>= (+ newcol (* c-basic-offset steps))
+ kernel-column-limit)
+ (setq steps (1- steps)))
+ (when kernel-lineup-maximum-tabs
+ (setq steps (min steps
+ kernel-lineup-maximum-tabs)))
+ (* (max steps 1) c-basic-offset)))))
+
+(add-hook 'c-mode-common-hook
+ (lambda ()
+ (c-add-style
+ "linux-kernel"
+ '("linux" (c-offsets-alist
+ (arglist-cont-nonempty
+ c-lineup-gcc-asm-reg
+ kernel-lineup-arglist))
+ (c-cleanup-list brace-else-brace
+ brace-elseif-brace)))))
+
+(defun kernel-style-hook ()
+ (let ((filename (buffer-file-name))
+ (source-path (expand-file-name kernel-source-path)))
+ ;; Enable kernel mode for the appropriate files
+ (when (and filename
+ (string-match source-path filename))
+ ;; Setup style
+ (c-set-style "linux-kernel")
+ (setq tab-width 8
+ comment-style 'extra-line
+ indent-tabs-mode t
+ backward-delete-char-untabify-method nil)
+ (c-toggle-auto-newline t)
+
+ ;; Setup tree paths here
+ (when (or (string-match (concat source-path "/net") filename)
+ (string-match (concat source-path "/drivers/net") filename))
+ (setup-kernel-style 'extra-bottom-line t nil))
+ (when (string-match (concat source-path "/drivers/usb/host") filename)
+ (setup-kernel-style 'extra-lines t 2))
+
+ ;; Set kernel style key bindings
+ (local-set-key [remap comment-dwim] 'kernel-comment-dwim)
+ (local-set-key (kbd "C-c a =") 'kernel-align-to-equals)
+ ;; Setup white space highlighting
+ (require 'whitespace)
+ (setq whitespace-line-column kernel-column-limit
+ whitespace-style '(face empty
+ indentation::tab
+ whitespace-space-before-tab
+ space-before-tab::tab
+ lines-tail
+ trailing))
+ (dolist (face '(whitespace-line
+ whitespace-indentation
+ whitespace-space
+ whitespace-space-before-tab
+ whitespace-empty
+ whitespace-trailing))
+ (set-face-background face "red"))
+ (set-face-attribute whitespace-line nil
+ :background "red"
+ :foreground "yellow"
+ :weight 'bold)
+ (whitespace-mode t))))
+
+(add-hook 'c-mode-hook 'kernel-style-hook)
--
2.7.0