--- /dev/null
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(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