2010-11-02 2 views
3

ПреамбулаEmacs Lisp

Используя библиотеку VTK с C++, довольно часто я должен написать что-то вроде этого:

vtkInteractorStyleRubberBandZoom *isrbz = vtkInteractorStyleRubberBandZoom::New(); 

Кроме того, каждый раз, когда мне нужно использовать новый класс VTK в моей программе, я должен пойти куда-нибудь вверх по исходному файлу и добавить #include "vtkInteractorStyleRubberBandZoom.h"

Как его автоматизировать, так что я должен набирать каждый из мучительно длинных имен классов один раз вместо трех?

Я пробовал написать небольшой режим Emacs для него. Есть, вероятно, уже существующие решения (YaSnippet?), Но я думал, что сам писать тоже будет хорошим упражнением.

Код

;vtk-mode.el 
;add to .emacs: 
;(load "vtk-mode") 
;(global-set-key [(control =)] 'expand-vtk) 

(defun expand-vtk() 
    (interactive) 
    (setq now (point)) 
    (setq vtkstart (search-backward "vtk")) 
    (setq vtkend (- (search-forward " ") 1)) 
    (setq vtkname (buffer-substring vtkstart vtkend)) 

    ;check for #include "vtkBlah.h" 
    (setq includename (format "#include \"%s.h\"\n" vtkname)) 
    (search-backward includename nil (append-include-vtk includename)) 
    (goto-char (+ now (length includename))) 

    (insert (format "= %s::New();" vtkname))) 

(defun append-include-vtk (incname) 
    (goto-char 0) 
    (insert incname)) 

Проблема

В основном, это работает, за исключением того, что поиск для имени включают в себя всегда терпит неудачу, е. g .:

vtkSomething *smth /*press C-= here, it looks backward for 
#include "vtkSomething.h", can't find it and 
calls append-include-vtk, adding it to the beginning 
of the file, then comes back here and expands this line into: */ 

vtkSomething *smth = vtkSomething::New(); 

//and let's add another instance of vtkSomething... 
vtkSomething *smth2 /*press C-= again, it looks backward for 
#include "vtkSomething", and fails, despite the fact 
that it was added by the previous command. So it adds it again."*/ 

Что я делаю неправильно здесь с поиском назад?

(есть еще одна (по крайней мере одна) ошибка в коде, я не должен добавлять (length includename), если поиск назад для нее был успешным, но на данный момент меня больше интересует, как сделать его успешным , в первую очередь)

ответ

2

ОК, я понял. Каким-то образом у меня появилась идея, что третий аргумент обратного поиска (noerror) - это обратный вызов, а это не так. Поэтому он оценивается каждый раз, а не только при неудачном поиске. Это должно быть что-то вроде этого, вместо:

(defun expand-vtk() 
    (interactive) 
    (setq now (point)) 
    (setq vtkstart (search-backward "vtk")) 
    (setq vtkend (- (search-forward " ") 1)) 
    (setq vtkname (buffer-substring vtkstart vtkend)) 

    ;check for #include "vtkBlah.h" 
    (setq includename (format "#include \"%s.h\"\n" vtkname)) 
    (if (search-backward includename nil t) 
     (goto-char now) 
     (progn (append-include-vtk includename) 
      (goto-char (+ now (length includename))))) 

    (insert (format "= %s::New();" vtkname))) 

(defun append-include-vtk (incname) 
    (goto-char 0) 
    (insert incname)) 
1

Команда, которая встроена в Emacs и поможет вам не вводить мучительно длинные имена классов является dabbrev-expand (связан с M-/):

(dabbrev-expand ARG) 

Expand previous word "dynamically". 

Expands to the most recent, preceding word for which this is a prefix. 
If no suitable preceding word is found, words following point are 
considered. If still no suitable word is found, then look in the 
buffers accepted by the function pointed out by variable 
`dabbrev-friend-buffer-function'. 

Набрав vtkInteractorStyleRubberBandZoom раз , в следующий раз вам это нужно, просто введите vtkI M-/.

+0

Спасибо. Я знаю это и использую его, когда это возможно. Тем не менее, это не всегда полезно в данном конкретном случае, потому что в библиотеке так много длинних имен классов, которые используют так много длинных общих префиксов. Есть, например, около 12 классов, начиная с «vtkInteractorStyle ...», и в случае, если мне нужно использовать более одного в одном источнике, мне все равно придется набирать «vtkInteractorStyleX ...» и «vtkInteractorStyleY ... " – Headcrab