From 6a5188b46e51f9476cb8d700bf8143db2206a40e Mon Sep 17 00:00:00 2001 From: Nikolaj Schumacher Date: Sat, 11 Apr 2009 22:05:28 +0200 Subject: [PATCH] Added Xcode back-end. --- company-xcode.el | 113 +++++++++++++++++++++++++++++++++++++++++++++++ company.el | 7 +-- 2 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 company-xcode.el diff --git a/company-xcode.el b/company-xcode.el new file mode 100644 index 000000000..1280c10ea --- /dev/null +++ b/company-xcode.el @@ -0,0 +1,113 @@ +;;; company-xcode.el --- a company-mode completion back-end for Xcode projects +;; +;; Copyright (C) 2009 Nikolaj Schumacher +;; +;; This file is part of company 0.2.1. +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License +;; as published by the Free Software Foundation; either version 2 +;; of the License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +(require 'company) +(eval-when-compile (require 'cl)) + +(defcustom company-xcode-xcodeindex-executable (executable-find "xcodeindex") + "*Location of xcodeindex executable" + :group 'company-xcode + :type 'file) + +(defvar company-xcode-tags nil) + +(defun company-xcode-reset () + "Reset the cached tags." + (interactive) + (setq company-xcode-tags nil)) + +(defcustom company-xcode-types + '("Class" "Const" "Constant" "Enum" "Macro" "Modeled Class" "Structure" + "Type" "Union" "Function") + "*The types of symbols offered by `company-xcode' +No context-enabled completion is available. Types like methods will be +offered regardless of whether the class supports them. The defaults should be +valid in most contexts." + :set (lambda (variable value) + (set variable value) + (company-xcode-reset)) + :group 'company-xcode + :type '(set (const "Category") (const "Class") (const "Class Method") + (const "Const") (const "Constant") (const "Enum") (const "Field") + (const "Instance Method") (const "Instance Variables") + (const "Macro") (const "Modeled Class") (const "Modeled Method") + (const "Property") (const "Protocol") (const "Structure") + (const "Type") (const "Union") (const "Variable") + (const "Function"))) + +(defvar company-xcode-symbol-regexp + "\\_<[A-Za-z_][A-Za-z_0-9]*\\_>") + +(defvar company-xcode-project 'unknown) +(make-variable-buffer-local 'company-xcode-project) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun company-xcode-fetch (project-bundle) + (setq project-bundle (directory-file-name project-bundle)) + (message "Retrieving dump from %s..." project-bundle) + (with-temp-buffer + (let ((default-directory (file-name-directory project-bundle))) + (call-process company-xcode-xcodeindex-executable nil (current-buffer) + nil "dump" "-project" + (file-name-nondirectory project-bundle) "-quiet") + (goto-char (point-min)) + (let ((regexp (concat "^\\([^\t\n]*\\)\t[^\t\n]*\t" + (regexp-opt company-xcode-types) + "\t[^\t\n]*\t[^\t\n]*")) + candidates) + (while (re-search-forward regexp nil t) + (add-to-list 'candidates (match-string 1))) + (message "Retrieving dump from %s...done" project-bundle) + candidates)))) + +(defun company-xcode-find-project () + (let ((dir (if buffer-file-name + (file-name-directory buffer-file-name) + (expand-file-name default-directory))) + file) + (while (not (or file (equal dir "/"))) + (setq file (car (directory-files dir t ".xcodeproj\\'" t)) + dir (file-name-directory (directory-file-name dir)))) + file)) + +(defun company-xcode-tags () + (when (eq company-xcode-project 'unknown) + (setq company-xcode-project (company-xcode-find-project))) + (when company-xcode-project + (cdr (or (assoc company-xcode-project company-xcode-tags) + (car (push (cons company-xcode-project + (company-xcode-fetch company-xcode-project)) + company-xcode-tags)))))) +;;;###autoload +(defun company-xcode (command &optional arg &rest ignored) + "A `company-mode' completion back-end for Xcode projects." + (interactive (list 'interactive)) + (case command + ('interactive (company-begin-backend 'company-xcode)) + ('prefix (and company-xcode-xcodeindex-executable + (not (company-in-string-or-comment)) + (company-xcode-tags) + (or (company-grab company-xcode-symbol-regexp) ""))) + ('candidates (let ((completion-ignore-case nil)) + (all-completions arg (company-xcode-tags)))))) + + +(provide 'company-xcode) +;;; company-xcode.el ends here diff --git a/company.el b/company.el index c7a34d575..086c021c7 100644 --- a/company.el +++ b/company.el @@ -69,7 +69,7 @@ ;; ;;; Change Log: ;; -;; Added abbrev and tempo back-ends. +;; Added abbrev, tempo and Xcode back-ends. ;; Back-ends are now interactive. You can start them with M-x backend-name. ;; Added `company-begin-with' for starting company from elisp-code. ;; Added hooks. @@ -234,8 +234,9 @@ The visualized data is stored in `company-prefix', `company-candidates', (function :tag "custom function" nil)))) (defcustom company-backends '(company-elisp company-nxml company-css - company-semantic company-gtags company-etags - company-oddmuse company-files company-dabbrev) + company-semantic company-xcode company-gtags + company-etags company-oddmuse company-files + company-dabbrev) "*The list of active back-ends (completion engines). Each back-end is a function that takes a variable number of arguments. The first argument is the command requested from the back-end. It is one -- 2.39.2