gnu-emacs-sources
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: EmacsAssist


From: Klaus Berndl
Subject: Re: EmacsAssist
Date: 28 Mar 2006 10:51:42 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

What are the advantages of your Emacs-assist compared to speedbar or ECB -
both of them allow already the same functionality, maybe besides the
header-body switch. But concerning this IMHO this functionality should be
integrated into semantic/senator and must be much more customizable because
often header and body do not reside in the same directory....

In general the ideas are good but should be integrated either in semantic or
maybe in ECB.....

Ciao,
Klaus

On 27 Mar 2006, Anton V. Belyaev wrote:



>  Remember VisualAssist for VisualStudio? If you lack its convinient M-o,
>  M-m features in Emacs, EmacsAssist is for you. EmacsAssist is a C/C++
>  code navigator, allowing rapid navigation between class methods and
>  switch between header and body files (.h and .cpp).
>  
>  Comments, critics, feature requests are welcome.
>  I am beginner in eLisp, so I would highly appreciate comments related
>  to Elisp usage and Emacs API usage (for example if something is written
>  ugly from point of view of experienced Elisp programmer).
>  
> ;;; eassist.el --- EmacsAssist, C/C++ code navigator.
>  
> ;; Copyright (C) 2006 Anton V. Belyaev
> ;; Author: Anton V. Belyaev <anton.belyaev at the gmail.com>
>  
> ;; This file is *NOT* part of GNU Emacs.
>  
> ;; 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, write to the Free
> ;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> ;; MA 02111-1307 USA
>  
> ;; Version: 0.1
>  
> ;; Compatibility: Emacs 22, CEDET 1.0pre3.
>  
> ;;; Commentary:
>  
> ;; Contains some useful functions features for C/C++ developers similar
>  to
> ;; those from VisualAssist. Remember that convinient M-o, M-g and M-m?
>  
> ;; 1) Method navigaton.
> ;;    When eassist-list-methods called when c/c++ body file buffer is
>  active
> ;;    a new buffer is shown, containing list of methods and functions
>  in the
> ;;    format: return type, class, method name. You can select the
>  method
> ;;    moving to its line and press ENTER to jump to the method. You
>  also can
> ;;    type a string in the buffer and method list will be reduced to
>  those
> ;;    which contain the string as a substring. Nice highlight is
>  implemented.
> ;;    This function is recommended to be bound to M-m in c-mode.
>  
> ;; 2) Header <-> Body file switch.
> ;;    You can easily switch between body (c, cpp, cc...) and its
>  corresponding
> ;;    header file (h, hpp...) using eassist-switch-h-cpp. The file is
>  searched
> ;;    in the same directory. You can adjust body to header
>  correspondance
> ;;    customizing eassist-header-switches variable.
> ;;    This function is recommended to be bound to M-o in c-mode.
>  
> ;; EmacsAssist uses Semantic
>  (http://cedet.sourceforge.net/semantic.shtml)
> ;; EmacsAssist is defeloped for Semantics from CEDET 1.0pre3 package.
> ;; EmacsAssist works with current development (22) version of Emacs and
> ;; does not work with version 21.
>  
> ;; Usage:
>  
> ;; 1) Install CEDET 1.0pre3 package for Emacs (if you dont have CEDET
>  already).
> ;; 2) Copy eassist.el to your emacs/lisp folder.
> ;; 3) Add to your .emacs following line to load EmacsAssist:
> ;;    (require 'eassist)
> ;; 4) Add convinient keymaps for fast EmacsAssist calls in c-mode:
> ;;    (defun my-c-mode-common-hook ()
> ;;      (define-key c-mode-base-map (kbd "M-o") 'eassist-switch-h-cpp)
> ;;      (define-key c-mode-base-map (kbd "M-m") 'eassist-list-methods))
> ;;    (add-hook 'c-mode-common-hook 'my-c-mode-common-hook)
> ;; 5) Open any C++ file with class definithion, press M-m. Try to type
> ;;    any method name.
> ;; 6) Open any .cpp file. Press M-o. If there is .h or .hpp file in the
> ;;    same folder, it will be opened.
>  
> ;;; Changelog:
>  
> ;; 27 mar 2006 -- Initial version 0.1 created.
>  
> ;;; Code:
>  
> ;; ================================== My STRING utils
>  ========================
>  (defun eassist-string-last (string n)
>    (substring string (- (length string) n)))
>  
>  (defun eassist-string-without-last (string n)
>    (substring string 0 (max 0(- (length string) n))))
>  
>  (defun eassist-string-ends-with (string end)
>    (string= end (eassist-string-last string (length end))))
> ;; ================================== My STRING utils end
>  ====================
>  
> ;; ================================== CPP-H switch
>  ===========================
> ;; Funcalls action until it is not nil.
> ;; Returns result of the last action.
>  (defun eassist-do-for-first-suitable (lst action)
>    (if (null lst)
>        nil
>      (let ((res (funcall action (car lst))))
>        (if (null res)
>         (eassist-do-for-first-suitable (cdr lst) action)
>       res))))
>  
>  (setq eassist-header-switches '(
>                            ("h" . ("cpp" "cc" "c"))
>                            ("hpp" . ("cpp"))
>                            ("cpp" . ("h" "hpp"))
>                            ("c" . ("h"))
>                            ("cc" . ("h" "hpp"))
>                            ))
>  
>  (defun eassist-switch-h-cpp ()
>    (interactive)
>    (let ((ext (file-name-extension (buffer-file-name))))
>      (if (null (eassist-do-for-first-suitable eassist-header-switches
>                                            (lambda (i)
>                                              (if (string= (car i) ext)
>                                                  (progn
>                                                    (if (null
>                                                    
> (eassist-do-for-first-suitable
>                                                    (cdr i)
>  'eassist-try-h-cpp))
>                                                        (message "There is no 
> corresponding pair (header or body)
>  file."))
>                                                    ext)
>                                                nil))))
>       (message "It is not a header or body file! See eassist-header-switches
>  variable."))))
>  
>  (defun eassist-try-h-cpp (ext)
>    (eassist-find-if-exist
>     (concat (eassist-string-without-last (buffer-file-name) (length
>  (file-name-extension (buffer-file-name)))) ext)))
>  
>  (defun eassist-find-if-exist (file)
>    (if (file-exists-p file)
>        (progn (find-file file) file)
>      nil))
> ;; ================================== CPP-H switch end
>  =========================
>  
> ;; ================================== Method navigator
>  =========================
>  (defun eassist-functions ()
>    (semantic-find-tags-by-class 'function
>  (semantic-something-to-tag-table eassist-buffer)))
>  
>  (defun eassist-car-if-list (thing)
>    (cond ((listp thing) (car thing))
>       (t thing)))
>  
>  (defun eassist-function-string-triplet (f)
>    (list
>     (eassist-car-if-list (semantic-tag-type f))
>     (semantic-tag-function-parent f)
>     (semantic-tag-name f)))
>  
>  (defun eassist-format-triplets (f)
>    (let ((return-width (reduce 'max (mapcar 'length (mapcar 'car f))
>  :initial-value 0))
>       (class-width (reduce 'max (mapcar 'length (mapcar 'cadr f))
>  :initial-value 0))
>       (name-width (reduce 'max (mapcar 'length (mapcar 'caddr f))
>  :initial-value 0)))
>      (mapcar
>       (lambda (tri)
>         (cond
>       ((cadr tri) (format (format "%%%ds  %%%ds :: %%s\n" return-width
>  class-width) (car tri) (cadr tri) (caddr tri)))
>       (         t (format (format "%%%ds  %%%ds    %%s\n" return-width
>  class-width) (car tri) ""         (caddr tri)))))
>       f)))
>  
>  (defun eassist-list-methods ()
>    (interactive)
>    (setq eassist-buffer (current-buffer))
>    (switch-to-buffer (get-buffer-create (concat (buffer-name
>  (current-buffer)) " method list")) t)
>    (eassist-mode))
>  
>  (defun eassist-jump-to-method ()
>    (interactive)
>    (let ((tag (cdr (nth (1- (line-number-at-pos))
>  eassist-actual-methods))))
>      (cond
>       (tag
>        (kill-buffer (current-buffer))
>        (switch-to-buffer (semantic-tag-buffer tag) t)
>        (goto-char (semantic-tag-start tag))
>        (recenter))
>       (t (message "The line does not contain method description!")))))
>  
>  (defun eassist-case-insensitive-regexp (reg)
>    (apply 'string
>        (mapcan
>         (lambda (ch)
>           (let ((up (upcase ch)) (down (downcase ch)))
>             (cond
>              ((= up down) (list ch))
>              (t (list ?\[ up down ?\])))))
>         (string-to-list reg))))
>  
>  (defun eassist-search-string-updated ()
>    (message eassist-search-string)
>    (setq eassist-actual-methods
>       (remove-if-not
>        '(lambda (elt) (string-match eassist-search-string (car elt)))
>        eassist-methods))
>    (erase-buffer)
>    (mapcar '(lambda (elt) (insert (car elt))) eassist-actual-methods)
>    (goto-line (/ (count-lines (point-min) (point-max)) 2))
>    (cond
>     ((= 0 (length eassist-search-string)) nil)
>     (t (highlight-regexp (eassist-case-insensitive-regexp
>  eassist-search-string) 'hi-yellow)))
>    )
>  
>  (defun eassist-key-pressed (key)
>    (unhighlight-regexp (eassist-case-insensitive-regexp
>  eassist-search-string))
>    (setq eassist-search-string (concat eassist-search-string
>  (char-to-string key)))
>    (eassist-search-string-updated))
>  
>  (defun eassist-backspace-pressed ()
>    (interactive)
>    (unhighlight-regexp (eassist-case-insensitive-regexp
>  eassist-search-string))
>    (setq eassist-search-string (eassist-string-without-last
>  eassist-search-string 1))
>    (eassist-search-string-updated))
>  
>  (defun eassist-make-key-function (key)
>     `(lambda () (interactive) (eassist-key-pressed ,key)))
>  
>  (defun eassist-escape ()
>    (interactive)
>    (kill-buffer (current-buffer))
>    (switch-to-buffer eassist-buffer))
>  
>  (defvar eassist-mode-map
>    (let ((map (make-sparse-keymap)))
>      (suppress-keymap map)
>      (do ((k (string-to-char "a") (+ 1 k))) ((> k (string-to-char "z")))
>        (define-key
>       map
>       (read-kbd-macro (char-to-string k))
>       (eassist-make-key-function k)))
>      (do ((k (string-to-char "A") (+ 1 k))) ((> k (string-to-char "Z")))
>        (define-key
>       map
>       (read-kbd-macro (char-to-string k))
>       (eassist-make-key-function k)))
>      (do ((k (string-to-char "0") (+ 1 k))) ((> k (string-to-char "9")))
>        (define-key
>       map
>       (read-kbd-macro (char-to-string k))
>       (eassist-make-key-function k)))
>      (define-key map (kbd "<RET>") 'eassist-jump-to-method)
>      (define-key map (kbd "<backspace>") 'eassist-backspace-pressed)
>      (define-key map (kbd "<ESC>") 'eassist-escape)
>      map)
>    "Keymap for `eassist-mode'.")
>  
>  (defun eassist-mode-init ()
>    (make-local-variable 'eassist-search-string)   ;; current method
>  search string
>    (make-local-variable 'eassist-methods)         ;; (<formatted method
>  string> . <semantic method tag>)
>    (make-local-variable 'eassist-actual-methods)  ;; subset of
>  eassist-methods that contain eassist-search string in the method string
>    (setq eassist-search-string "")
>  
>    (let ((method-tags (eassist-functions)))
>      (let ((method-strings (eassist-format-triplets (mapcar
>  'eassist-function-string-triplet method-tags))))
>        (setq eassist-methods
>           (mapcar* 'cons
>                    method-strings
>                    method-tags))))
>    (eassist-search-string-updated)
>    (hl-line-mode)
>    )
>  
>  (define-derived-mode eassist-mode nil "Eassist methods"
>    "EmacsAssist method selection mode.
>     \\{eassist-mode-map}
>     Turning on Text mode runs the normal hook `eassist-mode-hook'."
>    (eassist-mode-init))
>  
> ;; ================================== Method navigator end
>  ======================
>  
>  (provide 'eassist)
>  
> ;;; eassist.el ends here

-- 
Klaus Berndl                    mailto: address@hidden
sd&m AG                         http://www.sdm.de
software design & management    
Carl-Wery-Str. 42, 81739 Muenchen, Germany
Tel +49 89 63812-392, Fax -220


reply via email to

[Prev in Thread] Current Thread [Next in Thread]