X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/5cef93597739782b9be4b9ffdae686cffc0c7946..212c8fc3101781a2f1c55ca61772eb75a2046e87:/company-clang.el diff --git a/company-clang.el b/company-clang.el index 42a548784..54d4b9b9c 100644 --- a/company-clang.el +++ b/company-clang.el @@ -1,6 +1,6 @@ -;;; company-clang.el --- company-mode completion back-end for Clang -*- lexical-binding: t -*- +;;; company-clang.el --- company-mode completion backend for Clang -*- lexical-binding: t -*- -;; Copyright (C) 2009, 2011, 2013-2014 Free Software Foundation, Inc. +;; Copyright (C) 2009, 2011, 2013-2016 Free Software Foundation, Inc. ;; Author: Nikolaj Schumacher @@ -27,10 +27,10 @@ (require 'company) (require 'company-template) -(eval-when-compile (require 'cl)) +(require 'cl-lib) (defgroup company-clang nil - "Completion back-end for Clang." + "Completion backend for Clang." :group 'company) (defcustom company-clang-executable @@ -51,7 +51,7 @@ and `c-electric-colon', for automatic completion right after \">\" and "Additional arguments to pass to clang when completing. Prefix files (-include ...) can be selected with `company-clang-set-prefix' or automatically through a custom `company-clang-prefix-guesser'." - :type '(repeat (string :tag "Argument" nil))) + :type '(repeat (string :tag "Argument"))) (defcustom company-clang-prefix-guesser 'company-clang-guess-prefix "A function to determine the prefix file for the current buffer." @@ -60,6 +60,11 @@ or automatically through a custom `company-clang-prefix-guesser'." (defvar company-clang-modes '(c-mode c++-mode objc-mode) "Major modes which clang may complete.") +(defcustom company-clang-insert-arguments t + "When non-nil, insert function arguments as a template after completion." + :type 'boolean + :package-version '(company . "0.8.0")) + ;; prefix ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar company-clang--prefix nil) @@ -115,7 +120,7 @@ or automatically through a custom `company-clang-prefix-guesser'." "objective-c" "objective-c++") (substring (symbol-name major-mode) 0 -5))) -(defun company-clang--parse-output (prefix objc) +(defun company-clang--parse-output (prefix _objc) (goto-char (point-min)) (let ((pattern (format company-clang--completion-pattern (regexp-quote prefix))) @@ -139,13 +144,31 @@ or automatically through a custom `company-clang-prefix-guesser'." (get-text-property 0 'meta candidate)) (defun company-clang--annotation (candidate) + (let ((ann (company-clang--annotation-1 candidate))) + (if (not (and ann (string-prefix-p "(*)" ann))) + ann + (with-temp-buffer + (insert ann) + (search-backward ")") + (let ((pt (1+ (point)))) + (re-search-forward ".\\_>" nil t) + (delete-region pt (point))) + (buffer-string))))) + +(defun company-clang--annotation-1 (candidate) (let ((meta (company-clang--meta candidate))) (cond ((null meta) nil) - ((string-match ":" meta) - (substring meta (match-beginning 0))) - ((string-match "\\((.*)\\'\\)" meta) - (match-string 1 meta))))) + ((string-match "[^:]:[^:]" meta) + (substring meta (1+ (match-beginning 0)))) + ((string-match "\\((.*)[ a-z]*\\'\\)" meta) + (let ((paren (match-beginning 1))) + (if (not (eq (aref meta (1- paren)) ?>)) + (match-string 1 meta) + (with-temp-buffer + (insert meta) + (goto-char paren) + (substring meta (1- (search-backward "<")))))))))) (defun company-clang--strip-formatting (text) (replace-regexp-in-string @@ -177,10 +200,14 @@ or automatically through a custom `company-clang-prefix-guesser'." (defun company-clang--start-process (prefix callback &rest args) (let ((objc (derived-mode-p 'objc-mode)) - (buf (get-buffer-create "*clang-output*"))) - (with-current-buffer buf (erase-buffer)) + (buf (get-buffer-create "*clang-output*")) + ;; Looks unnecessary in Emacs 25.1 and later. + (process-adaptive-read-buffering nil)) (if (get-buffer-process buf) (funcall callback nil) + (with-current-buffer buf + (erase-buffer) + (setq buffer-undo-list t)) (let ((process (apply #'start-process "company-clang" buf company-clang-executable args))) (set-process-sentinel @@ -214,14 +241,14 @@ or automatically through a custom `company-clang-prefix-guesser'." t)))))) (defsubst company-clang--build-complete-args (pos) - (append '("-cc1" "-fsyntax-only" "-code-completion-macros") + (append '("-fsyntax-only" "-Xclang" "-code-completion-macros") (unless (company-clang--auto-save-p) (list "-x" (company-clang--lang-option))) company-clang-arguments (when (stringp company-clang--prefix) (list "-include" (expand-file-name company-clang--prefix))) - '("-code-completion-at") - (list (company-clang--build-location pos)) + (list "-Xclang" (format "-code-completion-at=%s" + (company-clang--build-location pos))) (list (if (company-clang--auto-save-p) buffer-file-name "-")))) (defun company-clang--candidates (prefix callback) @@ -237,15 +264,9 @@ or automatically through a custom `company-clang-prefix-guesser'." (company-clang--build-complete-args (- (point) (length prefix))))) (defun company-clang--prefix () - (let ((symbol (company-grab-symbol))) - (if symbol - (if (and company-clang-begin-after-member-access - (save-excursion - (forward-char (- (length symbol))) - (looking-back "\\.\\|->\\|::" (- (point) 2)))) - (cons symbol t) - symbol) - 'stop))) + (if company-clang-begin-after-member-access + (company-grab-symbol-cons "\\.\\|->\\|::" 2) + (company-grab-symbol))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -268,26 +289,8 @@ or automatically through a custom `company-clang-prefix-guesser'." ver)) 0))) -(defun company-clang-objc-templatify (selector) - (let* ((end (point-marker)) - (beg (- (point) (length selector) 1)) - (templ (company-template-declare-template beg end)) - (cnt 0)) - (save-excursion - (goto-char beg) - (catch 'stop - (while (search-forward ":" end t) - (when (looking-at "([^)]*) ?") - (delete-region (match-beginning 0) (match-end 0))) - (company-template-add-field templ (point) (format "arg%d" cnt)) - (if (< (point) end) - (insert " ") - (throw 'stop t)) - (incf cnt)))) - (company-template-move-to-first templ))) - (defun company-clang (command &optional arg &rest ignored) - "`company-mode' completion back-end for Clang. + "`company-mode' completion backend for Clang. Clang is a parser for C and ObjC. Clang version 1.1 or newer is required. Additional command line arguments can be specified in @@ -299,7 +302,7 @@ With Clang versions before 2.9, we have to save the buffer before performing completion. With Clang 2.9 and later, buffer contents are passed via standard input." (interactive (list 'interactive)) - (case command + (cl-case command (interactive (company-begin-backend 'company-clang)) (init (when (memq major-mode company-clang-modes) (unless company-clang-executable @@ -311,17 +314,18 @@ passed via standard input." buffer-file-name company-clang-executable (not (company-in-string-or-comment)) - (company-clang--prefix))) + (or (company-clang--prefix) 'stop))) (candidates (cons :async (lambda (cb) (company-clang--candidates arg cb)))) (meta (company-clang--meta arg)) (annotation (company-clang--annotation arg)) (post-completion (let ((anno (company-clang--annotation arg))) - (when anno + (when (and company-clang-insert-arguments anno) (insert anno) - (if (string-match ":" anno) - (company-clang-objc-templatify anno) - (company-template-c-like-templatify anno))))))) + (if (string-match "\\`:[^:]" anno) + (company-template-objc-templatify anno) + (company-template-c-like-templatify + (concat arg anno)))))))) (provide 'company-clang) ;;; company-clang.el ends here