]> code.delx.au - gnu-emacs-elpa/commitdiff
Added template insertion for ObjC selectors.
authorNikolaj Schumacher <git@nschum.de>
Fri, 19 Feb 2010 23:20:55 +0000 (00:20 +0100)
committerNikolaj Schumacher <git@nschum.de>
Tue, 23 Feb 2010 14:17:09 +0000 (15:17 +0100)
company-clang.el
company-template.el [new file with mode: 0644]
company.el

index 2cb2ce853733ce7feb6f83fceaec0e344de45aa4..c38a04377bba85161c96ea1afad90496115b9d71 100644 (file)
@@ -176,6 +176,19 @@ Prefix files (-include ...) can be selected with
     (when (re-search-forward "\\`clang version \\([0-9.]+\\)" nil t)
       (match-string-no-properties 1))))
 
+(defun company-clang-objc-templatify (selector)
+  (let* ((end (point))
+         (beg (- (point) (length selector)))
+         (templ (company-template-declare-template beg end)))
+    (save-excursion
+      (goto-char beg)
+      (while (search-forward ":" end t)
+        (replace-match ":  ")
+        (incf end 2)
+        (company-template-add-field templ (1- (match-end 0)) "<arg>"))
+      (delete-char -1))
+    (company-template-move-to-first templ)))
+
 (defun company-clang (command &optional arg &rest ignored)
   "A `company-mode' completion back-end for clang.
 Clang is a parser for C and ObjC.  The unreleased development version of
@@ -201,7 +214,10 @@ Completions only work correctly when the buffer has been saved.
                       company-clang-executable
                       (not (company-in-string-or-comment))
                       (or (company-grab-symbol) 'stop)))
-        ('candidates (company-clang--candidates arg))))
+        ('candidates (company-clang--candidates arg))
+        ('post-completion (and (derived-mode-p 'objc-mode)
+                               (string-match ":" arg)
+                               (company-clang-objc-templatify arg)))))
 
 (provide 'company-clang)
 ;;; company-clang.el ends here
diff --git a/company-template.el b/company-template.el
new file mode 100644 (file)
index 0000000..f9b0fcd
--- /dev/null
@@ -0,0 +1,114 @@
+(eval-when-compile (require 'cl))
+
+(defface company-template-field
+  '((((background dark)) (:background "yellow" :foreground "black"))
+    (((background light)) (:background "orange" :foreground "black")))
+  "*Face used for editable text in template fields."
+  :group 'company)
+
+(defvar company-template-nav-map
+  (let ((keymap (make-sparse-keymap)))
+    (define-key keymap [remap forward-word] 'company-template-forward-field)
+    (define-key keymap [remap subword-forward] 'company-template-forward-field)
+    ;; M-n
+    keymap))
+
+;; interactive ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defsubst company-template-templates-at (pos)
+  (let (os)
+    (dolist (o (overlays-at pos))
+      (when (overlay-get o 'company-template-fields)
+        (push o os)))
+    os))
+
+(defun company-template-move-to-first (templ)
+  (interactive)
+  (let ((fields (overlay-get templ 'company-template-fields)))
+    (push-mark)
+    (goto-char (apply 'min (mapcar 'overlay-start fields)))))
+
+(defun company-template-forward-field ()
+  (interactive)
+  (let* ((templates (company-template-templates-at (point)))
+         (minimum (apply 'max (mapcar 'overlay-end templates)))
+         (fields (apply 'append
+                        (mapcar (lambda (templ)
+                                  (overlay-get templ 'company-template-fields))
+                                templates))))
+    (dolist (pos (mapcar 'overlay-start fields))
+      (and pos
+           (> pos (point))
+           (< pos minimum)
+           (setq minimum pos)))
+    (push-mark)
+    (goto-char minimum)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar company-template--buffer-templates nil)
+(make-variable-buffer-local 'company-template--buffer-templates)
+
+(defun company-template-declare-template (beg end)
+  (let ((ov (make-overlay beg end)))
+    ;; (overlay-put ov 'face 'highlight)
+    (overlay-put ov 'keymap company-template-nav-map)
+    (overlay-put ov 'evaporate t)
+    (push ov company-template--buffer-templates)
+    (add-hook 'post-command-hook 'company-template-post-command nil t)
+    ov))
+
+(defun company-template-remove-template (templ)
+  (mapc 'company-template-remove-field
+        (overlay-get templ 'company-template-fields))
+  (setq company-template--buffer-templates
+        (delq templ company-template--buffer-templates))
+  (delete-overlay templ))
+
+(defun company-template-add-field (templ pos text)
+  (assert templ)
+  (save-excursion
+    ;; (goto-char pos)
+    (let ((ov (make-overlay pos pos))
+          (siblings (overlay-get templ 'company-template-fields))
+          (label (propertize text 'face 'company-template-field
+                             'company-template-parent templ)))
+      (overlay-put ov 'face 'highlight)
+      (add-text-properties 0 1 '(cursor t) label)
+      (overlay-put ov 'after-string label)
+      ;; (overlay-put ov 'evaporate t)
+      (overlay-put ov 'intangible t)
+      (overlay-put ov 'company-template-parent templ)
+      (overlay-put ov 'insert-in-front-hooks '(company-template-remove))
+      (push ov siblings)
+      (overlay-put templ 'company-template-fields siblings))))
+
+(defun company-template-remove-field (field)
+  (when (overlayp field)
+    ;; (delete-region (overlay-start field) (overlay-end field))
+    (delete-overlay field))
+  ;; TODO: unlink
+  )
+
+(defun company-template-clean-up (&optional pos)
+  "Clean up all templates that don't contain POS."
+  (unless pos (setq pos (point)))
+  (let ((local-ovs (overlays-in (- pos 2) pos)))
+    (dolist (templ company-template--buffer-templates)
+      (unless (memq templ local-ovs)
+        (company-template-remove-template templ)))))
+
+;; hooks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun company-template-remove (overlay after-p beg end &optional r)
+  "Called when a snippet input prompt is modified."
+  (when after-p
+    (delete-overlay overlay)))
+
+(defun company-template-post-command ()
+  (company-template-clean-up)
+  (unless company-template--buffer-templates
+    (remove-hook 'post-command-hook 'company-template-post-command t)))
+
+(provide 'company-template)
+;;; company-template.el ends here
index eddd4cbf879940ffa8eaebe719b51797581b49fe..bc296be733cadd3cd4cb1f8ca3a522e738a3dda7 100644 (file)
@@ -68,6 +68,8 @@
 ;;    `company-ropemacs' now provides location and docs.  (Fernando H. Silva)
 ;;    Added `company-with-candidate-inserted' macro.
 ;;    Added `company-clang' back-end.
+;;    Added new mechanism for non-consecutive insertion.
+;;      (So far only used by clang for ObjC.)
 ;;    The semantic back-end now shows meta information for local symbols.
 ;;    Added compatibility for CEDET in Emacs 23.2.
 ;;
@@ -1978,5 +1980,9 @@ Returns a negative number if the tooltip should be displayed above point."
     ('post-command (company-echo-show-soon 'company-fetch-metadata))
     ('hide (company-echo-hide))))
 
+;; templates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(autoload 'company-template-declare-template "company-template")
+
 (provide 'company)
 ;;; company.el ends here