]> code.delx.au - gnu-emacs-elpa/blob - packages/gnome-c-style/gnome-c-snippet.el
Merge commit '9e55c293a80c6173db756200742e74cb06468ab0'
[gnu-emacs-elpa] / packages / gnome-c-style / gnome-c-snippet.el
1 ;;; gnome-c-snippet.el --- GNOME-style code generation -*- lexical-binding: t; -*-
2 ;; Copyright (C) 2016 Free Software Foundation, Inc.
3
4 ;; Author: Daiki Ueno <ueno@gnu.org>
5 ;; Keywords: GNOME, C, coding style
6
7 ;; This file is part of GNU Emacs.
8
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.
13
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.
18
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/>.
21
22 ;;; Commentary:
23
24 ;; FIXME: The snippets defined here could be rewritten in yasnippet
25
26 ;;; Code:
27
28 (require 'gnome-c-align)
29
30 (eval-when-compile
31 (require 'subword))
32
33 (declare-function subword-forward "subword.el" (&optional arg))
34
35 (defvar gnome-c-snippet-package nil)
36 (make-variable-buffer-local 'gnome-c-snippet-package)
37
38 (defvar gnome-c-snippet-class nil)
39 (make-variable-buffer-local 'gnome-c-snippet-class)
40
41 (defvar gnome-c-snippet-parent-package nil)
42 (make-variable-buffer-local 'gnome-c-snippet-parent-package)
43
44 (defvar gnome-c-snippet-parent-class nil)
45 (make-variable-buffer-local 'gnome-c-snippet-parent-class)
46
47 (defcustom gnome-c-snippet-align-arglist t
48 "Whether to align argument list of the inserted snippet"
49 :type 'boolean
50 :group 'gnome-c-style)
51
52 (make-variable-buffer-local 'gnome-c-snippet-align-arglist)
53
54 (defun gnome-c-snippet--parse-name (name)
55 (require 'subword)
56 (with-temp-buffer
57 (let (words)
58 (insert name)
59 (goto-char (point-min))
60 (while (not (eobp))
61 ;; Skip characters not recognized by subword-mode.
62 (if (looking-at "[^[:lower:][:upper:][:digit:]]+")
63 (goto-char (match-end 0)))
64 (push (buffer-substring (point) (progn (subword-forward 1)
65 (point)))
66 words))
67 (nreverse words))))
68
69 (defun gnome-c-snippet--read-package-and-class (package-prompt
70 class-prompt
71 package-symbol
72 class-symbol)
73 (when (or current-prefix-arg
74 (not (and (symbol-value package-symbol)
75 (symbol-value class-symbol))))
76 (set package-symbol
77 (gnome-c-snippet--parse-name
78 (read-string (or package-prompt
79 "Package (CamelCase): ")
80 (if (symbol-value package-symbol)
81 (gnome-c-snippet--format-Package
82 (symbol-value package-symbol))))))
83 (set class-symbol
84 (gnome-c-snippet--parse-name
85 (read-string (or class-prompt
86 "Class (CamelCase): ")
87 (if (symbol-value class-symbol)
88 (gnome-c-snippet--format-Class
89 (symbol-value class-symbol)))))))
90 (list (symbol-value package-symbol) (symbol-value class-symbol)))
91
92 (defun gnome-c-snippet--format-PACKAGE (package)
93 (mapconcat #'upcase package "_"))
94 (defalias 'gnome-c-snippet--format-CLASS 'gnome-c-snippet--format-PACKAGE)
95
96 (defun gnome-c-snippet--format-PACKAGE_CLASS (package class)
97 (concat (gnome-c-snippet--format-PACKAGE package)
98 "_"
99 (gnome-c-snippet--format-CLASS class)))
100
101 (defun gnome-c-snippet--format-package (package)
102 (mapconcat #'downcase package "_"))
103 (defalias 'gnome-c-snippet--format-class 'gnome-c-snippet--format-package)
104
105 (defun gnome-c-snippet--format-package_class (package class)
106 (concat (gnome-c-snippet--format-package package)
107 "_"
108 (gnome-c-snippet--format-class class)))
109
110 (defun gnome-c-snippet--format-Package (package)
111 (mapconcat #'identity package ""))
112 (defalias 'gnome-c-snippet--format-Class 'gnome-c-snippet--format-Package)
113
114 (defun gnome-c-snippet--format-PackageClass (package class)
115 (concat (gnome-c-snippet--format-Package package)
116 (gnome-c-snippet--format-Class class)))
117
118 ;;;###autoload
119 (defun gnome-c-snippet-insert-package_class (package class)
120 "Insert the class name before the current point."
121 (interactive (gnome-c-snippet--read-package-and-class
122 nil nil
123 'gnome-c-snippet-package
124 'gnome-c-snippet-class))
125 (insert (gnome-c-snippet--format-package_class package class)))
126
127 ;;;###autoload
128 (defun gnome-c-snippet-insert-PACKAGE_CLASS (package class)
129 "Insert the class name before the current point."
130 (interactive (gnome-c-snippet--read-package-and-class
131 nil nil
132 'gnome-c-snippet-package
133 'gnome-c-snippet-class))
134 (insert (gnome-c-snippet--format-PACKAGE_CLASS package class)))
135
136 ;;;###autoload
137 (defun gnome-c-snippet-insert-PackageClass (package class)
138 "Insert the class name (in CamelCase) before the current point."
139 (interactive (gnome-c-snippet--read-package-and-class
140 nil nil
141 'gnome-c-snippet-package
142 'gnome-c-snippet-class))
143 (insert (gnome-c-snippet--format-PackageClass package class)))
144
145 (defun gnome-c-snippet-insert-interface-declaration (package iface
146 parent-package parent-class)
147 "Insert interface declaration for PACKAGE and IFACE"
148 (interactive
149 (append (gnome-c-snippet--read-package-and-class
150 nil
151 "Interface (CamelCase): "
152 'gnome-c-snippet-package
153 'gnome-c-snippet-class)
154 (gnome-c-snippet--read-package-and-class
155 "Parent package (CamelCase): "
156 "Parent class (CamelCase): "
157 'gnome-c-snippet-parent-package
158 'gnome-c-snippet-parent-class)))
159 (insert "\
160 #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 ())
161 G_DECLARE_INTERFACE (" (gnome-c-snippet--format-PackageClass package iface) ", "
162 (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) ")
163 "))
164
165 (defun gnome-c-snippet--insert-class-declaration (package
166 class
167 parent-package
168 parent-class
169 derivable)
170 (insert "\
171 #define " (gnome-c-snippet--format-PACKAGE package) "_TYPE_" (gnome-c-snippet--format-CLASS class) " (" (gnome-c-snippet--format-package_class package class) "_get_type ())
172 G_DECLARE_" (if derivable "DERIVABLE" "FINAL") "_TYPE (" (gnome-c-snippet--format-PackageClass package class) ", "
173 (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) ")
174 "))
175
176 (defun gnome-c-snippet-insert-final-class-declaration (package
177 class
178 parent-package
179 parent-class)
180 "Insert final class declaration for PACKAGE and CLASS."
181 (interactive
182 (append (gnome-c-snippet--read-package-and-class
183 nil nil
184 'gnome-c-snippet-package
185 'gnome-c-snippet-class)
186 (gnome-c-snippet--read-package-and-class
187 "Parent package (CamelCase): "
188 "Parent class (CamelCase): "
189 'gnome-c-snippet-parent-package
190 'gnome-c-snippet-parent-class)))
191 (gnome-c-snippet--insert-class-declaration package
192 class
193 parent-package
194 parent-class
195 nil))
196
197 (defun gnome-c-snippet-insert-derivable-class-declaration (package
198 class
199 parent-package
200 parent-class)
201 "Insert derivable class declaration for PACKAGE and CLASS."
202 (interactive
203 (append (gnome-c-snippet--read-package-and-class
204 nil nil
205 'gnome-c-snippet-package
206 'gnome-c-snippet-class)
207 (gnome-c-snippet--read-package-and-class
208 "Parent package (CamelCase): "
209 "Parent class (CamelCase): "
210 'gnome-c-snippet-parent-package
211 'gnome-c-snippet-parent-class)))
212 (gnome-c-snippet--insert-class-declaration package
213 class
214 parent-package
215 parent-class
216 t))
217
218 (defun gnome-c-snippet-insert-interface-definition (package
219 iface
220 parent-package
221 parent-class)
222 "Insert class definition for PACKAGE and CLASS."
223 (interactive
224 (append (gnome-c-snippet--read-package-and-class
225 nil
226 "Interface (CamelCase): "
227 'gnome-c-snippet-package
228 'gnome-c-snippet-class)
229 (gnome-c-snippet--read-package-and-class
230 "Parent package (CamelCase): "
231 "Parent class (CamelCase): "
232 'gnome-c-snippet-parent-package
233 'gnome-c-snippet-parent-class)))
234 (insert "\
235 static void
236 " (gnome-c-snippet--format-package_class package iface) "_default_init (" (gnome-c-snippet--format-PackageClass package iface) "Interface *iface) {
237 }
238
239 G_DEFINE_INTERFACE (" (gnome-c-snippet--format-PackageClass package iface) ", "
240 (gnome-c-snippet--format-package_class package iface) ", " (gnome-c-snippet--format-PACKAGE parent-package) "_TYPE_" (gnome-c-snippet--format-CLASS parent-class) ")
241 "))
242
243 (defun gnome-c-snippet--insert-class-definition (package
244 class
245 parent-package
246 parent-class
247 abstract)
248 (insert "\
249 G_DEFINE_" (if abstract "ABSTRACT_" "") "TYPE (" (gnome-c-snippet--format-PackageClass package class) ", "
250 (gnome-c-snippet--format-package_class package class) ", " (gnome-c-snippet--format-PACKAGE parent-package) "_TYPE_" (gnome-c-snippet--format-CLASS parent-class) ")
251
252 static void
253 " (gnome-c-snippet--format-package_class package class) "_class_init (" (gnome-c-snippet--format-PackageClass package class) "Class *klass)
254 {
255 }
256
257 static void
258 " (gnome-c-snippet--format-package_class package class) "_init (" (gnome-c-snippet--format-PackageClass package class) " *self)
259 {
260 }
261 "))
262
263 (defun gnome-c-snippet-insert-class-definition (package
264 class
265 parent-package
266 parent-class)
267 "Insert class definition for PACKAGE and CLASS."
268 (interactive
269 (append (gnome-c-snippet--read-package-and-class
270 nil nil
271 'gnome-c-snippet-package
272 'gnome-c-snippet-class)
273 (gnome-c-snippet--read-package-and-class
274 "Parent package (CamelCase): "
275 "Parent class (CamelCase): "
276 'gnome-c-snippet-parent-package
277 'gnome-c-snippet-parent-class)))
278 (gnome-c-snippet--insert-class-definition package
279 class
280 parent-package
281 parent-class
282 nil))
283
284 (defun gnome-c-snippet-insert-abstract-class-definition (package
285 class
286 parent-package
287 parent-class)
288 "Insert abstract class definition for PACKAGE and CLASS."
289 (interactive
290 (append (gnome-c-snippet--read-package-and-class
291 nil nil
292 'gnome-c-snippet-package
293 'gnome-c-snippet-class)
294 (gnome-c-snippet--read-package-and-class
295 "Parent package (CamelCase): "
296 "Parent class (CamelCase): "
297 'gnome-c-snippet-parent-package
298 'gnome-c-snippet-parent-class)))
299 (gnome-c-snippet--insert-class-definition package
300 class
301 parent-package
302 parent-class
303 t))
304
305 (defun gnome-c-snippet-insert-constructor (package class)
306 "Insert 'constructor' vfunc of GObjectClass for PACKAGE and CLASS."
307 (interactive
308 (gnome-c-snippet--read-package-and-class
309 nil nil
310 'gnome-c-snippet-package
311 'gnome-c-snippet-class))
312 (let (arglist-start body-start)
313 (insert "\
314 static GObject *
315 " (gnome-c-snippet--format-package_class package class) "_constructor (")
316 (setq arglist-start (point-marker))
317 (insert "GType *object,
318 guint n_construct_properties,
319 GObjectConstructParam *construct_properties)\n")
320 (setq body-start (point-marker))
321 (if gnome-c-snippet-align-arglist
322 (progn
323 (goto-char arglist-start)
324 (gnome-c-align-arglist-at-point))
325 (indent-region arglist-start (point)))
326 (goto-char body-start)
327 (insert "{
328 " (gnome-c-snippet--format-PackageClass package class) " *self = "
329 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
330
331 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->constructed (type, n_construct_properties, construct_properties);
332 }
333 ")
334 (indent-region body-start (point))))
335
336 (defun gnome-c-snippet-insert-set_property (package class)
337 "Insert 'set_property' vfunc of GObjectClass for PACKAGE and CLASS."
338 (interactive
339 (gnome-c-snippet--read-package-and-class
340 nil nil
341 'gnome-c-snippet-package
342 'gnome-c-snippet-class))
343 (let (arglist-start body-start)
344 (insert "\
345 static void
346 " (gnome-c-snippet--format-package_class package class) "_set_property (")
347 (setq arglist-start (point-marker))
348 (insert "GObject *object,
349 guint prop_id,
350 const GValue *value,
351 GParamSpec *pspec)\n")
352 (setq body-start (point-marker))
353 (if gnome-c-snippet-align-arglist
354 (progn
355 (goto-char arglist-start)
356 (gnome-c-align-arglist-at-point))
357 (indent-region arglist-start (point)))
358 (goto-char body-start)
359 (insert "{
360 " (gnome-c-snippet--format-PackageClass package class) " *self = "
361 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
362
363 switch (prop_id)
364 {
365 default:
366 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
367 break;
368 }
369 }
370 ")
371 (indent-region body-start (point))))
372
373 (defun gnome-c-snippet-insert-get_property (package class)
374 "Insert 'get_property' vfunc of GObjectClass for PACKAGE and CLASS."
375 (interactive
376 (gnome-c-snippet--read-package-and-class
377 nil nil
378 'gnome-c-snippet-package
379 'gnome-c-snippet-class))
380 (let (arglist-start body-start)
381 (insert "\
382 static void
383 " (gnome-c-snippet--format-package_class package class) "_get_property (")
384 (setq arglist-start (point-marker))
385 (insert "GObject *object,
386 guint prop_id,
387 GValue *value,
388 GParamSpec *pspec)\n")
389 (setq body-start (point-marker))
390 (if gnome-c-snippet-align-arglist
391 (progn
392 (goto-char arglist-start)
393 (gnome-c-align-arglist-at-point))
394 (indent-region arglist-start (point)))
395 (goto-char body-start)
396 (insert "{
397 " (gnome-c-snippet--format-PackageClass package class) " *self = "
398 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
399
400 switch (prop_id)
401 {
402 default:
403 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
404 break;
405 }
406 }
407 ")
408 (indent-region body-start (point))))
409
410 (defun gnome-c-snippet-insert-dispose (package class)
411 "Insert 'dispose' vfunc of GObjectClass for PACKAGE and CLASS."
412 (interactive
413 (gnome-c-snippet--read-package-and-class
414 nil nil
415 'gnome-c-snippet-package
416 'gnome-c-snippet-class))
417 (let (body-start)
418 (insert "\
419 static void
420 " (gnome-c-snippet--format-package_class package class) "_dispose (GObject *object)\n")
421 (setq body-start (point-marker))
422 (insert "{
423 " (gnome-c-snippet--format-PackageClass package class) " *self = "
424 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
425
426 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->dispose (object);
427 }
428 ")
429 (indent-region body-start (point))))
430
431 (defun gnome-c-snippet-insert-finalize (package class)
432 "Insert 'finalize' vfunc of GObjectClass for PACKAGE and CLASS."
433 (interactive
434 (gnome-c-snippet--read-package-and-class
435 nil nil
436 'gnome-c-snippet-package
437 'gnome-c-snippet-class))
438 (let (body-start)
439 (insert "\
440 static void
441 " (gnome-c-snippet--format-package_class package class) "_finalize (GObject *object)\n")
442 (setq body-start (point-marker))
443 (insert "{
444 " (gnome-c-snippet--format-PackageClass package class) " *self = "
445 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
446
447 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->finalize (object);
448 }
449 ")
450 (indent-region body-start (point))))
451
452 (defun gnome-c-snippet-insert-dispatch_properties_changed (package class)
453 "Insert 'dispatch_properties_changed vfunc of GObjectClass for
454 PACKAGE and CLASS."
455 (interactive
456 (gnome-c-snippet--read-package-and-class
457 nil nil
458 'gnome-c-snippet-package
459 'gnome-c-snippet-class))
460 (let (arglist-start body-start)
461 (insert "\
462 static void
463 " (gnome-c-snippet--format-package_class package class) "_dispatch_properties_changed (")
464 (setq arglist-start (point-marker))
465 (insert "GObject *object,
466 guint n_pspecs,
467 GParamSpec **pspecs)\n")
468 (setq body-start (point-marker))
469 (if gnome-c-snippet-align-arglist
470 (progn
471 (goto-char arglist-start)
472 (gnome-c-align-arglist-at-point))
473 (indent-region arglist-start (point)))
474 (goto-char body-start)
475 (insert "{
476 " (gnome-c-snippet--format-PackageClass package class) " *self = "
477 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
478
479 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
480 }
481 ")
482 (indent-region body-start (point))))
483
484 (defun gnome-c-snippet-insert-notify (package class)
485 "Insert 'notify' vfunc of GObjectClass for PACKAGE and CLASS."
486 (interactive
487 (gnome-c-snippet--read-package-and-class
488 nil nil
489 'gnome-c-snippet-package
490 'gnome-c-snippet-class))
491 (let (arglist-start body-start)
492 (insert "\
493 static void
494 " (gnome-c-snippet--format-package_class package class) "_notify (")
495 (setq arglist-start (point-marker))
496 (insert "GObject *object,
497 GParamSpec *pspec)\n")
498 (setq body-start (point-marker))
499 (if gnome-c-snippet-align-arglist
500 (progn
501 (goto-char arglist-start)
502 (gnome-c-align-arglist-at-point))
503 (indent-region arglist-start (point)))
504 (insert "{
505 " (gnome-c-snippet--format-PackageClass package class) " *self = "
506 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
507
508 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->notify (object, pspec);
509 }
510 ")
511 (indent-region body-start (point))))
512
513 (defun gnome-c-snippet-insert-constructed (package class)
514 "Insert 'constructed' vfunc of GObjectClass for PACKAGE and CLASS."
515 (interactive
516 (gnome-c-snippet--read-package-and-class
517 nil nil
518 'gnome-c-snippet-package
519 'gnome-c-snippet-class))
520 (let (body-start)
521 (insert "\
522 static void
523 " (gnome-c-snippet--format-package_class package class) "_constructed (GObject *object)\n")
524 (setq body-start (point-marker))
525 (insert "{
526 " (gnome-c-snippet--format-PackageClass package class) " *self = "
527 (gnome-c-snippet--format-PACKAGE_CLASS package class) " (object);
528
529 G_OBJECT_CLASS (" (gnome-c-snippet--format-package_class package class) "_parent_class)->constructed (object);
530 }
531 ")
532 (indent-region body-start (point))))
533
534 (defvar gnome-c-snippet-snippet-commands
535 '(("G_DECLARE_INTERFACE" . gnome-c-snippet-insert-interface-declaration)
536 ("G_DECLARE_FINAL_TYPE" . gnome-c-snippet-insert-final-class-declaration)
537 ("G_DECLARE_DERIVABLE_TYPE" .
538 gnome-c-snippet-insert-derivable-class-declaration)
539 ("G_DEFINE_INTERFACE" . gnome-c-snippet-insert-interface-definition)
540 ("G_DEFINE_TYPE" . gnome-c-snippet-insert-class-definition)
541 ("G_DEFINE_ABSTRACT_TYPE" .
542 gnome-c-snippet-insert-abstract-class-definition)
543 ("GObjectClass.constructor" . gnome-c-snippet-insert-constructor)
544 ("GObjectClass.set_property" . gnome-c-snippet-insert-set_property)
545 ("GObjectClass.get_property" . gnome-c-snippet-insert-get_property)
546 ("GObjectClass.dispose" . gnome-c-snippet-insert-dispose)
547 ("GObjectClass.finalize" . gnome-c-snippet-insert-finalize)
548 ("GObjectClass.dispatch_properties_changed" .
549 gnome-c-snippet-insert-dispatch_properties_changed)
550 ("GObjectClass.notify" . gnome-c-snippet-insert-notify)
551 ("GObjectClass.contructed" . gnome-c-snippet-insert-constructed)))
552
553 ;;;###autoload
554 (defun gnome-c-snippet-insert (snippet)
555 (interactive
556 (list (completing-read "Snippet: " gnome-c-snippet-snippet-commands nil t)))
557 (let ((entry (assoc snippet gnome-c-snippet-snippet-commands)))
558 (unless entry
559 (error "Unknown snippet: %s" snippet))
560 (call-interactively (cdr entry))))
561
562 (provide 'gnome-c-snippet)
563
564 ;;; gnome-c-snippet.el ends here