Files
SWG_Client_Next_Main/tools/workspace.el
2016-06-01 15:00:39 -04:00

201 lines
7.0 KiB
EmacsLisp

;;
;; Copyright 2001, Sony Online Entertainment, Inc.
;; All rights reserved.
;;
;;; declare variables
(defvar workspace-directory nil "workspace base directory")
(defvar workspace-completion-obarray nil "workspace completion data")
(defvar workspace-completion-hashsize 2047 "workspace completion hash entry count")
(defvar workspace-headerflip-source-extension-alist '((".c") (".cpp") (".cxx") (".C") (".plsql")) "workspace headerflip source extension alist")
(defvar workspace-headerflip-header-extension-alist '((".h") (".hpp") (".hxx") (".plsqlh")) "workspace headerflip header extension alist")
;;; Read a file containing workspace entries. Each line contains
;;; the short filename followed by the path to the filename. The
;;; path listed is relative to the workspace file path.
(defun workspace-find-workspace (workspace-pathname)
"Open a workspace file. Replaces any existing workspace file."
(interactive "fWorkspace Filename: ")
;; pull directory out of the workspace pathname. we'll need it later.
(posix-string-match "\\(.*/\\).*$" workspace-pathname)
(setq workspace-directory (substring workspace-pathname (match-beginning 1) (match-end 1)))
;; create a temp buffer for workspace processing
(with-temp-buffer
;; insert-file-contents of the workspace file
(insert-file-contents workspace-pathname)
;; initialize completion hash
(setq workspace-completion-obarray (make-vector workspace-completion-hashsize 0))
;; build lookup table entry for each entry in workspace
(while (posix-search-forward "^\\(.*\\):\\(.*\\)$" nil t)
;; add entry to completion obarray
(let
(
(completion-entry (intern-soft (match-string 1) workspace-completion-obarray))
(completion-data (list (match-string 2)))
)
(if completion-entry
;; entry already in array, append completion data to entry's list value
(set completion-entry (append (symbol-value completion-entry) completion-data))
;; entry doesn't exist, create it and set value to completion-data list
(setq completion-entry (intern (match-string 1) workspace-completion-obarray))
(set completion-entry completion-data)
)
)
)
)
)
;;; workspace-find-file function. This works like find-file (C-x f),
;;; but allows the user to enter the short filename of a workspace
;;; file instead of the whole path. If there is only one file with
;;; the given short filename, that file will be opened. If multiple
;;; files exist in the workspace with the same short name, the user is
;;; prompted to differentiate which one is desired. Standard Emacs
;;; completion is available at all stages.
(defun workspace-find-file ()
"Find file within workspace using short filename (no path)."
(interactive)
(let (
(completion-entry-name (completing-read "Workspace Filename: " workspace-completion-obarray nil t))
)
(let (
(completion-entry (intern completion-entry-name workspace-completion-obarray))
)
(let (
(completion-list (symbol-value completion-entry))
(completion-list-copy ())
(directory nil)
(path-completion-list ())
; (full-pathname (concat workspace-directory (car (symbol-value completion-entry)) completion-entry-name))
)
;; if there's only one completion entry, open it. Otherwise, we need to
;; provide the user with a selection of files to open.
(if (null (cdr completion-list))
;; only one entry, no selection required
(find-file (concat workspace-directory (car completion-list) completion-entry-name))
;; multiple entries for the short filename. must provide a choice.
;; build short filename's path completion list.
(setq completion-list-copy (copy-sequence completion-list))
(while (setq directory (car completion-list-copy))
;; add directory + short filename to alist of choices.
;; note: the alist does not associate anything with the pathname in this case.
(setq path-completion-list (cons (list (concat directory completion-entry-name)) path-completion-list))
;; remove directory from copy list
(setq completion-list-copy (cdr completion-list-copy))
)
;; ask user to choose workspace pathname
(let (
(chosen-filename (completing-read "Choose path: " path-completion-list nil t))
)
(find-file (concat workspace-directory chosen-filename))
)
)
)
)
)
)
;;; Function used internally to find and open the first existing file
;;; that starts with a given base filename and an assoc-list of
;;; extensions.
(defun workspace-open-base-find-extension (pathname-base extension-alist)
"Workspace internal function used to try to open a given base filename trying to append each extension in the alist."
;; open the first pathname (base + ext) that exists
(let (
(alist-copy (copy-sequence extension-alist))
(alist-entry nil)
(extension nil)
(try-pathname nil)
)
(while (setq alist-entry (car alist-copy))
;; get extension
(setq extension (car alist-entry))
;; build try pathname
(setq try-pathname (concat pathname-base extension))
;; open file if filename is exists and is readable
(if (file-readable-p try-pathname)
(find-file try-pathname))
;; increment loop
(setq alist-copy (cdr alist-copy))
)
)
)
;;; This funciton provides header-flip functionality. If the user is
;;; in a source-code implementation file, execution of this function
;;; will open the corresponding header file (or vice versa).
;;; Implementation and header file extensions are defined in separate
;;; assoc-lists at the top of this file.
(defun workspace-header-flip ()
"Flip between header and implementation file."
(interactive)
;; get pathname of current buffer
(let (
(pathname (buffer-file-name))
(extension nil)
(pathname-no-extension nil)
(is-source nil)
(is-header nil)
)
;; find extension of pathname
(posix-string-match "\\(.*\\)\\(\\..*\\)$" pathname)
(if (match-beginning 2)
;; we have an extension
(progn
;; get the extension
(setq extension (substring pathname (match-beginning 2) (match-end 2)))
;; determine if we're considered a source or header
(if (assoc extension workspace-headerflip-source-extension-alist)
(setq is-source t))
(if (assoc extension workspace-headerflip-header-extension-alist)
(setq is-header t))
;; only do more work if we're a source or header
(if (or is-source is-header)
(progn
;; get pathname without extension
(setq pathname-no-extension (substring pathname (match-beginning 1) (match-end 1)))
(if is-source
;; if source, try to open base pathname with any header extension attached
(workspace-open-base-find-extension pathname-no-extension workspace-headerflip-header-extension-alist)
;; if source, try to open base pathname with any header extension attached
(workspace-open-base-find-extension pathname-no-extension workspace-headerflip-source-extension-alist)
)
)
)
)
;; no extension found
(prin1 (format "failed to find extension for [%s]" pathname))
)
)
)
(provide 'workspace)