1 ;;; gnome-c-snippet.el --- GNOME-style code generation -*- lexical-binding: t; -*-
2 ;; Copyright (C) 2016 Free Software Foundation, Inc.
4 ;; Author: Daiki Ueno <ueno@gnu.org>
5 ;; Keywords: GNOME, C, coding style
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24 ;; FIXME: The snippets defined here could be rewritten in yasnippet
28 (require 'gnome-c-align)
31 (defvar gnome-c-snippet-package nil)
32 (make-variable-buffer-local 'gnome-c-snippet-package)
34 (defvar gnome-c-snippet-class nil)
35 (make-variable-buffer-local 'gnome-c-snippet-class)
37 (defvar gnome-c-snippet-parent-package nil)
38 (make-variable-buffer-local 'gnome-c-snippet-parent-package)
40 (defvar gnome-c-snippet-parent-class nil)
41 (make-variable-buffer-local 'gnome-c-snippet-parent-class)
43 (defcustom gnome-c-snippet-align-arglist t
44 "Whether to align argument list of the inserted snippet"
46 :group 'gnome-c-style)
48 (make-variable-buffer-local 'gnome-c-snippet-align-arglist)
50 (defun gnome-c-snippet--parse-name (name)
53 (insert (upcase-initials name))
54 (goto-char (point-min))
56 ;; Skip characters not recognized by subword-mode.
57 (if (looking-at "[^[:lower:][:upper:][:digit:]]+")
58 (goto-char (match-end 0)))
59 (push (buffer-substring (point) (progn (subword-forward 1)
64 (defun gnome-c-snippet--read-name (prompt symbol &optional default)
65 (when (or current-prefix-arg
66 (not (symbol-value symbol)))
68 (gnome-c-snippet--parse-name
70 (or (if (symbol-value symbol)
71 (gnome-c-snippet--format-Package
72 (symbol-value symbol)))
74 (symbol-value symbol))
76 (defun gnome-c-snippet--read-package-and-class (parent)
77 (append (list (gnome-c-snippet--read-name
78 "Package (CamelCase): "
79 'gnome-c-snippet-package)
80 (gnome-c-snippet--read-name
82 'gnome-c-snippet-class))
84 (list (gnome-c-snippet--read-name
85 "Parent package (CamelCase): "
86 'gnome-c-snippet-parent-package)
87 (gnome-c-snippet--read-name
88 "Parent class (CamelCase): "
89 'gnome-c-snippet-parent-class)))))
91 (defun gnome-c-snippet--read-package-and-interface (parent)
92 (list (gnome-c-snippet--read-name
93 "Package (CamelCase): "
94 'gnome-c-snippet-package)
95 (gnome-c-snippet--read-name
96 "Interface (CamelCase): "
97 'gnome-c-snippet-class)
99 (list (gnome-c-snippet--read-name
100 "Parent package (CamelCase): "
101 'gnome-c-snippet-parent-package)
102 (gnome-c-snippet--read-name
103 "Parent class (CamelCase): "
104 'gnome-c-snippet-parent-class)))))
106 (defun gnome-c-snippet--format-PACKAGE (package)
107 (mapconcat #'upcase package "_"))
108 (defalias 'gnome-c-snippet--format-CLASS 'gnome-c-snippet--format-PACKAGE)
110 (defun gnome-c-snippet--format-PACKAGE_CLASS (package class)
111 (concat (gnome-c-snippet--format-PACKAGE package)
113 (gnome-c-snippet--format-CLASS class)))
115 (defun gnome-c-snippet--format-package (package)
116 (mapconcat #'downcase package "_"))
117 (defalias 'gnome-c-snippet--format-class 'gnome-c-snippet--format-package)
119 (defun gnome-c-snippet--format-package_class (package class)
120 (concat (gnome-c-snippet--format-package package)
122 (gnome-c-snippet--format-class class)))
124 (defun gnome-c-snippet--format-Package (package)
125 (mapconcat #'identity package ""))
126 (defalias 'gnome-c-snippet--format-Class 'gnome-c-snippet--format-Package)
128 (defun gnome-c-snippet--format-PackageClass (package class)
129 (concat (gnome-c-snippet--format-Package package)
130 (gnome-c-snippet--format-Class class)))
133 (defun gnome-c-snippet-insert-package_class (package class)
134 "Insert the class name before the current point."
135 (interactive (gnome-c-snippet--read-package-and-class nil))
136 (insert (gnome-c-snippet--format-package_class package class)))
139 (defun gnome-c-snippet-insert-PACKAGE_CLASS (package class)
140 "Insert the class name before the current point."
141 (interactive (gnome-c-snippet--read-package-and-class nil))
142 (insert (gnome-c-snippet--format-PACKAGE_CLASS package class)))
145 (defun gnome-c-snippet-insert-PackageClass (package class)
146 "Insert the class name (in CamelCase) before the current point."
147 (interactive (gnome-c-snippet--read-package-and-class nil))
148 (insert (gnome-c-snippet--format-PackageClass package class)))
150 (defun gnome-c-snippet-insert-interface-declaration (package iface
151 parent-package parent-class)
152 "Insert interface declaration for PACKAGE and IFACE"
153 (interactive (gnome-c-snippet--read-package-and-interface t))
155 #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 ())
156 G_DECLARE_INTERFACE (" (gnome-c-snippet--format-PackageClass package iface) ", "
157 (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) ")
160 (defun gnome-c-snippet--insert-class-declaration (package
166 #define " (gnome-c-snippet--format-PACKAGE package) "_TYPE_" (gnome-c-snippet--format-CLASS class) " (" (gnome-c-snippet--format-package_class package class) "_get_type ())
167 G_DECLARE_" (if derivable "DERIVABLE" "FINAL") "_TYPE (" (gnome-c-snippet--format-PackageClass package class) ", "
168 (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) ")
171 (defun gnome-c-snippet-insert-final-class-declaration (package
175 "Insert final class declaration for PACKAGE and CLASS."
176 (interactive (gnome-c-snippet--read-package-and-class t))
177 (gnome-c-snippet--insert-class-declaration package
183 (defun gnome-c-snippet-insert-derivable-class-declaration (package
187 "Insert derivable class declaration for PACKAGE and CLASS."
188 (interactive (gnome-c-snippet--read-package-and-class t))
189 (gnome-c-snippet--insert-class-declaration package
195 (defun gnome-c-snippet-insert-interface-definition (package
199 "Insert class definition for PACKAGE and CLASS."
200 (interactive (gnome-c-snippet--read-package-and-interface t))
203 " (gnome-c-snippet--format-package_class package iface) "_default_init (" (gnome-c-snippet--format-PackageClass package iface) "Interface *iface) {
206 G_DEFINE_INTERFACE (" (gnome-c-snippet--format-PackageClass package iface) ", "
207 (gnome-c-snippet--format-package_class package iface) ", " (gnome-c-snippet--format-PACKAGE parent-package) "_TYPE_" (gnome-c-snippet--format-CLASS parent-class) ")
210 (defun gnome-c-snippet--insert-class-definition (package
216 G_DEFINE_" (if abstract "ABSTRACT_" "") "TYPE (" (gnome-c-snippet--format-PackageClass package class) ", "
217 (gnome-c-snippet--format-package_class package class) ", " (gnome-c-snippet--format-PACKAGE parent-package) "_TYPE_" (gnome-c-snippet--format-CLASS parent-class) ")
220 " (gnome-c-snippet--format-package_class package class) "_class_init (" (gnome-c-snippet--format-PackageClass package class) "Class *klass)
225 " (gnome-c-snippet--format-package_class package class) "_init (" (gnome-c-snippet--format-PackageClass package class) " *self)
230 (defun gnome-c-snippet-insert-class-definition (package
234 "Insert class definition for PACKAGE and CLASS."
235 (interactive (gnome-c-snippet--read-package-and-class t))
236 (gnome-c-snippet--insert-class-definition package
242 (defun gnome-c-snippet-insert-abstract-class-definition (package
246 "Insert abstract class definition for PACKAGE and CLASS."
247 (interactive (gnome-c-snippet--read-package-and-class t))
248 (gnome-c-snippet--insert-class-definition package
254 (defun gnome-c-snippet-insert-constructor (package class)
255 "Insert 'constructor' vfunc of GObjectClass for PACKAGE and CLASS."
256 (interactive (gnome-c-snippet--read-package-and-class nil))
257 (let (arglist-start body-start)
260 " (gnome-c-snippet--format-package_class package class) "_constructor (")
261 (setq arglist-start (point-marker))
262 (insert "GType *object,
263 guint n_construct_properties,
264 GObjectConstructParam *construct_properties)\n")
265 (setq body-start (point-marker))
266 (if gnome-c-snippet-align-arglist
268 (goto-char arglist-start)
269 (gnome-c-align-arglist-at-point))
270 (indent-region arglist-start (point)))
271 (goto-char body-start)
273 " (gnome-c-snippet--format-PackageClass package class) " *self = "
274 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
276 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->constructor (type, n_construct_properties, construct_properties);
279 (indent-region body-start (point))))
281 (defun gnome-c-snippet-insert-set_property (package class)
282 "Insert 'set_property' vfunc of GObjectClass for PACKAGE and CLASS."
283 (interactive (gnome-c-snippet--read-package-and-class nil))
284 (let (arglist-start body-start)
287 " (gnome-c-snippet--format-package_class package class) "_set_property (")
288 (setq arglist-start (point-marker))
289 (insert "GObject *object,
292 GParamSpec *pspec)\n")
293 (setq body-start (point-marker))
294 (if gnome-c-snippet-align-arglist
296 (goto-char arglist-start)
297 (gnome-c-align-arglist-at-point))
298 (indent-region arglist-start (point)))
299 (goto-char body-start)
301 " (gnome-c-snippet--format-PackageClass package class) " *self = "
302 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
307 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
312 (indent-region body-start (point))))
314 (defun gnome-c-snippet-insert-get_property (package class)
315 "Insert 'get_property' vfunc of GObjectClass for PACKAGE and CLASS."
316 (interactive (gnome-c-snippet--read-package-and-class nil))
317 (let (arglist-start body-start)
320 " (gnome-c-snippet--format-package_class package class) "_get_property (")
321 (setq arglist-start (point-marker))
322 (insert "GObject *object,
325 GParamSpec *pspec)\n")
326 (setq body-start (point-marker))
327 (if gnome-c-snippet-align-arglist
329 (goto-char arglist-start)
330 (gnome-c-align-arglist-at-point))
331 (indent-region arglist-start (point)))
332 (goto-char body-start)
334 " (gnome-c-snippet--format-PackageClass package class) " *self = "
335 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
340 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
345 (indent-region body-start (point))))
347 (defun gnome-c-snippet-insert-dispose (package class)
348 "Insert 'dispose' vfunc of GObjectClass for PACKAGE and CLASS."
349 (interactive (gnome-c-snippet--read-package-and-class nil))
353 " (gnome-c-snippet--format-package_class package class) "_dispose (GObject *object)\n")
354 (setq body-start (point-marker))
356 " (gnome-c-snippet--format-PackageClass package class) " *self = "
357 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
359 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->dispose (object);
362 (indent-region body-start (point))))
364 (defun gnome-c-snippet-insert-finalize (package class)
365 "Insert 'finalize' vfunc of GObjectClass for PACKAGE and CLASS."
366 (interactive (gnome-c-snippet--read-package-and-class nil))
370 " (gnome-c-snippet--format-package_class package class) "_finalize (GObject *object)\n")
371 (setq body-start (point-marker))
373 " (gnome-c-snippet--format-PackageClass package class) " *self = "
374 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
376 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->finalize (object);
379 (indent-region body-start (point))))
381 (defun gnome-c-snippet-insert-dispatch_properties_changed (package class)
382 "Insert 'dispatch_properties_changed vfunc of GObjectClass for
384 (interactive (gnome-c-snippet--read-package-and-class nil))
385 (let (arglist-start body-start)
388 " (gnome-c-snippet--format-package_class package class) "_dispatch_properties_changed (")
389 (setq arglist-start (point-marker))
390 (insert "GObject *object,
392 GParamSpec **pspecs)\n")
393 (setq body-start (point-marker))
394 (if gnome-c-snippet-align-arglist
396 (goto-char arglist-start)
397 (gnome-c-align-arglist-at-point))
398 (indent-region arglist-start (point)))
399 (goto-char body-start)
401 " (gnome-c-snippet--format-PackageClass package class) " *self = "
402 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
404 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
407 (indent-region body-start (point))))
409 (defun gnome-c-snippet-insert-notify (package class)
410 "Insert 'notify' vfunc of GObjectClass for PACKAGE and CLASS."
411 (interactive (gnome-c-snippet--read-package-and-class nil))
412 (let (arglist-start body-start)
415 " (gnome-c-snippet--format-package_class package class) "_notify (")
416 (setq arglist-start (point-marker))
417 (insert "GObject *object,
418 GParamSpec *pspec)\n")
419 (setq body-start (point-marker))
420 (if gnome-c-snippet-align-arglist
422 (goto-char arglist-start)
423 (gnome-c-align-arglist-at-point))
424 (indent-region arglist-start (point)))
426 " (gnome-c-snippet--format-PackageClass package class) " *self = "
427 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
429 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->notify (object, pspec);
432 (indent-region body-start (point))))
434 (defun gnome-c-snippet-insert-constructed (package class)
435 "Insert 'constructed' vfunc of GObjectClass for PACKAGE and CLASS."
436 (interactive (gnome-c-snippet--read-package-and-class nil))
440 " (gnome-c-snippet--format-package_class package class) "_constructed (GObject *object)\n")
441 (setq body-start (point-marker))
443 " (gnome-c-snippet--format-PackageClass package class) " *self = "
444 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
446 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->constructed (object);
449 (indent-region body-start (point))))
451 (defvar gnome-c-snippet-snippet-commands
452 '(("G_DECLARE_INTERFACE" . gnome-c-snippet-insert-interface-declaration)
453 ("G_DECLARE_FINAL_TYPE" . gnome-c-snippet-insert-final-class-declaration)
454 ("G_DECLARE_DERIVABLE_TYPE" .
455 gnome-c-snippet-insert-derivable-class-declaration)
456 ("G_DEFINE_INTERFACE" . gnome-c-snippet-insert-interface-definition)
457 ("G_DEFINE_TYPE" . gnome-c-snippet-insert-class-definition)
458 ("G_DEFINE_ABSTRACT_TYPE" .
459 gnome-c-snippet-insert-abstract-class-definition)
460 ("GObjectClass.constructor" . gnome-c-snippet-insert-constructor)
461 ("GObjectClass.set_property" . gnome-c-snippet-insert-set_property)
462 ("GObjectClass.get_property" . gnome-c-snippet-insert-get_property)
463 ("GObjectClass.dispose" . gnome-c-snippet-insert-dispose)
464 ("GObjectClass.finalize" . gnome-c-snippet-insert-finalize)
465 ("GObjectClass.dispatch_properties_changed" .
466 gnome-c-snippet-insert-dispatch_properties_changed)
467 ("GObjectClass.notify" . gnome-c-snippet-insert-notify)
468 ("GObjectClass.constructed" . gnome-c-snippet-insert-constructed)))
471 (defun gnome-c-snippet-insert (snippet)
473 (list (completing-read "Snippet: " gnome-c-snippet-snippet-commands nil t)))
474 (let ((entry (assoc snippet gnome-c-snippet-snippet-commands)))
476 (error "Unknown snippet: %s" snippet))
477 (call-interactively (cdr entry))))
479 (provide 'gnome-c-snippet)
481 ;;; gnome-c-snippet.el ends here