branch: master commit 1abce8eb7d46cfcbb571784260b6882b16b7f9f1 Merge: c281465 d827bb5 Author: Daiki Ueno <u...@gnu.org> Commit: Daiki Ueno <u...@gnu.org>
Merge commit 'd827bb511203a64da3ae5cc6910b87b7c99d233b' --- packages/gnome-c-style/README.md | 49 ++-- packages/gnome-c-style/gnome-c-align.el | 16 +- packages/gnome-c-style/gnome-c-snippet.el | 485 ++++++++++++++++++---------- packages/gnome-c-style/gnome-c-tests.el | 70 ++++ 4 files changed, 422 insertions(+), 198 deletions(-) diff --git a/packages/gnome-c-style/README.md b/packages/gnome-c-style/README.md index 86b79a7..69532eb 100644 --- a/packages/gnome-c-style/README.md +++ b/packages/gnome-c-style/README.md @@ -1,13 +1,15 @@ gnome-c-style ====== -gnome-c-style is an Emacs minor mode for editing C source code in [GNOME C coding style](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en). In particular, it is useful to properly line-up [function arguments](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en#functions) and [function declarations in header files](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en#functions). +gnome-c-style is an Emacs minor mode for editing C source code in [GNOME C coding style](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en). +In particular, it is useful to properly line-up [function arguments](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en#functions) and +[function declarations in header files](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en#header-files). Install ------ -* M-x package-install gnome-c-style -* Add the following lines to ~/.emacs/init.el: +* `M-x package-install gnome-c-style` +* Add the following line to `~/.emacs.d/init.el`: ``` (add-hook 'c-mode-hook 'gnome-c-style-mode) @@ -22,10 +24,10 @@ Usage | 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 f | 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 @@ -51,18 +53,18 @@ 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 +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 +identifier-start: 9, arglist-start: 41, arglist-identifier-start: 64 ``` -Then, mark the region again, type ```C-c C-g r```, and you will get -the code aligned: +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); +GGpgCtx *g_gpg_ctx_new (GError **error); typedef void (*GGpgProgressCallback) (gpointer user_data, const gchar *what, @@ -70,16 +72,17 @@ typedef void (*GGpgProgressCallback) (gpointer user_data, 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); +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. +Note that the `typedef` statement 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 index 446b48f..734800a 100644 --- a/packages/gnome-c-style/gnome-c-align.el +++ b/packages/gnome-c-style/gnome-c-align.el @@ -493,7 +493,19 @@ This sets `gnome-c-align-identifier-start-column', ;;;###autoload (defun gnome-c-align-decls-region (beg end) - "Reformat function declarations in the region between BEG and END." + "Reformat function declarations in the region between BEG and END. + +The `gnome-c-align-identifier-start-column', +`gnome-c-align-arglist-start-column', and +`gnome-c-align-arglist-identifier-start-column' variables +control the widths. + +To set those variables, use \\[gnome-c-align-set-column], +\\[gnome-c-align-guess-columns], or +\\[gnome-c-align-guess-optimal-columns]. + +If they are not set, this function internally calls +\\[gnome-c-align-guess-optimal-columns] before formatting." (interactive "r") (save-excursion (let (decls) @@ -513,8 +525,8 @@ This sets `gnome-c-align-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) + (gnome-c-align--normalize-decl decl) (goto-char (gnome-c-align--decl-identifier-start decl)) (gnome-c-align--indent-to-column gnome-c-align-identifier-start-column) diff --git a/packages/gnome-c-style/gnome-c-snippet.el b/packages/gnome-c-style/gnome-c-snippet.el index 239f148..95c5f6d 100644 --- a/packages/gnome-c-style/gnome-c-snippet.el +++ b/packages/gnome-c-style/gnome-c-snippet.el @@ -26,11 +26,7 @@ ;;; Code: (require 'gnome-c-align) - -(eval-when-compile - (require 'subword)) - -(declare-function subword-forward "subword.el" (&optional arg)) +(require 'subword) (defvar gnome-c-snippet-package nil) (make-variable-buffer-local 'gnome-c-snippet-package) @@ -44,6 +40,11 @@ (defvar gnome-c-snippet-parent-class nil) (make-variable-buffer-local 'gnome-c-snippet-parent-class) +(defconst gnome-c-snippet-guess-name-functions + '(gnome-c-snippet--guess-name-from-header-buffer + gnome-c-snippet--guess-name-from-declaration + gnome-c-snippet--guess-name-from-file-name)) + (defcustom gnome-c-snippet-align-arglist t "Whether to align argument list of the inserted snippet" :type 'boolean @@ -51,11 +52,139 @@ (make-variable-buffer-local 'gnome-c-snippet-align-arglist) +(defun gnome-c-snippet--find-declaration () + (save-excursion + (let (beg end) + (goto-char (point-min)) + (when (re-search-forward + "^G_DECLARE_\\(?:FINAL\\|DERIVABLE\\)_TYPE\\s-*(" + nil t) + (setq beg (match-beginning 0)) + (goto-char (match-end 0)) + (backward-char) + (condition-case nil + (progn + (c-forward-sexp) + (setq end (point))) + (error))) + (when (and beg end) + (list beg end))))) + +(defun gnome-c-snippet--extract-names-from-declaration (beg end) + (save-excursion + (narrow-to-region beg end) + (goto-char (point-min)) + (search-forward "(") + (c-forward-syntactic-ws) + (let ((capitalized-package-class + (buffer-substring-no-properties (point) + (progn + (c-forward-token-2) + (c-backward-syntactic-ws) + (point)))) + uppercased-package uppercased-class + capitalized-package capitalized-class capitalized-parent) + (c-forward-syntactic-ws) + (c-forward-token-2 3) + (setq uppercased-package (split-string + (buffer-substring (point) + (progn + (c-forward-token-2) + (c-backward-syntactic-ws) + (point))) + "_")) + (c-forward-syntactic-ws) + (c-forward-token-2) + (setq uppercased-class (split-string + (buffer-substring (point) + (progn + (c-forward-token-2) + (c-backward-syntactic-ws) + (point))) + "_")) + (c-forward-syntactic-ws) + (c-forward-token-2) + (setq capitalized-parent (gnome-c-snippet--parse-name + (buffer-substring (point) + (progn + (c-forward-token-2) + (c-backward-syntactic-ws) + (point))))) + (catch 'error + (let ((index 0)) + (dolist (uppercased uppercased-package) + (let* ((length (length uppercased)) + (capitalized + (substring capitalized-package-class + index (+ index length)))) + (unless (equal (upcase capitalized) uppercased) + (throw 'error nil)) + (push capitalized capitalized-package) + (setq index (+ index length)))) + (dolist (uppercased uppercased-class) + (let* ((length (length uppercased)) + (capitalized + (substring capitalized-package-class + index (+ index length)))) + (unless (equal (upcase capitalized) uppercased) + (throw 'error nil)) + (push capitalized capitalized-class) + (setq index (+ index length)))))) + (list (nreverse capitalized-package) + (nreverse capitalized-class) + capitalized-parent)))) + +(defun gnome-c-snippet--find-header-buffer () + (pcase (file-name-extension buffer-file-name) + ("h" + (current-buffer)) + ("c" + (let ((header-file-name + (concat (file-name-sans-extension buffer-file-name) ".h"))) + (cl-find-if + (lambda (buffer) + (with-current-buffer buffer + (equal buffer-file-name header-file-name))) + (buffer-list)))))) + +(defun gnome-c-snippet--guess-name-from-header-buffer (symbol) + (let ((header-buffer (gnome-c-snippet--find-header-buffer))) + (when header-buffer + (with-current-buffer header-buffer + (symbol-value (intern (format "gnome-c-snippet-%S" symbol))))))) + +(defun gnome-c-snippet--guess-name-from-declaration (symbol) + (when (memq symbol '(package class parent-package parent-class)) + (let ((header-buffer (gnome-c-snippet--find-header-buffer))) + (when header-buffer + (with-current-buffer header-buffer + (let ((region (gnome-c-snippet--find-declaration)) + names) + (when region + (setq names + (apply #'gnome-c-snippet--extract-names-from-declaration + region)) + (when names + (pcase symbol + (`package (car names)) + (`class (nth 1 names)) + (`parent-package (list (car (nth 2 names)))) + (`parent-class (cdr (nth 2 names)))))))))))) + +(defun gnome-c-snippet--guess-name-from-file-name (symbol) + (when (memq symbol '(package class)) + (let ((filename (file-name-sans-extension + (file-name-nondirectory buffer-file-name)))) + (when (string-match-p "-" filename) + (let ((names (split-string filename "-"))) + (pcase symbol + (`package (list (upcase-initials (car names)))) + (`class (mapcar #'upcase-initials (cdr names))))))))) + (defun gnome-c-snippet--parse-name (name) - (require 'subword) (with-temp-buffer (let (words) - (insert name) + (insert (upcase-initials name)) (goto-char (point-min)) (while (not (eobp)) ;; Skip characters not recognized by subword-mode. @@ -66,28 +195,79 @@ words)) (nreverse words)))) -(defun gnome-c-snippet--read-package-and-class (package-prompt - class-prompt - package-symbol - class-symbol) +(defun gnome-c-snippet--read-name (prompt symbol &optional default) (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 + (not (symbol-value symbol))) + (set 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))) + (read-string prompt + (or (if (symbol-value symbol) + (gnome-c-snippet--format-Package + (symbol-value symbol))) + default))))) + (symbol-value symbol)) + +(defun gnome-c-snippet--read-package-and-class (parent) + (append (list (gnome-c-snippet--read-name + "Package (CamelCase): " + 'gnome-c-snippet-package + (gnome-c-snippet--format-Package + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'package))) + (gnome-c-snippet--read-name + "Class (CamelCase): " + 'gnome-c-snippet-class + (gnome-c-snippet--format-Class + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'class)))) + (when parent + (list (gnome-c-snippet--read-name + "Parent package (CamelCase): " + 'gnome-c-snippet-parent-package + (gnome-c-snippet--format-Package + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'parent-package))) + (gnome-c-snippet--read-name + "Parent class (CamelCase): " + 'gnome-c-snippet-parent-class + (gnome-c-snippet--format-Class + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'parent-class))))))) + +(defun gnome-c-snippet--read-package-and-interface (parent) + (list (gnome-c-snippet--read-name + "Package (CamelCase): " + 'gnome-c-snippet-package + (gnome-c-snippet--format-Package + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'package))) + (gnome-c-snippet--read-name + "Interface (CamelCase): " + 'gnome-c-snippet-class + (gnome-c-snippet--format-Class + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'class))) + (when parent + (list (gnome-c-snippet--read-name + "Parent package (CamelCase): " + 'gnome-c-snippet-parent-package + (gnome-c-snippet--format-Package + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'parent-package))) + (gnome-c-snippet--read-name + "Parent class (CamelCase): " + 'gnome-c-snippet-parent-class + (gnome-c-snippet--format-Class + (run-hook-with-args-until-success + 'gnome-c-snippet-guess-name-functions + 'parent-class))))))) (defun gnome-c-snippet--format-PACKAGE (package) (mapconcat #'upcase package "_")) @@ -118,44 +298,25 @@ ;;;###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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (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))) + (interactive (gnome-c-snippet--read-package-and-interface t)) (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) ", " @@ -178,16 +339,7 @@ G_DECLARE_" (if derivable "DERIVABLE" "FINAL") "_TYPE (" (gnome-c-snippet--forma 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))) + (interactive (gnome-c-snippet--read-package-and-class t)) (gnome-c-snippet--insert-class-declaration package class parent-package @@ -199,16 +351,7 @@ G_DECLARE_" (if derivable "DERIVABLE" "FINAL") "_TYPE (" (gnome-c-snippet--forma 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))) + (interactive (gnome-c-snippet--read-package-and-class t)) (gnome-c-snippet--insert-class-declaration package class parent-package @@ -220,17 +363,7 @@ G_DECLARE_" (if derivable "DERIVABLE" "FINAL") "_TYPE (" (gnome-c-snippet--forma 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))) + (interactive (gnome-c-snippet--read-package-and-interface t)) (insert "\ static void " (gnome-c-snippet--format-package_class package iface) "_default_init (" (gnome-c-snippet--format-PackageClass package iface) "Interface *iface) { @@ -244,71 +377,67 @@ G_DEFINE_INTERFACE (" (gnome-c-snippet--format-PackageClass package iface) ", " class parent-package parent-class - abstract) + abstract + code) (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) ") +G_DEFINE_" (if abstract "ABSTRACT_" "") "TYPE" (if code "WITH_CODE" "") " (" (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) (if code ", " "") ")")) -static void -" (gnome-c-snippet--format-package_class package class) "_class_init (" (gnome-c-snippet--format-PackageClass package class) "Class *klass) -{ -} +(defun gnome-c-snippet-insert-G_DEFINE_TYPE (package + class + parent-package + parent-class) + "Insert G_DEFINE_TYPE for PACKAGE and CLASS." + (interactive (gnome-c-snippet--read-package-and-class t)) + (gnome-c-snippet--insert-class-definition package + class + parent-package + parent-class + nil + nil)) -static void -" (gnome-c-snippet--format-package_class package class) "_init (" (gnome-c-snippet--format-PackageClass package class) " *self) -{ -} -")) +(defun gnome-c-snippet-insert-G_DEFINE_TYPE_WITH_CODE (package + class + parent-package + parent-class) + "Insert G_DEFINE_TYPE_WITH_CODE for PACKAGE and CLASS." + (interactive (gnome-c-snippet--read-package-and-class t)) + (gnome-c-snippet--insert-class-definition package + class + parent-package + parent-class + nil + t)) -(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))) +(defun gnome-c-snippet-insert-G_DEFINE_ABSTRACT_TYPE (package + class + parent-package + parent-class) + "Insert G_DEFINE_ABSTRACT_TYPE for PACKAGE and CLASS." + (interactive (gnome-c-snippet--read-package-and-class t)) (gnome-c-snippet--insert-class-definition package class parent-package parent-class + t 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))) +(defun gnome-c-snippet-insert-G_DEFINE_ABSTRACT_TYPE_WITH_CODE (package + class + parent-package + parent-class) + "Insert G_DEFINE_ABSTRACT_TYPE_WITH_CODE for PACKAGE and CLASS." + (interactive (gnome-c-snippet--read-package-and-class t)) (gnome-c-snippet--insert-class-definition package class parent-package parent-class + t 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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (arglist-start body-start) (insert "\ static GObject * @@ -328,18 +457,14 @@ GObjectConstructParam *construct_properties)\n") " (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); + G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->constructor (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (arglist-start body-start) (insert "\ static void @@ -372,11 +497,7 @@ GParamSpec *pspec)\n") (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (arglist-start body-start) (insert "\ static void @@ -409,11 +530,7 @@ GParamSpec *pspec)\n") (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (body-start) (insert "\ static void @@ -430,11 +547,7 @@ static void (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (body-start) (insert "\ static void @@ -452,11 +565,7 @@ static void (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (arglist-start body-start) (insert "\ static void @@ -483,11 +592,7 @@ GParamSpec **pspecs)\n") (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (arglist-start body-start) (insert "\ static void @@ -512,11 +617,7 @@ GParamSpec *pspec)\n") (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)) + (interactive (gnome-c-snippet--read-package-and-class nil)) (let (body-start) (insert "\ static void @@ -531,15 +632,38 @@ static void ") (indent-region body-start (point)))) +(defun gnome-c-snippet-insert-class-init (package class) + "Insert '_class_init' function for PACKAGE and CLASS." + (interactive (gnome-c-snippet--read-package-and-class nil)) + (insert "\ +static void +" (gnome-c-snippet--format-package_class package class) "_class_init (" (gnome-c-snippet--format-PackageClass package class) "Class *klass)\n") + (insert "{ +} +")) + +(defun gnome-c-snippet-insert-init (package class) + "Insert '_init' function for PACKAGE and CLASS." + (interactive (gnome-c-snippet--read-package-and-class nil)) + (insert "\ +static void +" (gnome-c-snippet--format-package_class package class) "_init (" (gnome-c-snippet--format-PackageClass package class) " *self)\n") + (insert "{ +} +")) + (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_TYPE" . gnome-c-snippet-insert-G_DEFINE_TYPE) + ("G_DEFINE_TYPE_WITH_CODE" . gnome-c-snippet-insert-G_DEFINE_TYPE_WITH_CODE) ("G_DEFINE_ABSTRACT_TYPE" . - gnome-c-snippet-insert-abstract-class-definition) + gnome-c-snippet-insert-G_DEFINE_ABSTRACT_TYPE) + ("G_DEFINE_ABSTRACT_TYPE_WITH_CODE" . + gnome-c-snippet-insert-G_DEFINE_ABSTRACT_TYPE_WITH_CODE) ("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) @@ -548,16 +672,31 @@ static void ("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))) + ("GObjectClass.constructed" . gnome-c-snippet-insert-constructed) + ;; Will be overridden by `gnome-c-snippet-insert'. + ("_class_init" . gnome-c-snippet-insert-class-init) + ;; Will be overridden by `gnome-c-snippet-insert'. + ("_init" . gnome-c-snippet-insert-init))) ;;;###autoload -(defun gnome-c-snippet-insert (snippet) +(defun gnome-c-snippet-insert (command) (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)))) + (let ((commands (copy-tree gnome-c-snippet-snippet-commands))) + (when (and gnome-c-snippet-package gnome-c-snippet-class) + (setcar (assoc "_class_init" commands) + (concat (gnome-c-snippet--format-package_class + gnome-c-snippet-package gnome-c-snippet-class) + "_class_init")) + (setcar (assoc "_init" commands) + (concat (gnome-c-snippet--format-package_class + gnome-c-snippet-package gnome-c-snippet-class) + "_init"))) + (let* ((name (completing-read "Snippet: " commands nil t)) + (entry (assoc name commands))) + (unless entry + (error "Unknown snippet: %s" name)) + (list (cdr entry))))) + (call-interactively command)) (provide 'gnome-c-snippet) diff --git a/packages/gnome-c-style/gnome-c-tests.el b/packages/gnome-c-style/gnome-c-tests.el index a573cd3..17dbfe1 100644 --- a/packages/gnome-c-style/gnome-c-tests.el +++ b/packages/gnome-c-style/gnome-c-tests.el @@ -22,6 +22,7 @@ ;;; Code: (require 'gnome-c-align) +(require 'gnome-c-snippet) (defconst gnome-c-test-program-1 "\ GGpgCtx *g_gpg_ctx_new (GError **error); @@ -129,6 +130,11 @@ int identifier_1234567890 double b); ") +(defconst gnome-c-test-program-7 "\ +G_DECLARE_FINAL_TYPE (GGpgEngineInfo, g_gpg_engine_info, G_GPG, ENGINE_INFO, + GObject) +") + (ert-deftest gnome-c-test-align--guess-optimal-columns () "Tests the `gnome-c-align--guess-optimal-columns'." (with-temp-buffer @@ -212,3 +218,67 @@ int identifier_1234567890 (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)))) + +(ert-deftest gnome-c-test-snippet-guess-name-from-declaration () + "Tests the `gnome-c-snippet--guess-name-from-declaration'." + (with-temp-buffer + (insert gnome-c-test-program-7) + (c-mode) + (setq buffer-file-name "gpgme-glib.h") + (let ((package (gnome-c-snippet--guess-name-from-declaration 'package)) + (class (gnome-c-snippet--guess-name-from-declaration 'class)) + (parent-package + (gnome-c-snippet--guess-name-from-declaration 'parent-package)) + (parent-class + (gnome-c-snippet--guess-name-from-declaration 'parent-class))) + (should (equal package '("G" "Gpg"))) + (should (equal class '("Engine" "Info"))) + (should (equal parent-package '("G"))) + (should (equal parent-class '("Object")))))) + +(ert-deftest gnome-c-test-snippet-guess-name-from-declaration-2 () + "Tests the `gnome-c-snippet--guess-name-from-declaration'." + (let (buffer) + (unwind-protect + (progn + (setq buffer (generate-new-buffer "header")) + (with-current-buffer buffer + (insert gnome-c-test-program-7) + (c-mode) + (setq buffer-file-name "gpgme-glib.h")) + (with-temp-buffer + (c-mode) + (setq buffer-file-name "gpgme-glib.c") + (let ((package + (gnome-c-snippet--guess-name-from-declaration 'package)) + (class + (gnome-c-snippet--guess-name-from-declaration 'class)) + (parent-package + (gnome-c-snippet--guess-name-from-declaration + 'parent-package)) + (parent-class + (gnome-c-snippet--guess-name-from-declaration + 'parent-class))) + (should (equal package '("G" "Gpg"))) + (should (equal class '("Engine" "Info"))) + (should (equal parent-package '("G"))) + (should (equal parent-class '("Object")))))) + (kill-buffer buffer)))) + +(ert-deftest gnome-c-test-snippet-guess-name-from-file-name () + "Tests the `gnome-c-snippet--guess-name-from-file-name'" + (with-temp-buffer + (c-mode) + (setq buffer-file-name "g-gpg-engine-info.c") + (let ((package + (gnome-c-snippet--guess-name-from-file-name 'package)) + (class + (gnome-c-snippet--guess-name-from-file-name 'class)) + (parent-package + (gnome-c-snippet--guess-name-from-file-name 'parent-package)) + (parent-class + (gnome-c-snippet--guess-name-from-file-name 'parent-class))) + (should (equal package '("G"))) + (should (equal class '("Gpg" "Engine" "Info"))) + (should (equal parent-package nil)) + (should (equal parent-class nil)))))