coder . cl » emacs http://coder.cl web developer & system programmer Sat, 03 Nov 2012 12:37:47 +0000 en hourly 1 http://wordpress.org/?v=3.4.2 why I still use emacs? http://coder.cl/2012/07/why-i-still-use-emacs/ http://coder.cl/2012/07/why-i-still-use-emacs/#comments Tue, 10 Jul 2012 12:16:00 +0000 Daniel Molina Wegener http://coder.cl/?p=2576 There are many Integrated Development Environments to work with, but still I am using Emacs as my main editor, some times as IDE due to its wide variety on working modes, like Emacs Code Browser and CEDET, where both are making Emacs my main C and C++ editor due to its flexibility and extensibility. Also, I am a Lisp programmer, so I usually code some small extensions to make easier my work, like directory specific hooks to ensure that the indentation style is strictly related to the project that I am working. Emacs is an editor that can work as IDE, also provides extensibility through its embedded Emacs Lisp interpreter, allowing very nice modes and extensions to be programmed in a well known functional language.

On Emacs almost all events have a hook, where each hook is an event handler. For example to change the indentation style for each C and C++ project that I have I use ecb-after-directory-change-hook, where the event handler has an assigned function symbol to be called by the hook handler every time that the event is triggered, and this case the event is triggered on each directory change on the source tree navigator — called Speedbar — with two arguments, where the first one is the old directory and the second one is the new directory. So, KNF style based projects and Python Style based projects are respecting its indentation thanks to this hook. Thanks to this kind of features I have all my C and C++ projects with its own include paths, styles, and its own search tools, like CScope and Global. And those really large projects are quickly indexed with the proper tools. I really cannot imagine Eclipse with CDT indexing the Linux Kernel or indexing the FreeBSD Kernel, and I cannot imagine Code Blocks indexing both projects.

Emacs with FCM Project

Emacs with FCM Project

I have tried using Eclipse and similar ones with C and C++ projects, with Haskell, Python, and various other languages — currently I am working only with C, C++, Haskell, Lisp, Python and Java — and every IDE that I have tried is not working well as Emacs does. Also they are not easily extensible, they require to build its own extension projects and similar stuff. Too much work to add a small feature like directory hooks and others like completion hooks as semantic-idle-completions-mode-hook helps me on filtering symbols.

They compare Emacs with operating systems, because there are many modes, including audio playing modes — to listen mp3 and similar audio files — and seems to be true. I usually have my Emacs session open with my task list on org-mode and some other nifty modes that are making my work even better than using integrated desktops. The problem with Emacs is the learning curve, because it is very slow if you do not know anything about the Lisp programming language, but learning Lisp is not so hard as you think.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | 2 comments | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/07/why-i-still-use-emacs/feed/ 2
haskell and emacs http://coder.cl/2012/02/haskell-and-emacs/ http://coder.cl/2012/02/haskell-and-emacs/#comments Mon, 20 Feb 2012 12:17:04 +0000 Daniel Molina Wegener http://coder.cl/?p=2262 I think that I have a very nice integration between Haskell and Emacs. The first stuff that you should do to work with Haskell under Emacs, is to integrate the haskell-mode in Emacs with the proper hook to get the haskell-mode fully functional and working fine with Haskell code, so you can use Emacs as most likely an IDE rather than a simple text editor. That can be done thanks to the powerful Emacs Lisp interpreter that has embedded the Emacs editor.


(defun dmw-haskell-pointfree-region ()
  "Executes the Haskell pointfree too on the marked region."
  (interactive)
  (let ((pfcmd (format "pointfree %s"
                       (shell-quote-argument (buffer-substring-no-properties
                                              (region-beginning)
                                              (region-end))))))
    (message (format "%s" (shell-command-to-string pfcmd)))))

(defun dmw-haskell-pointfree-replace ()
  "Replaces the marked region with the Haskell pointfree evaluation."
  (interactive)
  (let ((pfcmd (format "pointfree %s"
                       (shell-quote-argument (buffer-substring-no-properties
                                              (region-beginning)
                                              (region-end))))))
    (shell-command-on-region (region-beginning) (region-end) pfcmd t)))

