[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 30b18d1 2/3: Merge commit 'cce1d8b50b1ceccb80c20398cd659db
From: |
Daiki Ueno |
Subject: |
[elpa] master 30b18d1 2/3: Merge commit 'cce1d8b50b1ceccb80c20398cd659db3a6348aac' as 'packages/gnome-c-style' |
Date: |
Tue, 19 Jan 2016 06:39:52 +0000 |
branch: master
commit 30b18d1d6f7deb3b0a1973c87e77490e9a50c818
Merge: 445258b cce1d8b
Author: Daiki Ueno <address@hidden>
Commit: Daiki Ueno <address@hidden>
Merge commit 'cce1d8b50b1ceccb80c20398cd659db3a6348aac' as
'packages/gnome-c-style'
---
packages/gnome-c-style/.gitignore | 2 +
packages/gnome-c-style/Makefile | 16 +
packages/gnome-c-style/README | 1 +
packages/gnome-c-style/README.md | 94 +++++
packages/gnome-c-style/gnome-c-align.el | 536 +++++++++++++++++++++++++++
packages/gnome-c-style/gnome-c-snippet.el | 565 +++++++++++++++++++++++++++++
packages/gnome-c-style/gnome-c-style.el | 75 ++++
packages/gnome-c-style/gnome-c-tests.el | 191 ++++++++++
8 files changed, 1480 insertions(+), 0 deletions(-)
diff --git a/packages/gnome-c-style/.gitignore
b/packages/gnome-c-style/.gitignore
new file mode 100644
index 0000000..7c5214c
--- /dev/null
+++ b/packages/gnome-c-style/.gitignore
@@ -0,0 +1,2 @@
+*.elc
+
diff --git a/packages/gnome-c-style/Makefile b/packages/gnome-c-style/Makefile
new file mode 100644
index 0000000..571841e
--- /dev/null
+++ b/packages/gnome-c-style/Makefile
@@ -0,0 +1,16 @@
+EMACS ?= emacs
+RM ?= rm
+ELC = gnome-c-align.elc gnome-c-snippet.elc gnome-c-style.elc
+
+all: $(ELC)
+
+%.elc: %.el
+ $(EMACS) -Q -batch --eval "(setq load-path (cons nil load-path))" \
+ -f batch-byte-compile $<
+
+check:
+ $(EMACS) -Q -batch --eval "(setq load-path (cons nil load-path))" \
+ -l ert -l gnome-c-tests.el -f ert-run-tests-batch-and-exit
+
+clean:
+ $(RM) -rf $(ELC)
diff --git a/packages/gnome-c-style/README b/packages/gnome-c-style/README
new file mode 120000
index 0000000..42061c0
--- /dev/null
+++ b/packages/gnome-c-style/README
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/packages/gnome-c-style/README.md b/packages/gnome-c-style/README.md
new file mode 100644
index 0000000..336a462
--- /dev/null
+++ b/packages/gnome-c-style/README.md
@@ -0,0 +1,94 @@
+gnome-c-style
+======
+
+In the C coding style commonly used in GNOME, identifiers are written
+in camel case and function arguments are aligned to the right end.
+That makes it a bit cumbersome to keep your code consistent with the
+style, even with align.el or plugins like yasnippet.
+
+gnome-c-style is an Emacs minor mode intended to help editing C
+source code in that style. It mainly provides two features: text
+alignment and snippet insersion.
+
+Install
+------
+
+* Type "make"
+* Copy .elc files somewhere in your load-path
+* Add the following lines to ~/.emacs/init.el:
+
+```
+(autoload 'gnome-c-style-mode "gnome-c-style" "GNOME-style C minor mode" t)
+(add-hook 'c-mode-hook 'gnome-c-style-mode)
+```
+
+Usage
+------
+
+| Key | Command |
+--------------|-----------------------------------------------------------|
+| C-c C-g a | Align argument list at the current point |
+| C-c C-g r | Align function declarations in the current region |
+| C-c C-g C-g | Compute optimal alignment columns from the current region |
+| C-c C-g g | Guess alignment columns from the current region |
+| C-c C-g s | Set alignment column to the current point |
+| C-c C-g c | Insert ```module_object``` |
+| C-c C-g C | Insert ```MODULE_OBJECT``` |
+| C-c C-g C-c | Insert ```ModuleObject``` |
+| C-c C-g s | Insert custom snippet |
+
+Example
+------
+
+If you have the following code in a header file:
+```c
+GGpgCtx *g_gpg_ctx_new (GError **error);
+
+typedef void (*GGpgProgressCallback) (gpointer user_data,
+ const gchar *what,
+ gint type,
+ gint current,
+ gint total);
+
+void g_gpg_ctx_set_progress_callback (GGpgCtx *ctx,
+ GGpgProgressCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_data);
+void g_gpg_ctx_add_signer (GGpgCtx *ctx, GGpgKey *key);
+guint g_gpg_ctx_get_n_signers (GGpgCtx *ctx);
+GGpgKey *g_gpg_ctx_get_signer (GGpgCtx *ctx, guint index);
+void g_gpg_ctx_clear_signers (GGpgCtx *ctx);
+```
+
+Mark the region, type ```C-c C-g C-g```, and you will see the optimum
+alignment columns:
+
+```
+identifier-start: 9, arglist-start: 41, arglist-identifier-start: 63
+```
+
+Then, mark the region again, type ```C-c C-g r```, and you will get
+the code aligned:
+
+```c
+GGpgCtx *g_gpg_ctx_new (GError **error);
+
+typedef void (*GGpgProgressCallback) (gpointer user_data,
+ const gchar *what,
+ gint type,
+ gint current,
+ gint total);
+
+void g_gpg_ctx_set_progress_callback (GGpgCtx *ctx,
+ GGpgProgressCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_data);
+void g_gpg_ctx_add_signer (GGpgCtx *ctx,
+ GGpgKey *key);
+guint g_gpg_ctx_get_n_signers (GGpgCtx *ctx);
+GGpgKey *g_gpg_ctx_get_signer (GGpgCtx *ctx,
+ guint index);
+void g_gpg_ctx_clear_signers (GGpgCtx *ctx);
+```
+
+Note that ```typedef``` is skipped as it is not a function declaration.
diff --git a/packages/gnome-c-style/gnome-c-align.el
b/packages/gnome-c-style/gnome-c-align.el
new file mode 100644
index 0000000..64b8178
--- /dev/null
+++ b/packages/gnome-c-style/gnome-c-align.el
@@ -0,0 +1,536 @@
+;; gnome-c-align.el --- GNOME-style code alignment -*- lexical-binding: t; -*-
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <address@hidden>
+;; Keywords: GNOME, C, coding style
+
+;; This file is not part of GNU Emacs.
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cc-mode)
+(require 'cl-lib)
+
+(defcustom gnome-c-align-max-column 80
+ "Maximum number of columns per line."
+ :type '(choice (integer :tag "Columns")
+ (const :tag "No wrap"))
+ :group 'gnome-c-style)
+
+(defvar gnome-c-align-identifier-start-column nil)
+(make-variable-buffer-local 'gnome-c-align-identifier-start-column)
+
+(defvar gnome-c-align-arglist-start-column nil)
+(make-variable-buffer-local 'gnome-c-align-arglist-start-column)
+
+(defvar gnome-c-align-arglist-identifier-start-column nil)
+(make-variable-buffer-local 'gnome-c-align-arglist-identifier-start-column)
+
+(cl-defstruct (gnome-c-align--argument
+ (:constructor nil)
+ (:constructor gnome-c-align--make-argument (type-start
+ type-identifier-end
+ type-end
+ identifier-start
+ identifier-end))
+ (:copier nil)
+ (:predicate nil))
+ (type-start nil :read-only t)
+ (type-identifier-end nil :read-only t)
+ (type-end nil :read-only t)
+ (identifier-start nil :read-only t)
+ (identifier-end nil :read-only t))
+
+(defun gnome-c-align--marker-column (marker)
+ (save-excursion
+ (goto-char marker)
+ (current-column)))
+
+(defun gnome-c-align--indent-to-column (column)
+ ;; Prefer 'char **foo' than 'char ** foo'
+ (when (looking-back "\\*+" nil t)
+ (setq column (- column (- (match-end 0) (match-beginning 0))))
+ (goto-char (match-beginning 0)))
+ ;; FIXME: should respect indent-tabs-mode?
+ (let (indent-tabs-mode)
+ (indent-to-column column)))
+
+(defun gnome-c-align--argument-type-width (arg)
+ (- (gnome-c-align--marker-column (gnome-c-align--argument-type-end arg))
+ (gnome-c-align--marker-column (gnome-c-align--argument-type-start arg))))
+
+(defun gnome-c-align--argument-type-identifier-width (arg)
+ (- (gnome-c-align--marker-column
+ (gnome-c-align--argument-type-identifier-end arg))
+ (gnome-c-align--marker-column
+ (gnome-c-align--argument-type-start arg))))
+
+(defun gnome-c-align--arglist-identifier-start-column (arglist start-column)
+ (let ((max-type-identifier-width
+ (apply #'max
+ 0
+ (mapcar #'gnome-c-align--argument-type-identifier-width
+ arglist)))
+ (max-extra-width
+ (apply #'max
+ 0
+ (mapcar
+ (lambda (argument)
+ (- (gnome-c-align--argument-type-end argument)
+ (gnome-c-align--argument-type-identifier-end argument)))
+ arglist))))
+ (+ start-column max-type-identifier-width max-extra-width)))
+
+(defun gnome-c-align--argument-identifier-width (argument)
+ (if (gnome-c-align--argument-identifier-start argument)
+ (- (gnome-c-align--marker-column
+ (gnome-c-align--argument-identifier-end argument))
+ (gnome-c-align--marker-column
+ (gnome-c-align--argument-identifier-start argument)))
+ 0))
+
+(defun gnome-c-align--arglist-identifier-width (arglist)
+ (apply #'max 0 (mapcar #'gnome-c-align--argument-identifier-width arglist)))
+
+(defun gnome-c-align--normalize-arglist-region (arglist beg end)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (while (re-search-forward "\\s-+" nil t)
+ (replace-match " "))
+ (goto-char (point-min))
+ (while (re-search-forward "\\s-*," nil t)
+ (replace-match ",\n"))
+ (goto-char (point-min))
+ (delete-trailing-whitespace)
+ ;; Remove whitespace at the beginning of line
+ (goto-char (point-min))
+ (while (re-search-forward "^\\s-+" nil t)
+ (replace-match ""))
+ ;; Remove empty lines
+ (goto-char (point-min))
+ (delete-matching-lines "^$")
+ ;; 'int * * * foo' -> 'int ***foo'
+ (dolist (argument arglist)
+ (goto-char (gnome-c-align--argument-type-end argument))
+ (while (re-search-backward
+ "\\(\\*+\\)\\s-+"
+ (gnome-c-align--argument-type-identifier-end argument)
+ t)
+ (replace-match "\\1"))
+ (when (gnome-c-align--argument-identifier-start argument)
+ (goto-char (gnome-c-align--argument-identifier-start argument))
+ (if (looking-back "\\* " nil)
+ (delete-char -1)))
+ (goto-char (gnome-c-align--argument-type-end argument))))))
+
+(defun gnome-c-align--parse-arglist (beg end)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (let (type-start
+ type-identifier-end
+ type-end
+ identifier-start
+ identifier-end
+ arglist
+ last-token-start)
+ (goto-char (point-max))
+ (while (not (bobp))
+ (c-backward-syntactic-ws)
+ (setq identifier-end (point-marker))
+ ;; Array argument, such as 'int a[]'
+ (if (eq (preceding-char) ?\])
+ (c-backward-sexp))
+ (c-backward-token-2)
+ (setq identifier-start (point-marker))
+ (c-backward-syntactic-ws)
+ (if (or (bobp) (eq (preceding-char) ?,))
+ (progn
+ ;; Identifier is omitted, or '...'.
+ (setq type-start identifier-start
+ type-identifier-end identifier-end
+ type-end identifier-end
+ identifier-start nil
+ identifier-end nil)
+ (c-backward-token-2))
+ (setq type-end (point-marker)
+ last-token-start type-end)
+ (while (and (not (bobp))
+ (progn
+ (c-backward-token-2)
+ (unless (eq (char-after) ?,)
+ (setq last-token-start (point-marker)))))
+ (c-backward-syntactic-ws))
+ (setq type-start last-token-start)
+ (save-excursion
+ (goto-char type-end)
+ (skip-chars-backward "* " type-start)
+ (c-backward-syntactic-ws)
+ (setq type-identifier-end (point-marker))))
+ (push (gnome-c-align--make-argument type-start
+ type-identifier-end
+ type-end
+ identifier-start
+ identifier-end)
+ arglist))
+ arglist))))
+
+;;;###autoload
+(defun gnome-c-align-arglist-at-point (&optional identifier-start-column)
+ "Reformat argument list at point, aligning argument to the right end."
+ (interactive)
+ (save-excursion
+ (let* (start-column arglist)
+ (cl-destructuring-bind (beg end)
+ (gnome-c-align--arglist-region-at-point (point))
+ (goto-char beg)
+ (setq start-column (current-column))
+ (save-restriction
+ (narrow-to-region beg end)
+ (setq arglist (gnome-c-align--parse-arglist (point-min) (point-max)))
+ (gnome-c-align--normalize-arglist-region
+ arglist (point-min) (point-max))
+ (unless identifier-start-column
+ (setq identifier-start-column
+ (gnome-c-align--arglist-identifier-start-column arglist 0)))
+ (dolist (argument arglist)
+ (goto-char (gnome-c-align--argument-type-start argument))
+ (let ((column (if (bobp) 0 start-column)))
+ (when (not (bobp))
+ (gnome-c-align--indent-to-column start-column))
+ (when (gnome-c-align--argument-identifier-start argument)
+ (setq column (+ column identifier-start-column))
+ (goto-char (gnome-c-align--argument-identifier-start argument))
+ (gnome-c-align--indent-to-column column)))))))))
+
+(cl-defstruct (gnome-c-align--decl
+ (:constructor nil)
+ (:constructor gnome-c-align--make-decl (start
+ end
+ identifier-start
+ identifier-end
+ arglist-start
+ arglist-end
+ arglist))
+ (:copier nil)
+ (:predicate nil))
+ (start nil :read-only t)
+ (end nil :read-only t)
+ (identifier-start nil :read-only t)
+ (identifier-end nil :read-only t)
+ (arglist-start nil :read-only t)
+ (arglist-end nil :read-only t)
+ (arglist nil :read-only t))
+
+(defun gnome-c-align--decls-identifier-start-column (decls start-column)
+ (apply #'max
+ start-column
+ (delq nil
+ (mapcar
+ (lambda (decl)
+ (let ((decl-column
+ (+ start-column
+ (gnome-c-align--marker-column
+ (gnome-c-align--decl-identifier-start decl)))))
+ (if (and gnome-c-align-max-column
+ (> decl-column gnome-c-align-max-column))
+ nil
+ decl-column)))
+ decls))))
+
+(defun gnome-c-align--decl-identifier-width (decl)
+ (- (gnome-c-align--marker-column
+ (gnome-c-align--decl-identifier-end decl))
+ (gnome-c-align--marker-column
+ (gnome-c-align--decl-identifier-start decl))))
+
+(defun gnome-c-align--decls-arglist-start-column (decls start-column)
+ (let ((arglist-width
+ (+ (gnome-c-align--decls-arglist-identifier-start-column decls 0)
+ (gnome-c-align--decls-arglist-identifier-width decls)
+ (length ");"))))
+ (apply #'max
+ start-column
+ (delq nil
+ (mapcar
+ (lambda (decl)
+ (let ((decl-column
+ (+ start-column
+ (gnome-c-align--decl-identifier-width decl)
+ 1)))
+ (if (and gnome-c-align-max-column
+ (> (+ decl-column arglist-width)
+ gnome-c-align-max-column))
+ nil
+ decl-column)))
+ decls)))))
+
+(defun gnome-c-align--decls-arglist-identifier-width (decls)
+ (apply #'max 0 (mapcar (lambda (decl)
+ (gnome-c-align--arglist-identifier-width
+ (gnome-c-align--decl-arglist decl)))
+ decls)))
+
+(defun gnome-c-align--decls-arglist-identifier-start-column (decls
start-column)
+ (apply #'max 0 (mapcar (lambda (decl)
+ ;; FIXME: should wrap lines inside argument list?
+ (gnome-c-align--arglist-identifier-start-column
+ (gnome-c-align--decl-arglist decl)
+ start-column))
+ decls)))
+
+(defun gnome-c-align--parse-decl (beg end)
+ ;; Parse at most one func declaration found in BEG END.
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (let (arglist-start
+ arglist-end
+ identifier-start
+ identifier-end
+ vfunc-p)
+ (goto-char (point-min))
+ (c-forward-syntactic-ws)
+ (unless (looking-at
+ "typedef\\|#\\|G_\\(?:DECLARE\\|DEFINE\\)")
+ (while (and (not (eobp))
+ (not (eq (char-after) ?\()))
+ (c-forward-token-2)
+ (c-forward-syntactic-ws))
+ ;; Identifier is vfunc.
+ (when (looking-at "(\\s-*\\*")
+ (c-forward-sexp)
+ (c-forward-syntactic-ws)
+ (setq vfunc-p t))
+ (when (eq (char-after) ?\()
+ (setq arglist-start (point-marker))
+ (c-backward-syntactic-ws)
+ (setq identifier-end (point-marker))
+ (if vfunc-p
+ (c-backward-sexp)
+ (c-backward-token-2))
+ (setq identifier-start (point-marker))
+ (goto-char arglist-start)
+ (c-forward-sexp)
+ (setq arglist-end (point-marker))
+ (gnome-c-align--make-decl beg end
+ identifier-start identifier-end
+ arglist-start arglist-end
+ (gnome-c-align--parse-arglist
+ (1+ arglist-start)
+ (1- arglist-end)))))))))
+
+(defun gnome-c-align--normalize-decl (decl)
+ (save-excursion
+ ;; Replace newlines with a space
+ (save-restriction
+ ;; Ignore lines before identifier-start
+ (goto-char (gnome-c-align--decl-identifier-start decl))
+ (beginning-of-line)
+ (narrow-to-region (point)
+ (gnome-c-align--decl-arglist-end decl))
+ (goto-char (point-min))
+ (while (re-search-forward "\n" nil t)
+ (replace-match " ")))
+ ;; Replace consequent spaces with a space
+ (save-restriction
+ ;; Ignore lines before identifier-start
+ (goto-char (gnome-c-align--decl-identifier-start decl))
+ (beginning-of-line)
+ (narrow-to-region (point)
+ (gnome-c-align--decl-arglist-end decl))
+ (goto-char (point-min))
+ (while (re-search-forward "\\s-+" nil t)
+ (replace-match " ")))
+ (goto-char (gnome-c-align--decl-identifier-start decl))
+ (if (looking-back "\\* " nil)
+ (delete-char -1))
+ ;; Normalize the argument list
+ (gnome-c-align--normalize-arglist-region
+ (gnome-c-align--decl-arglist decl)
+ (gnome-c-align--decl-arglist-start decl)
+ (gnome-c-align--decl-arglist-end decl))))
+
+(defun gnome-c-align--arglist-region-at-point (point)
+ (save-excursion
+ (let (start)
+ (goto-char point)
+ (c-beginning-of-statement-1)
+ (c-backward-syntactic-ws)
+ (unless (eq ?\( (preceding-char))
+ (error "No containing argument list"))
+ (setq start (point))
+ (backward-char)
+ (condition-case nil
+ (c-forward-sexp)
+ (error
+ (error "No closing parenthesis")))
+ (backward-char)
+ (list start (point)))))
+
+;;;###autoload
+(defun gnome-c-align-set-column (symbol)
+ "Set alignment column of SYMBOL."
+ (interactive
+ (let ((symbol-name (completing-read "Symbol to change: "
+ '("identifier-start"
+ "arglist-start"
+ "arglist-identifier-start")
+ nil t)))
+ (list (intern (format "gnome-c-align-%s-column" symbol-name)))))
+ (set symbol (current-column)))
+
+(defun gnome-c-align--scan-decls (beg end)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char (point-min))
+ (let (decls)
+ (while (not (eobp))
+ (let (decl-start decl-end decl)
+ (c-forward-syntactic-ws)
+ (setq decl-start (point-marker))
+ (c-end-of-statement)
+ (setq decl-end (point-marker))
+ (setq decl (gnome-c-align--parse-decl decl-start decl-end))
+ (when decl
+ (push decl decls))))
+ decls))))
+
+(defun gnome-c-align--guess-optimal-columns (beg end)
+ (let ((buffer (current-buffer))
+ decls)
+ (with-temp-buffer
+ (insert-buffer-substring-no-properties buffer beg end)
+ (c-mode)
+ (setq decls (gnome-c-align--scan-decls (point-min) (point-max)))
+ (mapc #'gnome-c-align--normalize-decl decls)
+ (let* ((identifier-start-column
+ (gnome-c-align--decls-identifier-start-column
+ decls 0))
+ (arglist-start-column
+ (gnome-c-align--decls-arglist-start-column
+ decls identifier-start-column))
+ (arglist-identifier-start-column
+ (gnome-c-align--decls-arglist-identifier-start-column
+ decls (+ (length "(") arglist-start-column))))
+ (list (cons 'identifier-start-column
+ identifier-start-column)
+ (cons 'arglist-start-column
+ arglist-start-column)
+ (cons 'arglist-identifier-start-column
+ arglist-identifier-start-column))))))
+
+;;;###autoload
+(defun gnome-c-align-guess-optimal-columns (beg end)
+ "Compute the optimal alignment rule from the declarations in BEG and END.
+
+This sets `gnome-c-align-identifier-start-column',
+`gnome-c-align-arglist-start-column', and
+`gnome-c-align-arglist-identifier-start-column'."
+ (interactive "r")
+ (let ((columns (gnome-c-align--guess-optimal-columns beg end)))
+ (setq gnome-c-align-identifier-start-column
+ (cdr (assq 'identifier-start-column columns))
+ gnome-c-align-arglist-start-column
+ (cdr (assq 'arglist-start-column columns))
+ gnome-c-align-arglist-identifier-start-column
+ (cdr (assq 'arglist-identifier-start-column columns)))
+ (message
+ "identifier-start: %d, arglist-start: %d, arglist-identifier-start: %d"
+ gnome-c-align-identifier-start-column
+ gnome-c-align-arglist-start-column
+ gnome-c-align-arglist-identifier-start-column)))
+
+;;;###autoload
+(defun gnome-c-align-guess-columns (beg end)
+ "Guess the existing alignment rule from the declarations in BEG and END.
+
+This sets `gnome-c-align-identifier-start-column',
+`gnome-c-align-arglist-start-column', and
+`gnome-c-align-arglist-identifier-start-column'."
+ (interactive "r")
+ (let ((decls (gnome-c-align--scan-decls beg end))
+ arglist)
+ (unless decls
+ (error "No function declaration in the region"))
+ (setq arglist (gnome-c-align--parse-arglist
+ (1+ (gnome-c-align--decl-arglist-start (car decls)))
+ (1- (gnome-c-align--decl-arglist-end (car decls)))))
+ (unless arglist
+ (error "Empty argument list"))
+ (unless (gnome-c-align--argument-identifier-start (car arglist))
+ (error "No identifier in the argument list"))
+ (setq gnome-c-align-identifier-start-column
+ (gnome-c-align--marker-column
+ (gnome-c-align--decl-identifier-start (car decls)))
+ gnome-c-align-arglist-start-column
+ (gnome-c-align--marker-column
+ (gnome-c-align--decl-arglist-start (car decls)))
+ gnome-c-align-arglist-identifier-start-column
+ (gnome-c-align--marker-column
+ (gnome-c-align--argument-identifier-start (car arglist))))
+ (message
+ "identifier-start: %d, arglist-start: %d, arglist-identifier-start: %d"
+ gnome-c-align-identifier-start-column
+ gnome-c-align-arglist-start-column
+ gnome-c-align-arglist-identifier-start-column)))
+
+;;;###autoload
+(defun gnome-c-align-decls-region (beg end)
+ "Reformat function declarations in the region between BEG and END."
+ (interactive "r")
+ (save-excursion
+ (let (decls)
+ (save-restriction
+ (narrow-to-region beg end)
+ (unless (and gnome-c-align-identifier-start-column
+ gnome-c-align-arglist-start-column
+ gnome-c-align-arglist-identifier-start-column)
+ (let ((columns (gnome-c-align--guess-optimal-columns beg end)))
+ (unless gnome-c-align-identifier-start-column
+ (setq gnome-c-align-identifier-start-column
+ (cdr (assq 'identifier-start-column columns))))
+ (unless gnome-c-align-arglist-start-column
+ (setq gnome-c-align-arglist-start-column
+ (cdr (assq 'arglist-start-column columns))))
+ (unless gnome-c-align-arglist-identifier-start-column
+ (setq gnome-c-align-arglist-identifier-start-column
+ (cdr (assq 'arglist-identifier-start-column columns))))))
+ (setq decls (gnome-c-align--scan-decls beg end))
+ (mapc #'gnome-c-align--normalize-decl decls)
+ (dolist (decl decls)
+ (goto-char (gnome-c-align--decl-identifier-start decl))
+ (gnome-c-align--indent-to-column
+ gnome-c-align-identifier-start-column)
+ (goto-char (gnome-c-align--decl-identifier-end decl))
+ (when (>= (current-column) gnome-c-align-arglist-start-column)
+ (insert "\n"))
+ (goto-char (gnome-c-align--decl-arglist-start decl))
+ (gnome-c-align--indent-to-column
+ gnome-c-align-arglist-start-column)
+ (forward-char)
+ (gnome-c-align-arglist-at-point
+ (- (- gnome-c-align-arglist-identifier-start-column
+ (length "("))
+ gnome-c-align-arglist-start-column)))))))
+
+(provide 'gnome-c-align)
+
+;;; gnome-c-align.el ends here
diff --git a/packages/gnome-c-style/gnome-c-snippet.el
b/packages/gnome-c-style/gnome-c-snippet.el
new file mode 100644
index 0000000..ed36336
--- /dev/null
+++ b/packages/gnome-c-style/gnome-c-snippet.el
@@ -0,0 +1,565 @@
+;;; gnome-c-snippet.el --- GNOME-style code generation -*- lexical-binding: t;
-*-
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <address@hidden>
+;; Keywords: GNOME, C, coding style
+
+;; This file is not part of GNU Emacs.
+
+;; 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:
+
+;; FIXME: The snippets defined here could be rewritten in yasnippet
+
+;;; Code:
+
+(require 'gnome-c-align)
+
+(eval-when-compile
+ (require 'subword))
+
+(declare-function subword-forward "subword.el" (&optional arg))
+
+(defvar gnome-c-snippet-package nil)
+(make-variable-buffer-local 'gnome-c-snippet-package)
+
+(defvar gnome-c-snippet-class nil)
+(make-variable-buffer-local 'gnome-c-snippet-class)
+
+(defvar gnome-c-snippet-parent-package nil)
+(make-variable-buffer-local 'gnome-c-snippet-parent-package)
+
+(defvar gnome-c-snippet-parent-class nil)
+(make-variable-buffer-local 'gnome-c-snippet-parent-class)
+
+(defcustom gnome-c-snippet-align-arglist t
+ "Whether to align argument list of the inserted snippet"
+ :type 'boolean
+ :group 'gnome-c-style)
+
+(make-variable-buffer-local 'gnome-c-snippet-align-arglist)
+
+(defun gnome-c-snippet--parse-name (name)
+ (require 'subword)
+ (with-temp-buffer
+ (let (words)
+ (insert name)
+ (goto-char (point-min))
+ (while (not (eobp))
+ ;; Skip characters not recognized by subword-mode.
+ (if (looking-at "[^[:lower:][:upper:][:digit:]]+")
+ (goto-char (match-end 0)))
+ (push (buffer-substring (point) (progn (subword-forward 1)
+ (point)))
+ words))
+ (nreverse words))))
+
+(defun gnome-c-snippet--read-package-and-class (package-prompt
+ class-prompt
+ package-symbol
+ class-symbol)
+ (when (or current-prefix-arg
+ (not (and (symbol-value package-symbol)
+ (symbol-value class-symbol))))
+ (set package-symbol
+ (gnome-c-snippet--parse-name
+ (read-string (or package-prompt
+ "Package (CamelCase): ")
+ (if (symbol-value package-symbol)
+ (gnome-c-snippet--format-Package
+ (symbol-value package-symbol))))))
+ (set class-symbol
+ (gnome-c-snippet--parse-name
+ (read-string (or class-prompt
+ "Class (CamelCase): ")
+ (if (symbol-value class-symbol)
+ (gnome-c-snippet--format-Class
+ (symbol-value class-symbol)))))))
+ (list (symbol-value package-symbol) (symbol-value class-symbol)))
+
+(defun gnome-c-snippet--format-PACKAGE (package)
+ (mapconcat #'upcase package "_"))
+(defalias 'gnome-c-snippet--format-CLASS 'gnome-c-snippet--format-PACKAGE)
+
+(defun gnome-c-snippet--format-PACKAGE_CLASS (package class)
+ (concat (gnome-c-snippet--format-PACKAGE package)
+ "_"
+ (gnome-c-snippet--format-CLASS class)))
+
+(defun gnome-c-snippet--format-package (package)
+ (mapconcat #'downcase package "_"))
+(defalias 'gnome-c-snippet--format-class 'gnome-c-snippet--format-package)
+
+(defun gnome-c-snippet--format-package_class (package class)
+ (concat (gnome-c-snippet--format-package package)
+ "_"
+ (gnome-c-snippet--format-class class)))
+
+(defun gnome-c-snippet--format-Package (package)
+ (mapconcat #'identity package ""))
+(defalias 'gnome-c-snippet--format-Class 'gnome-c-snippet--format-Package)
+
+(defun gnome-c-snippet--format-PackageClass (package class)
+ (concat (gnome-c-snippet--format-Package package)
+ (gnome-c-snippet--format-Class class)))
+
+;;;###autoload
+(defun gnome-c-snippet-insert-package_class (package class)
+ "Insert the class name before the current point."
+ (interactive (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (insert (gnome-c-snippet--format-package_class package class)))
+
+;;;###autoload
+(defun gnome-c-snippet-insert-PACKAGE_CLASS (package class)
+ "Insert the class name before the current point."
+ (interactive (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (insert (gnome-c-snippet--format-PACKAGE_CLASS package class)))
+
+;;;###autoload
+(defun gnome-c-snippet-insert-PackageClass (package class)
+ "Insert the class name (in CamelCase) before the current point."
+ (interactive (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (insert (gnome-c-snippet--format-PackageClass package class)))
+
+(defun gnome-c-snippet-insert-interface-declaration (package iface
+ parent-package
parent-class)
+ "Insert interface declaration for PACKAGE and IFACE"
+ (interactive
+ (append (gnome-c-snippet--read-package-and-class
+ nil
+ "Interface (CamelCase): "
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class)
+ (gnome-c-snippet--read-package-and-class
+ "Parent package (CamelCase): "
+ "Parent class (CamelCase): "
+ 'gnome-c-snippet-parent-package
+ 'gnome-c-snippet-parent-class)))
+ (insert "\
+#define " (gnome-c-snippet--format-PACKAGE package) "_TYPE_"
(gnome-c-snippet--format-CLASS iface) " (" (gnome-c-snippet--format-package
package) "_" (gnome-c-snippet--format-class iface) "_get_type ())
+G_DECLARE_INTERFACE (" (gnome-c-snippet--format-PackageClass package iface) ",
"
+(gnome-c-snippet--format-package_class package iface) ", "
(gnome-c-snippet--format-PACKAGE package) ", " (gnome-c-snippet--format-CLASS
iface) ", " (gnome-c-snippet--format-PackageClass parent-package parent-class)
")
+"))
+
+(defun gnome-c-snippet--insert-class-declaration (package
+ class
+ parent-package
+ parent-class
+ derivable)
+ (insert "\
+#define " (gnome-c-snippet--format-PACKAGE package) "_TYPE_"
(gnome-c-snippet--format-CLASS class) " ("
(gnome-c-snippet--format-package_class package class) "_get_type ())
+G_DECLARE_" (if derivable "DERIVABLE" "FINAL") "_TYPE ("
(gnome-c-snippet--format-PackageClass package class) ", "
+(gnome-c-snippet--format-package_class package class) ", "
(gnome-c-snippet--format-PACKAGE package) ", " (gnome-c-snippet--format-CLASS
class) ", " (gnome-c-snippet--format-PackageClass parent-package parent-class)
")
+"))
+
+(defun gnome-c-snippet-insert-final-class-declaration (package
+ class
+ parent-package
+ parent-class)
+ "Insert final class declaration for PACKAGE and CLASS."
+ (interactive
+ (append (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class)
+ (gnome-c-snippet--read-package-and-class
+ "Parent package (CamelCase): "
+ "Parent class (CamelCase): "
+ 'gnome-c-snippet-parent-package
+ 'gnome-c-snippet-parent-class)))
+ (gnome-c-snippet--insert-class-declaration package
+ class
+ parent-package
+ parent-class
+ nil))
+
+(defun gnome-c-snippet-insert-derivable-class-declaration (package
+ class
+ parent-package
+ parent-class)
+ "Insert derivable class declaration for PACKAGE and CLASS."
+ (interactive
+ (append (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class)
+ (gnome-c-snippet--read-package-and-class
+ "Parent package (CamelCase): "
+ "Parent class (CamelCase): "
+ 'gnome-c-snippet-parent-package
+ 'gnome-c-snippet-parent-class)))
+ (gnome-c-snippet--insert-class-declaration package
+ class
+ parent-package
+ parent-class
+ t))
+
+(defun gnome-c-snippet-insert-interface-definition (package
+ iface
+ parent-package
+ parent-class)
+ "Insert class definition for PACKAGE and CLASS."
+ (interactive
+ (append (gnome-c-snippet--read-package-and-class
+ nil
+ "Interface (CamelCase): "
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class)
+ (gnome-c-snippet--read-package-and-class
+ "Parent package (CamelCase): "
+ "Parent class (CamelCase): "
+ 'gnome-c-snippet-parent-package
+ 'gnome-c-snippet-parent-class)))
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package iface) "_default_init ("
(gnome-c-snippet--format-PackageClass package iface) "Interface *iface) {
+}
+
+G_DEFINE_INTERFACE (" (gnome-c-snippet--format-PackageClass package iface) ", "
+(gnome-c-snippet--format-package_class package iface) ", "
(gnome-c-snippet--format-PACKAGE parent-package) "_TYPE_"
(gnome-c-snippet--format-CLASS parent-class) ")
+"))
+
+(defun gnome-c-snippet--insert-class-definition (package
+ class
+ parent-package
+ parent-class
+ abstract)
+ (insert "\
+G_DEFINE_" (if abstract "ABSTRACT_" "") "TYPE ("
(gnome-c-snippet--format-PackageClass package class) ", "
+(gnome-c-snippet--format-package_class package class) ", "
(gnome-c-snippet--format-PACKAGE parent-package) "_TYPE_"
(gnome-c-snippet--format-CLASS parent-class) ")
+
+static void
+" (gnome-c-snippet--format-package_class package class) "_class_init ("
(gnome-c-snippet--format-PackageClass package class) "Class *klass)
+{
+}
+
+static void
+" (gnome-c-snippet--format-package_class package class) "_init ("
(gnome-c-snippet--format-PackageClass package class) " *self)
+{
+}
+"))
+
+(defun gnome-c-snippet-insert-class-definition (package
+ class
+ parent-package
+ parent-class)
+ "Insert class definition for PACKAGE and CLASS."
+ (interactive
+ (append (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class)
+ (gnome-c-snippet--read-package-and-class
+ "Parent package (CamelCase): "
+ "Parent class (CamelCase): "
+ 'gnome-c-snippet-parent-package
+ 'gnome-c-snippet-parent-class)))
+ (gnome-c-snippet--insert-class-definition package
+ class
+ parent-package
+ parent-class
+ nil))
+
+(defun gnome-c-snippet-insert-abstract-class-definition (package
+ class
+ parent-package
+ parent-class)
+ "Insert abstract class definition for PACKAGE and CLASS."
+ (interactive
+ (append (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class)
+ (gnome-c-snippet--read-package-and-class
+ "Parent package (CamelCase): "
+ "Parent class (CamelCase): "
+ 'gnome-c-snippet-parent-package
+ 'gnome-c-snippet-parent-class)))
+ (gnome-c-snippet--insert-class-definition package
+ class
+ parent-package
+ parent-class
+ t))
+
+(defun gnome-c-snippet-insert-constructor (package class)
+ "Insert 'constructor' vfunc of GObjectClass for PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (arglist-start body-start)
+ (insert "\
+static GObject *
+" (gnome-c-snippet--format-package_class package class) "_constructor (")
+ (setq arglist-start (point-marker))
+ (insert "GType *object,
+guint n_construct_properties,
+GObjectConstructParam *construct_properties)\n")
+ (setq body-start (point-marker))
+ (if gnome-c-snippet-align-arglist
+ (progn
+ (goto-char arglist-start)
+ (gnome-c-align-arglist-at-point))
+ (indent-region arglist-start (point)))
+ (goto-char body-start)
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class)
"_parent_class)->constructed (type, n_construct_properties,
construct_properties);
+}
+")
+ (indent-region body-start (point))))
+
+(defun gnome-c-snippet-insert-set_property (package class)
+ "Insert 'set_property' vfunc of GObjectClass for PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (arglist-start body-start)
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package class) "_set_property (")
+ (setq arglist-start (point-marker))
+ (insert "GObject *object,
+guint prop_id,
+const GValue *value,
+GParamSpec *pspec)\n")
+ (setq body-start (point-marker))
+ (if gnome-c-snippet-align-arglist
+ (progn
+ (goto-char arglist-start)
+ (gnome-c-align-arglist-at-point))
+ (indent-region arglist-start (point)))
+ (goto-char body-start)
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+")
+ (indent-region body-start (point))))
+
+(defun gnome-c-snippet-insert-get_property (package class)
+ "Insert 'get_property' vfunc of GObjectClass for PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (arglist-start body-start)
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package class) "_get_property (")
+ (setq arglist-start (point-marker))
+ (insert "GObject *object,
+guint prop_id,
+GValue *value,
+GParamSpec *pspec)\n")
+ (setq body-start (point-marker))
+ (if gnome-c-snippet-align-arglist
+ (progn
+ (goto-char arglist-start)
+ (gnome-c-align-arglist-at-point))
+ (indent-region arglist-start (point)))
+ (goto-char body-start)
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+")
+ (indent-region body-start (point))))
+
+(defun gnome-c-snippet-insert-dispose (package class)
+ "Insert 'dispose' vfunc of GObjectClass for PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (body-start)
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package class) "_dispose (GObject
*object)\n")
+ (setq body-start (point-marker))
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class)
"_parent_class)->dispose (object);
+}
+")
+ (indent-region body-start (point))))
+
+(defun gnome-c-snippet-insert-finalize (package class)
+ "Insert 'finalize' vfunc of GObjectClass for PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (body-start)
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package class) "_finalize (GObject
*object)\n")
+ (setq body-start (point-marker))
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class)
"_parent_class)->finalize (object);
+}
+")
+ (indent-region body-start (point))))
+
+(defun gnome-c-snippet-insert-dispatch_properties_changed (package class)
+ "Insert 'dispatch_properties_changed vfunc of GObjectClass for
+PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (arglist-start body-start)
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package class)
"_dispatch_properties_changed (")
+ (setq arglist-start (point-marker))
+ (insert "GObject *object,
+guint n_pspecs,
+GParamSpec **pspecs)\n")
+ (setq body-start (point-marker))
+ (if gnome-c-snippet-align-arglist
+ (progn
+ (goto-char arglist-start)
+ (gnome-c-align-arglist-at-point))
+ (indent-region arglist-start (point)))
+ (goto-char body-start)
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class)
"_parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
+}
+")
+ (indent-region body-start (point))))
+
+(defun gnome-c-snippet-insert-notify (package class)
+ "Insert 'notify' vfunc of GObjectClass for PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (arglist-start body-start)
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package class) "_notify (")
+ (setq arglist-start (point-marker))
+ (insert "GObject *object,
+GParamSpec *pspec)\n")
+ (setq body-start (point-marker))
+ (if gnome-c-snippet-align-arglist
+ (progn
+ (goto-char arglist-start)
+ (gnome-c-align-arglist-at-point))
+ (indent-region arglist-start (point)))
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class)
"_parent_class)->notify (object, pspec);
+}
+")
+ (indent-region body-start (point))))
+
+(defun gnome-c-snippet-insert-constructed (package class)
+ "Insert 'constructed' vfunc of GObjectClass for PACKAGE and CLASS."
+ (interactive
+ (gnome-c-snippet--read-package-and-class
+ nil nil
+ 'gnome-c-snippet-package
+ 'gnome-c-snippet-class))
+ (let (body-start)
+ (insert "\
+static void
+" (gnome-c-snippet--format-package_class package class) "_constructed (GObject
*object)\n")
+ (setq body-start (point-marker))
+ (insert "{
+ " (gnome-c-snippet--format-PackageClass package class) " *self = "
+ (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
+
+ G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class)
"_parent_class)->constructed (object);
+}
+")
+ (indent-region body-start (point))))
+
+(defvar gnome-c-snippet-snippet-commands
+ '(("G_DECLARE_INTERFACE" . gnome-c-snippet-insert-interface-declaration)
+ ("G_DECLARE_FINAL_TYPE" . gnome-c-snippet-insert-final-class-declaration)
+ ("G_DECLARE_DERIVABLE_TYPE" .
+ gnome-c-snippet-insert-derivable-class-declaration)
+ ("G_DEFINE_INTERFACE" . gnome-c-snippet-insert-interface-definition)
+ ("G_DEFINE_TYPE" . gnome-c-snippet-insert-class-definition)
+ ("G_DEFINE_ABSTRACT_TYPE" .
+ gnome-c-snippet-insert-abstract-class-definition)
+ ("GObjectClass.constructor" . gnome-c-snippet-insert-constructor)
+ ("GObjectClass.set_property" . gnome-c-snippet-insert-set_property)
+ ("GObjectClass.get_property" . gnome-c-snippet-insert-get_property)
+ ("GObjectClass.dispose" . gnome-c-snippet-insert-dispose)
+ ("GObjectClass.finalize" . gnome-c-snippet-insert-finalize)
+ ("GObjectClass.dispatch_properties_changed" .
+ gnome-c-snippet-insert-dispatch_properties_changed)
+ ("GObjectClass.notify" . gnome-c-snippet-insert-notify)
+ ("GObjectClass.contructed" . gnome-c-snippet-insert-constructed)))
+
+;;;###autoload
+(defun gnome-c-snippet-insert (snippet)
+ (interactive
+ (list (completing-read "Snippet: " gnome-c-snippet-snippet-commands nil t)))
+ (let ((entry (assoc snippet gnome-c-snippet-snippet-commands)))
+ (unless entry
+ (error "Unknown snippet: %s" snippet))
+ (call-interactively (cdr entry))))
+
+(provide 'gnome-c-snippet)
+
+;;; gnome-c-snippet.el ends here
diff --git a/packages/gnome-c-style/gnome-c-style.el
b/packages/gnome-c-style/gnome-c-style.el
new file mode 100644
index 0000000..589de3c
--- /dev/null
+++ b/packages/gnome-c-style/gnome-c-style.el
@@ -0,0 +1,75 @@
+;;; gnome-c-style.el --- minor mode for editing GNOME-style C source code -*-
lexical-binding: t; -*-
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <address@hidden>
+;; Keywords: GNOME, C, coding style
+;; Version: 0.1
+;; Maintainer: Daiki Ueno <address@hidden>
+
+;; This file is not part of GNU Emacs.
+
+;; 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:
+
+;; This package provides a minor mode to help editing C source code
+;; in the GNOME C coding style:
+;;
+;;
<https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en#header-files>
+;;
<https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en#functions>
+;;
+;; It basically provides two functions: code alignment and snippet
+;; insertion. To align code, use `gnome-c-style-align-region' to
+;; line-up multiple function declarations in region, and
+;; `gnome-c-style-align-at-point' to line-up arguments in the argument
+;; list at point.
+;;
+;; To insert code snippet, use `gnome-c-snippet-insert'. The command
+;; will let you choose a template to be inserted. This package also
+;; provide commands to insert package/class names in upper case,
+;; capital case, and lower case. For complete list of commands, do
+;; M-x describe-bindings.
+
+;;; Code:
+
+(require 'gnome-c-align)
+(require 'gnome-c-snippet)
+
+(defgroup gnome-c-style nil
+ "GNOME-style C source code editing"
+ :prefix "gnome-c-"
+ :group 'c)
+
+(defvar gnome-c-style-mode-map
+ (let ((keymap (make-sparse-keymap)))
+ (define-key keymap "\C-c\C-ga" 'gnome-c-align-arglist-at-point)
+ (define-key keymap "\C-c\C-gr" 'gnome-c-align-decls-region)
+ (define-key keymap "\C-c\C-gf" 'gnome-c-align-set-column)
+ (define-key keymap "\C-c\C-gg" 'gnome-c-align-guess-columns)
+ (define-key keymap "\C-c\C-g\C-g" 'gnome-c-align-guess-optimal-columns)
+ (define-key keymap "\C-c\C-gc" 'gnome-c-snippet-insert-package_class)
+ (define-key keymap "\C-c\C-gC" 'gnome-c-snippet-insert-PACKAGE_CLASS)
+ (define-key keymap "\C-c\C-g\C-c" 'gnome-c-snippet-insert-PackageClass)
+ (define-key keymap "\C-c\C-gs" 'gnome-c-snippet-insert)
+ keymap))
+
+;;;###autoload
+(define-minor-mode gnome-c-style-mode
+ "A minor-mode for editing GNOME-style C source code."
+ nil " GNOME" gnome-c-style-mode-map)
+
+(provide 'gnome-c-style)
+
+;;; gnome-c-style.el ends here
diff --git a/packages/gnome-c-style/gnome-c-tests.el
b/packages/gnome-c-style/gnome-c-tests.el
new file mode 100644
index 0000000..3b48463
--- /dev/null
+++ b/packages/gnome-c-style/gnome-c-tests.el
@@ -0,0 +1,191 @@
+(require 'gnome-c-align)
+
+(defconst gnome-c-test-program-1 "\
+GGpgCtx *g_gpg_ctx_new (GError **error);
+
+typedef void (*GGpgProgressCallback) (gpointer user_data,
+ const gchar *what,
+ gint type,
+ gint current,
+ gint total);
+
+void g_gpg_ctx_set_progress_callback (GGpgCtx *ctx,
+ GGpgProgressCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_data);
+void g_gpg_ctx_add_signer (GGpgCtx *ctx, GGpgKey *key);
+guint g_gpg_ctx_get_n_signers (GGpgCtx *ctx);
+GGpgKey *g_gpg_ctx_get_signer (GGpgCtx *ctx, guint index);
+void g_gpg_ctx_clear_signers (GGpgCtx *ctx);
+")
+
+(defconst gnome-c-test-program-1-aligned "\
+GGpgCtx *g_gpg_ctx_new (GError **error);
+
+typedef void (*GGpgProgressCallback) (gpointer user_data,
+ const gchar *what,
+ gint type,
+ gint current,
+ gint total);
+
+void g_gpg_ctx_set_progress_callback (GGpgCtx *ctx,
+ GGpgProgressCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_data);
+void g_gpg_ctx_add_signer (GGpgCtx *ctx,
+ GGpgKey *key);
+guint g_gpg_ctx_get_n_signers (GGpgCtx *ctx);
+GGpgKey *g_gpg_ctx_get_signer (GGpgCtx *ctx,
+ guint index);
+void g_gpg_ctx_clear_signers (GGpgCtx *ctx);
+")
+
+(defconst gnome-c-test-program-2 "\
+GDK_AVAILABLE_IN_3_16
+const gchar ** gtk_widget_list_action_prefixes (GtkWidget
*widget);
+")
+
+(defconst gnome-c-test-program-3 "\
+ /* overridable methods */
+ void (*set_property) (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+ void (*get_property) (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+")
+
+(defconst gnome-c-test-program-4 "\
+FOO_AVAILABLE_IN_ALL
+int foo (struct foo ***a, int b, ...) G_GNUC_CONST;
+")
+
+(defconst gnome-c-test-program-4-aligned "\
+FOO_AVAILABLE_IN_ALL
+int foo (struct foo ***a,
+ int b,
+ ...) G_GNUC_CONST;
+")
+
+(defconst gnome-c-test-program-5 "\
+int * bar (const char * const * * a, int b);
+")
+
+(defconst gnome-c-test-program-5-aligned "\
+int *bar (const char * const **a,
+ int b);
+")
+
+(defconst gnome-c-test-program-6 "\
+int foo (char **a, int b);
+type_1234567890 bar (char a, int b);
+int identifier_1234567890 (double a, double b);
+")
+
+(defconst gnome-c-test-program-6-aligned-1 "\
+int foo
+ (char **a,
+ int b);
+type_1234567890 bar
+ (char a,
+ int b);
+int identifier_1234567890
+ (double a,
+ double b);
+")
+
+(defconst gnome-c-test-program-6-aligned-2 "\
+int foo (char **a,
+ int b);
+type_1234567890 bar (char a,
+ int b);
+int identifier_1234567890
+ (double a,
+ double b);
+")
+
+(ert-deftest gnome-c-test-align--guess-optimal-columns ()
+ "Tests the `gnome-c-align--guess-optimal-columns'."
+ (with-temp-buffer
+ (insert gnome-c-test-program-1)
+ (c-mode)
+ (let* (gnome-c-align-max-column
+ (columns
+ (gnome-c-align--guess-optimal-columns (point-min) (point-max))))
+ (should (= (cdr (assq 'identifier-start-column columns)) 9))
+ (should (= (cdr (assq 'arglist-start-column columns)) 41))
+ (should (= (cdr (assq 'arglist-identifier-start-column columns)) 64)))))
+
+(ert-deftest gnome-c-test-align-region ()
+ "Tests the `gnome-c-align-decls-region'."
+ (with-temp-buffer
+ (insert gnome-c-test-program-1)
+ (c-mode)
+ (let (gnome-c-align-max-column)
+ (gnome-c-align-guess-optimal-columns (point-min) (point-max))
+ (gnome-c-align-decls-region (point-min) (point-max)))
+ (should (equal (buffer-string) gnome-c-test-program-1-aligned))))
+
+(ert-deftest gnome-c-test-align-region-2 ()
+ "Tests the `gnome-c-align-decls-region'."
+ (with-temp-buffer
+ (insert gnome-c-test-program-4)
+ (c-mode)
+ (let (gnome-c-align-max-column)
+ (gnome-c-align-guess-optimal-columns (point-min) (point-max))
+ (gnome-c-align-decls-region (point-min) (point-max)))
+ (should (equal (buffer-string) gnome-c-test-program-4-aligned))))
+
+(ert-deftest gnome-c-test-align-region-3 ()
+ "Tests the `gnome-c-align-decls-region'."
+ (with-temp-buffer
+ (insert gnome-c-test-program-5)
+ (c-mode)
+ (let (gnome-c-align-max-column)
+ (gnome-c-align-guess-optimal-columns (point-min) (point-max))
+ (gnome-c-align-decls-region (point-min) (point-max)))
+ (should (equal (buffer-string) gnome-c-test-program-5-aligned))))
+
+(ert-deftest gnome-c-test-align-region-4 ()
+ "Tests the `gnome-c-align-decls-region', with max columns set."
+ (with-temp-buffer
+ (insert gnome-c-test-program-6)
+ (c-mode)
+ (let ((gnome-c-align-max-column 20))
+ (gnome-c-align-guess-optimal-columns (point-min) (point-max))
+ (gnome-c-align-decls-region (point-min) (point-max)))
+ (should (equal (buffer-string) gnome-c-test-program-6-aligned-1))))
+
+(ert-deftest gnome-c-test-align-region-5 ()
+ "Tests the `gnome-c-align-decls-region', with max columns set."
+ (with-temp-buffer
+ (insert gnome-c-test-program-6)
+ (c-mode)
+ (let ((gnome-c-align-max-column 30))
+ (gnome-c-align-guess-optimal-columns (point-min) (point-max))
+ (gnome-c-align-decls-region (point-min) (point-max)))
+ (should (equal (buffer-string) gnome-c-test-program-6-aligned-2))))
+
+(ert-deftest gnome-c-test-align-guess-columns-1 ()
+ "Tests the `gnome-c-align-guess-columns'."
+ (with-temp-buffer
+ (insert gnome-c-test-program-2)
+ (c-mode)
+ (let (gnome-c-align-max-column)
+ (gnome-c-align-guess-columns (point-min) (point-max)))
+ (should (= gnome-c-align-identifier-start-column 24))
+ (should (= gnome-c-align-arglist-start-column 56))
+ (should (= gnome-c-align-arglist-identifier-start-column 80))))
+
+(ert-deftest gnome-c-test-align-guess-columns-2 ()
+ "Tests the `gnome-c-align-guess-columns'."
+ (with-temp-buffer
+ (insert gnome-c-test-program-3)
+ (c-mode)
+ (let (gnome-c-align-max-column)
+ (gnome-c-align-guess-columns (point-min) (point-max)))
+ (should (= gnome-c-align-identifier-start-column 13))
+ (should (= gnome-c-align-arglist-start-column 40))
+ (should (= gnome-c-align-arglist-identifier-start-column 57))))