(defun dmw-haskell-hlint-buffer ()
  "Runs hlint on the currently edited file."
  (interactive)
  (set (make-local-variable 'compile-command)
       (let ((file (file-name-nondirectory buffer-file-name)))
         (format "hlint %s" file)))
  (message compile-command)
  (compile compile-command))

(defun dmw-haskell-mode-hook ()
  "Haskell Mode Hook."
  (setq haskell-program-name "/usr/bin/ghci"
        indent-tabs-mode nil)
  (turn-on-haskell-doc-mode)
  (turn-on-haskell-indentation)
  (turn-on-haskell-decl-scan)
  (capitalized-words-mode t)
  (define-key haskell-mode-map "C-cC-p" 'dmw-haskell-pointfree-region)
  (define-key haskell-mode-map "C-cC-r" 'dmw-haskell-pointfree-replace)
  (define-key haskell-mode-map "C-cC-c" 'dmw-haskell-hlint-buffer)
  (message ">>> done dmw-haskell-mode-hook..."))

So, some nice thing about this mode-hook, is the fact that it can search for documentation on each function using C-c M-/ and find definitions using C-c M-.. With two custom commands which can allow you to use Pointfree — which can be installed using cabal — and Hlint — which can be found usually under your operating system without problems and can be installed using cabal too. So, to use Hlint with this hook, you can start it with C-c C-c or C-c C-v, and you can see if there is a point free style replacement for the selected expression — using Emacs region selection — with the binding C-c C-p, and if you like the point free style replacement, you can replace the selected region with the point free style expression using the binding C-c C-r.

I will try to add more nice stuff to my Haskell hook, probably something like searching modules and ordering imports, because would be nice to have similar stuff running under Emacs, to allow more easy to handle Haskell edition under Emacs. Enjoy!


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/02/haskell-and-emacs/feed/ 0
integrating pycheckers and emacs http://coder.cl/2011/08/integrating-pycheckers-and-emacs/ http://coder.cl/2011/08/integrating-pycheckers-and-emacs/#comments Tue, 09 Aug 2011 17:17:59 +0000 Daniel Molina Wegener http://coder.cl/?p=1728 There are many versions of the pycheckers.py script. It is wrapper between various static analysis tools for Python code. I have my own modified version of the pycheckers script and it is running pep8, pychecker, pyflakes and pylint. I have that script integrated with Emacs, so I run the compile command to verify the code quality. My code should meet all Python standards to pass all checks that are made by those tools.

You can download my version of the pycheckers.py script and you must put it on path available from the PATH environment variable scope. You must be sure that Emacs finds the pycheckers.py command in your PATH.


;;; load the python mode.
(autoload 'python-mode
          "python-mode"
          "Mode for editing Python source files")

;;; autoload the python-mode on each opened python file.
(setq auto-mode-alist
		(append '(("\.py" . python-mode)) auto-mode-alist)))

;;; we ensure that we will use the font-lock mode
;;; on Python files.
(setq font-lock-auto-mode-list
      (list 'python-mode))

;;; finally we create the python mode hook function.
(defun dmw-python-mode-hook ()
  (setq py-indent-offset 4
        py-smart-indentation nil
        py-continuation-offset 4
        indent-tabs-mode nil
        py-pychecker-command "pycheckers"
        py-pychecker-command-args (quote ("")))
  (setq interpreter-mode-alist(cons '("python" . python-mode)
                                    interpreter-mode-alist))
  (eldoc-mode 1)
  (define-key py-mode-map "C-cC-w" (lambda ()
                                      (interactive)
                                      (command-execute
                                       'py-pychecker-run)))
  (message ">>> done dmw-python-mode-hook..."))

;;; then we add the hook function.
(add-hook 'python-mode-hook 'dmw-python-mode-hook)

I hope that you will enjoy checking your code. You just need to install pep8, pylint, pychecker and pyflakes.


© Daniel Molina Wegener for coder . cl, 2011. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2011/08/integrating-pycheckers-and-emacs/feed/ 0
killing equally named buffers in emacs http://coder.cl/2011/05/killing-equally-named-buffers-in-emacs/ http://coder.cl/2011/05/killing-equally-named-buffers-in-emacs/#comments Tue, 03 May 2011 12:56:21 +0000 Daniel Molina Wegener http://coder.cl/?p=1466 As you know I am an Emacs user. Also, I usually implement small commands on it to help me in my programming tasks. For example while I am working with Django — the Python framework — usually I must open various files with the same name, for example views.py and urls.py. Once you have modified various of those files and you want to close them, you need to visit each buffer and apply the kill-buffer command on each one. I have created — for my comfort — a pair of commands that can close various buffers at once.

The first one is batch-kill-buffer-equal-named, which can kill various unmodified buffers at once. You just need to place your current buffer to the buffer that has the name that you want to kill, and apply that command.


(require 'cl)

(defun batch-kill-buffer-equal-named ()
  (interactive)
  (let ((cbn (file-name-nondirectory
              (buffer-file-name
               (current-buffer)))))
    (let ((eqn-nm (lambda (x)
                    (and (not (eq (buffer-file-name x) nil))
                         (and (string= (file-name-nondirectory
                                        (buffer-file-name x))
                                       cbn)
                              (not (buffer-modified-p x))))))
          (tmp-buffer-list (copy-tree (buffer-list))))
      (dolist (cb (remove-if-not eqn-nm tmp-buffer-list))
        (kill-buffer cb)))))

The command above uses the standard Emacs Lisp functions, also some Emacs CL (Common Lisp) functions to make some tasks easier. So, you need to use the cl package. The other command, applies the same logic, but instead of asking for buffer modifications, it saves the visited buffer and then kills it.


(defun batch-kill-buffer-save-equal-named ()
  (interactive)
  (let ((cbn (file-name-nondirectory
              (buffer-file-name
               (current-buffer)))))
    (let ((eqn-nm (lambda (x)
                    (and (not (eq (buffer-file-name x) nil))
                         (and (string= (file-name-nondirectory
                                        (buffer-file-name x))
                                       cbn)))))
          (tmp-buffer-list (copy-tree (buffer-list))))
      (dolist (cb (remove-if-not eqn-nm tmp-buffer-list))
        (progn (save-buffer cb)
               (kill-buffer cb))))))

This is one the reasons why I am very pleased to use Emacs, you can extend it and customize it without complex tasks, you just need to know how to program using the Emacs Lisp dialect. Then you can place those commands on binding of your taste, I have those commands configured with the following bindings:


(global-set-key "C-cC-q" 'batch-kill-buffer-equal-named)
(global-set-key "C-cC-a" 'batch-kill-buffer-save-equal-named)

I think that you will enjoy your favourite editor… Emacs :)


© Daniel Molina Wegener for coder . cl, 2011. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2011/05/killing-equally-named-buffers-in-emacs/feed/ 0
directory based hooks in emacs http://coder.cl/2010/10/directory-based-hooks-in-emacs/ http://coder.cl/2010/10/directory-based-hooks-in-emacs/#comments Fri, 08 Oct 2010 23:46:09 +0000 Daniel Molina Wegener http://coder.cl/?p=968 Some time ago, I was using ecb-mode — Emacs Code Browser — hooks to specify which hook will run on certain directory, so I was configuring Emacs to run certain hook based on the directory of the file. The ecb-after-directory-change-hook was great to integrate Emacs and well defined project specific indentation modes for C, C++ and some other languages. Each project has its own indentation style, for example for Python extensions, you must use the python style: (setq c-default-style "python"); for the Linux Kernel you must use the “linux” style: (setq c-default-style "linux"); for GNU related tools, you must use the gnu style: (setq c-default-style "gnu") and for the FreeBSD operating system, you must the knf style: (setq c-default-style "knf").

This small trick, will allow you to use certain style and run your project specific hook based on the directory name or file name that is visited by Emacs.

(defvar dmw-visit-file-mode-list
  '(("/home/dmw" caffeine-c-mode-hook)
    ("/work/src/caffeine" caffeine-c-mode-hook)
    ("/work/src/caffeine++" caffeine-c++-mode-hook)
    ("/work/src/fireservice" caffeine-c++-mode-hook)
    ("/work/src/Linux" gnu-c++-mode-hook)
    ("/work/src/FreeBSD" caffeine-c-mode-hook)
    ("/work/src/jaxer/products/server/src" caffeine-c++-mode-hook)
    ("/work/src/syslog-ng" caffeine-c-mode-hook)
    ("/work/src/pyxser" python-c-mode-hook)
    ("/work/gae/gae-1.3.7/cclp" python-mode-hook)
    ("/work/gae/gae-1.3.7/todo" python-mode-hook)
    ("/work/gae/gae-1.3.7" python-mode-hook)
    ("/work/www" dmw-php-mode-hook)))

(defun dmw-directory-based-c-hook ()
  (make-local-variable 'tab-width)
  (make-local-variable 'indent-tabs-mode)
  (make-local-variable 'fill-column)
  (make-local-variable 'tab-width)
  (make-local-variable 'c-tab-always-indent)
  (make-local-variable 'c-auto-hungry-initial-state)
  (make-local-variable 'c-default-style)
  (make-local-variable 'c-indent-level)
  (make-local-variable 'c-auto-hungry-initial-state)
  (make-local-variable 'c-block-comment-prefix)
  (make-local-variable 'c-basic-offset)
  (make-local-variable 'c-offsets-alist)
  (make-local-variable 'c-tab-always-indent)
  (make-local-variable 'fill-column)
  (dolist (dir-mode-pair dmw-ecb-directory-change-alist)
    (let ((dir-name (concat (first dir-mode-pair) ".*"))
          (mode-is (car (last dir-mode-pair)))
          (match-dir-based (string-match
                            (concat (first dir-mode-pair) ".*")
                            (buffer-file-name))))
      (if (and (numberp match-dir-based)
               (>= match-dir-based 0))
          (funcall mode-is))))
  (message ">>> done dmw-directory-based-c-hook..."))

Where each hook function on the dmw-visit-file-mode-list, runs each time that a file is visited. For example if I visit a file on the "/work/src/pyxser" directory, it will run the python-c-mode-hook function as mode hook.

;;; I add dmw-directory-based-c-hook to both C and C++ mode hook lists
(add-hook 'c-mode-hook 'dmw-directory-based-c-hook)
(add-hook 'c++-mode-hook 'dmw-directory-based-c-hook)
;;; instead of adding directly the python-c-mode-hook
(add-hook 'c-mode-hook 'python-c-mode-hook)
;;; which is only one, so, I leave project specific hooks to be handled
;;; based on its directory

And the python-c-mode-hook hook function, looks as follows:

(defun python-c-mode-hook ()
  (setq c-default-style "python")
  (setq tab-width 4)
  (setq indent-tabs-mode nil)
  (setq c-tab-always-indent t)
  (setq c-basic-offset 4)
  (setq c-auto-hungry-initial-state 'none)
  (setq c-tab-always-indent t)
  (setq c-block-comment-prefix "* ")
  (setq fill-column 78)
  (c-set-offset 'arglist-cont 4)
  (c-set-offset 'arglist-cont-nonempty 4)
  (c-set-offset 'statement-cont 4)
  (c-set-offset 'label [0])
  (c-set-style "python")
  (message ">>> done python-c-mode-hook (style %s)" c-indentation-style))

Happy programming under Emacs ;)


© Daniel Molina Wegener for coder . cl, 2010. | Permalink | 2 comments | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2010/10/directory-based-hooks-in-emacs/feed/ 2
emacs as python ide http://coder.cl/2010/09/emacs-as-python-ide/ http://coder.cl/2010/09/emacs-as-python-ide/#comments Thu, 30 Sep 2010 19:53:45 +0000 Daniel Molina Wegener http://coder.cl/?p=951 Emacs is a powerful text editor. It has an embedded List dialect interpreter, called Emacs-Lisp and it has many extensions — called Emacs Modes — to work in various tasks, from programming tasks, IRC clients, MUAs and time organizing tasks. Many people says that Emacs works likely an Operating System, since it has a lot of applications mounted on top of Emacs Lisp. Python Mode (python-mode) in emacs has been extended and it can be used with various tools, turning your Emacs editor in a powerful IDE to work with Python.


python-mode

Emacs is configured through the Lisp dialect Emacs-Lisp. Core configuration directives are processed from the ~/.emacs file. To enable the python-mode, you just need to load the python-mode each time that your Emacs editor opens a Python file.


;;; auto load python-mode
(autoload 'python-mode "python-mode" "Mode for editing Python source files")

;;; enable python-mode on .py files
(setq auto-mode-alist
      (append '(("\.py" . python-mode)
                ) auto-mode-alist))

;; auto font lock mode
(defvar font-lock-auto-mode-list
  (list 'python-mode))

Also i known that each Emacs Mode, has some hooks, and python-mode isn’t an exception. To customize the python-mode you can use the python-mode-hook variable:


(add-hook 'python-mode-hook 'dmw-python-mode-hook)

Where, in this case, dmw-python-mode-hook is a symbol pointing to a function called dmw-python-mode-hook:


;; python mode hook
(defun dmw-python-mode-hook ()
  (load "py-mode-ext")
  (load "pyp")
  (require 'pycomplete)
  (setq py-indent-offset 4)
  (setq py-smart-indentation t)
  (setq py-continuation-offset 4)
  (setq indent-tabs-mode nil)
  (setq py-pychecker-command "~/bin/pylint_etc_wrapper.py")
  (setq py-pychecker-command-args (quote ("")))
  (autoload 'pymacs-load "pymacs" nil t)
  (autoload 'pymacs-eval "pymacs" nil t)
  (autoload 'pymacs-apply "pymacs")
  (autoload 'pymacs-call "pymacs")
  (setq interpreter-mode-alist(cons '("python" . python-mode)
                                    interpreter-mode-alist))
  (eldoc-mode 1)
  (define-key py-mode-map [f12] 'pyp)
  (define-key py-mode-map "C-cC-w" (lambda ()
                                       (interactive)
                                       (command-execute 'py-pychecker-run)))
  (define-key py-mode-map [C-S-iso-lefttab] 'py-complete)
  )


python-mode-hook

This python-mode-hook function or hook function, enables a series of features for you python-mode. First, it loads py-mode-ext and pyp, and also loads pycomplete. Those tools are part of the PAGE – Python Automatic GUI Generator package. py-mode-ext adds some nice functions and commands, like py-call-pdb, to begin debugging Python. pyp adds a command/function that prints the current expression, or prompts for an expression to print, with the complete code hierarchy as prefix:


def main():
    if len(sys.argv) != 3:
        print "No dialup numbern"
    txtmsg = sys.argv[2]
    number = sys.argv[1]
    number = number.strip()
    for n in [' ', '+', '(', ')', "s", "t", '-']:
        number = number.replace(n, "");
    number = '+' + number
    skype = Skype4Py.Skype()
    skype.Attach()
    ### this line was generated with the pyp
    ### command that has the line
    ### (define-key py-mode-map [f12] 'pyp) on the
    ### python-mode-hook
    print 'main: skype =', skype    # dmw   pyp
    message = skype.CreateSms(Skype4Py.smsMessageTypeOutgoing, number)
    message.Body = txtmsg
    message.Send()

Finally the pycomplete module has a very nice tool to enable Python auto-completion. For example the following code:


class ParentObject:
    parent1 = None
    parent2 = None
    parent3 = None
    def __init__(self, m1, m2, m3):
        self.parent1 = m1
        self.parent2 = m2
    def child(self, m1, m2, m3):
        self.parent3 = ChildObject(m1, m2, m3)
    def nested(self, m1, m2, m3):
        self.parent3.child4 = NestedChild(m1, m2, m3)
    def subnested(self, m1):
        self.parent3.child4.nested4 = SubNestedChild(m1)
        ### here I press ctrl + s + tab
        ### this will run py-complete as the line
        ### (define-key py-mode-map [C-S-iso-lefttab] 'py-complete)
        ### is defined on the python-mode-hook
        str<Ctrl+S+Tab>
    def __repr__(self):
        return "n-> " + repr(self.__dict__)

This will display a window as follows — where you just need to press mouse-2 or the middle button on your mouse to select one completion:


pychecker

Python static checkers are cool, also are tools that you must use in your daily Python programming tasks. For example, on the Emacs Wiki, you can find this article about using Emacs as Python IDE. There I’ve found the pylint_etc_wrapper.py script, which runs three Python static checkers at once: pylint, pychecker, pyflakes and pep8. Running the pychecker script using the ctrl + cctrl + w key sequence, you will obtain a window similar to the next one, will errors reported from those tools:

I hope that you will enjoy hacking Python from Emacs, it’s a great editor. Also you can use the Emacs Code Browser with Python, I hope that you can find it very interesting.


© Daniel Molina Wegener for coder . cl, 2010. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2010/09/emacs-as-python-ide/feed/ 0
changes in my ecb hooks http://coder.cl/2010/08/changes-in-my-ecb-hooks/ http://coder.cl/2010/08/changes-in-my-ecb-hooks/#comments Sun, 08 Aug 2010 15:54:24 +0000 Daniel Molina Wegener http://coder.cl/?p=800 As you know I’m an emacs user. I use emacs due its flexibility and extensibility, I’m using some major modes like CEDET and ECB. I use some hooks to integrate emacs and my common programming tasks. For example, I can’t imagine programming large projects like the FreeBSD Kernel or Linux Kernel only by using grep(1), egrep(1) or find(1), so I need to index large amount of code files…

For indexing tasks I’ve integrated ECB and cscope-mode, and created some hooks for certain directories. To let ECB know which hook must run on each directory, I’ve created the following variable in my .emacs file:

(defvar dmw-ecb-directory-change-alist
  '(("/work/src/caffeine" caffeine-c-mode-hook)
    ("/work/src/caffeine++" caffeine-c++-mode-hook)
    ("/work/src/fireservice" caffeine-c++-mode-hook)
    ("/work/src/Linux" caffeine-c-mode-hook)
    ("/work/src/FreeBSD" caffeine-c-mode-hook)
    ("/work/src/jaxer/products/server/src" caffeine-c++-mode-hook)
    ("/work/src/syslog-ng" caffeine-c-mode-hook)
    ("/work/src/pyxser" python-c-mode-hook)
    ("/work/gae/gae-1.3.5/cclp" python-mode-hook)
    ("/work/gae/gae-1.3.5" python-mode-hook)))

To let emacs know which directories requires automatic indexing of C code files I’ve created the following variable:

(defvar dmw-ecb-cscope-autoindexing-projects
  '("/work/src/caffeine"
    "/work/src/caffeine++"
    "/work/src/fireservice"
    "/work/src/Linux"
    "/work/src/FreeBSD"
    "/work/src/jaxer/products/server/src"
    "/work/src/syslog-ng"
    "/work/src/pyxser"))

And created the following hook to make each emacs sessions something really productive:

(defun dmw-ecb-directory-change-hook (dirold dirnew)
  (dolist (prji dmw-ecb-directory-change-alist)
    (let ((prj-name (first prji))
          (prj-match (string-match (concat (first prji) ".*") dirnew))
          (prj-hook (last prji))
          )
      (if (numberp prj-match)
          (progn
            (if (>= prj-match 0)
                (dolist (h (last prji))
                  (run-hook-with-args h)))
            (dolist (cscope-auto dmw-ecb-cscope-autoindexing-projects)
              (let ((newpath (concat dirnew "/cscope.out"))
                    (dirnew dirnew))
                (if (and (string= prj-name cscope-auto)
                         (not (file-exists-p cscope-auto)))
                    (progn
                      (setq cscope-database-file newpath
                            cscope-do-not-update-database nil
                            cscope-use-relative-path t
                            cscope-initial-directory dirnew)
                      (cscope-index-files dirnew)))))
            )))))

(defun dmw-cedet-hook ()
  (local-set-key [(control return)] 'semantic-ia-complete-symbol)
  (local-set-key "C-c?" 'semantic-ia-complete-symbol-menu)
  (local-set-key "C-c>" 'semantic-complete-analyze-inline)
  (local-set-key "C-cp" 'semantic-analyze-proto-impl-toggle))

(add-hook 'c-mode-common-hook
          'dmw-cedet-hook)

(add-hook 'ecb-after-directory-change-hook
          'dmw-ecb-directory-change-hook)

(global-ede-mode t)

The dmw-ecb-directory-change-hook run each hook associated with project directories in the dmw-ecb-directory-change-alist list and also, it verify if the directory is present in the dmw-ecb-cscope-autoindexing-projects, and if the directory is on the list, it will call the cscope-index-files function to index the directory using cscope(1).

Also, here is my ecb-activate-hook, which makes coding under emacs quite more productive, and make its behaviour very similar to any another IDE:

(defun dmw-ecb-activate-hook ()
  (custom-set-variables
   '(ecb-display-default-dir-after-start t)
   '(ecb-auto-activate nil)
   '(ecb-options-version "2.32")
   '(ecb-source-path dmw-ecb-working-projects)
   '(ecb-tip-of-the-day nil)
   '(cache-directory-contents
     (quote ((".*caffeine" . 10000)
             (".*caffeine++" . 10000)
             (".*pyxser" . 10000)
             (".*fireservice" . 10000)
             (".*src/" . 10000))))
   )
  (setq-mode-local c-mode semanticdb-find-default-throttle
                   '(project unloaded system recursive))
  (setq-mode-local c++-mode semanticdb-find-default-throttle
                   '(project unloaded system recursive))
  (semantic-add-system-include "/usr/include" 'c++-mode)
  (semantic-add-system-include "/usr/local/include" 'c++-mode)
  (semantic-add-system-include "/usr/include" 'c-mode)
  (semantic-add-system-include "/usr/local/include" 'c-mode)
  (message "ECB Activate Hook Done!"))

emacs rocks ;)


© Daniel Molina Wegener for coder . cl, 2010. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2010/08/changes-in-my-ecb-hooks/feed/ 0
emacs and integrating ecb with cscope http://coder.cl/2009/08/emacs-and-integrating-ecb-with-cscope/ http://coder.cl/2009/08/emacs-and-integrating-ecb-with-cscope/#comments Sat, 01 Aug 2009 17:54:45 +0000 Daniel Molina Wegener http://coder.cl/?p=85

Emacs is a powerful editor, the most powerful and the fastest programmable editor that I know. Emacs uses a Lisp dialect to create configurations, functions and modes. My favorite mode on Emacs is ECB, a powerful code browsing one, like many IDEs that I know. The difference is that ECB, do not does code indexing until you configure it. For large C projects, I like to use external tools, but not ctags or etags, instead I prefer to use cscope. But you may ask "how can I integrate cscope and Emacs running the ECB mode?". Well, in this post I will try to explain how to integrate both, cscope and Emacs.

To know more about ECB, CEDET and related Emacs modes you can look some articles on the Internet, such as "A Gentle introduction to Cedet", by Alex Ott. All of them would help a lot on configuring both, Emacs and ECB. Also the CEDET — the base package for ECB — and ECB itself are well documented.

The cscope mode that I’m using is the cscope mode contributed to the cscope source tree. It’s called xcscope.el and comes with a small cscope indexing script called cscope-indexer.

On ECB there is a hook that runs on every time that you change your working directory by using the directory navigator. The hook is called ecb-after-directory-change-hook. For my C and C++ projects I use various indentation settings, depending on the project that I’m working on. Then, I’ve created a hook function to ecb-after-directory-change-hook that sets the indenting style depending on the project that I’m working on. I’ve created the dmw-ecb-directory-change-alist variable, and it holds the project path and the indenting style to be applied to the project.

(defvar dmw-ecb-directory-change-alist
  '(("/work/dmw/c/caffeine" caffeine-c-mode-hook)
    ("/work/dmw/c/pyxser" python-c-mode-hook)
    ("/work/dmw/cxx/caffeine++" caffeine-c++-mode-hook)
    ("/work/dmw/cxx/qstats" caffeine-c++-mode-hook)
    ("/usr/src/sys" knf)
    ("/current/usr/src/sys" knf)))

Then, I’ve created the hook to apply the indenting style.

(defun dmw-ecb-directory-change-hook (dirold dirnew)
  (dolist (prji dmw-ecb-directory-change-alist)
    (let ((prj-name (first prji))
          (prj-match (string-match (concat (first prji) ".*") dirnew)))
      (if (numberp prj-match)
          (progn
            ;; run hooks and functions related to
            ;; relative path matching on directory browsing
            (if (>= prj-match 0)
                (dolist (h (last prji))
                  (run-hook-with-args h)))
            ;; run hooks and functions related to
            ;; full path matching on directory browsing
            (if (string= prj-name dirnew)
                (let ((newpath (concat dirnew "/cscope.out"))
                      (dirnew dirnew))
                  (progn
                    (setq cscope-database-file newpath
                          cscope-do-not-update-database nil
                          cscope-use-relative-path t
                          cscope-initial-directory dirnew)
                    (cscope-index-files dirnew))))
            )))))

What does this hook? See the documentation for ecb-after-directory-change-hook. On every directory change on the directory browsing window, the hook runs passing the old directory and the new directory as it’s arguments.

Hook which run directly after the selected directory has changed. This means not only after a click onto a directory in the directory-window of ECB but it means this hook runs always when the current directory changes regardless of the trigger of this change[...]

Then, when the hook matches my C and C++ projects, it pass by the (if (>= prj-match 0) expression and setup the indenting style configured in dmw-ecb-directory-change-alist. If the directory pass by the (if (string= prj-name dirnew) expression, then it runs the block related to the new directory bellow the if sentence. What it does? It sets the cscope-database-file variable to the newpath local variable, which have the value of the new directory concatenated with "/cscope.out", also set some variable to ensure that the cscope database is updated, to enable cscope to use relative paths — this enables that cscope can lookup on different directories if the path changes — and set the initial directory to the new directory. Then, it runs the cscope-indexer. In few words, this hooks refresh the cscope database, and sets a permanent database location relative to the project that I’m working on.

Then, somewhere in your .emacs file, you should put your ECB variables as follows.

(add-hook 'ecb-after-directory-change-hook
          'dmw-ecb-directory-change-hook)

Then, just setup the keybinding to use the cscope mode — I do a lot of C programming under emacs, that’s the reason that I’ve configured the keybinding as global, and not local to the C programming mode. Those keybindings bellow are a little bit tricky, you can search for C symbols just by typing Ctrl + Meta + Down. ;)

;; cscope keys
(define-key global-map [(control meta s)] 'cscope-set-initial-directory)
(define-key global-map [(control meta u)] 'cscope-unset-initial-directory)
(define-key global-map [(control meta f)] 'cscope-find-this-symbol)
(define-key global-map [(control meta g)] 'cscope-find-global-definition)
(define-key global-map [(control meta x)] 'cscope-find-global-definition-no-prompting)
(define-key global-map [(control meta m)] 'cscope-pop-mark)
(define-key global-map [(control meta n)] 'cscope-next-symbol)
(define-key global-map [(control meta N)] 'cscope-next-file)
(define-key global-map [(control meta p)] 'cscope-prev-symbol)
(define-key global-map [(control meta P)] 'cscope-prev-file)
(define-key global-map [(control meta c)] 'cscope-display-buffer)
(define-key global-map [(control meta C)] 'cscope-display-buffer-toggle)

I prefer cscope since it have the capability of searching symbols on many ways that other code indexer do not do, and large IDEs like eclipse with CDT gets leaked with large projects like the kernel sources — CDT takes just a few hours to index the complete kernel! — and since cscope is purely made in C and runs really fast.


© Daniel Molina Wegener for coder . cl, 2009. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2009/08/emacs-and-integrating-ecb-with-cscope/feed/ 0