2015-02-14 2 views
2

Я использую Verilg-mode для emacs каждый день, но выравнивание кода для меня не очень хорошо. Поэтому хочется добавить что-то вроде вертикального выравнивания.Как добавить функцию вертикального выравнивания в основной режим для Emacs

Во-первых, я надеюсь, что для выравнивания декларации такие строки:

bit [1:0] a; 
bit [3254:0] b; 
bit unsigned [P_DWIDTH-1:0] c; 
bit unsigned [P_DWIDTH-1:P_DWIDTH-4] d; 
int e; 

к:

bit   [   1:0   ] a; 
bit   [  3254:0   ] b; 
bit unsigned [P_DWIDTH-1:0   ] c; 
bit unsigned [P_DWIDTH-1:P_DWIDTH-4] d; 
int         e; 

У меня нет большого опыта работы Elisp. Я не уверен, что что-то вроде align-regexp - это правильная вещь? Или кто-нибудь, пожалуйста, укажите мне правильное направление для начала.

+0

Вы также можете задать вопрос об Emacs StackExchange. –

ответ

3

Согласно @homeless ответ, я сделал изменения: Используйте narrow-to-region, чтобы избежать изменения границ области.

(defun align-decl-vertically() 
    "Align verilog declarations." 
    (interactive) 
    (save-excursion 
    (save-restriction 
     (narrow-to-region (region-beginning) (region-end)) 
     ;; remove spaces around ":" 
     (goto-char (point-min)) 
     (while (re-search-forward "\\s-*:\\s-*" (point-max) t) 
     (replace-match ":")) 

     ;; align "[" 
     (align-regexp (point-min) (point-max) "\\(\\s-*\\)\\[" -1 1 0) 
     ;; align ":" 
     (align-regexp (point-min) (point-max) "\\[\\(.+:\\)" -1 0 0) 
     ;; align "]" 
     (align-regexp (point-min) (point-max) "\\s-*\\(\\]\\)" -1 0 0) 
     ;; align variable name 
     (align-regexp (point-min) (point-max) "\\(\\s-+\\)\\S-+;" -1 1 0) 
     (widen)))) 

также найти другой способ обновления правил align для достижения этой цели (это не работает точно так, как я ожидал, но только перечислить здесь, возможно, некоторые бы помочь мне это исправить):

(add-to-list 'align-mode-rules-list        
      '(declaration-range-field-alignment     
       (regexp . "\\(\\s-*\\[\\)\\(.*:\\).*\\S-+\\(\\s-*\\]\\)\\(.*\\)") 
       (group . (1 2 3 4))        
       (modes . '(verilog-mode))       
       (tab-stop . nil)         
       (spacing . (1 0 0 1))        
       (repeat . nil)         
       (justify . t)))         
(add-to-list 'align-mode-rules-list        
      '(declaration-variable-name-alignment    
       (regexp . "\\(\\s-*\\S-*\\s-*;\\)")     
       (group . 1)          
       (modes . '(verilog-mode))       
       (repeat . nil)         
       (tab-stop . nil)         
       (spacing . 1)          
       (justify . t)))   

Но иногда для запуска конечного результата может потребоваться несколько раз запустить align. Я еще не понял, почему.

2

Вы можете попробовать действительно с align-regexp. Имеет следующие поможет вам:

(defun align-decl-vertically() 
    "Align verilog declarations." 
    (interactive) 
    (let ((BEG (region-beginning)) 
     (END (region-end))) 
    (align-regexp BEG END "\\(\\s-*\\)\\[" 1 1 0) 
    (align-regexp BEG END "\\(\\s-*\\)\\]" 1 1 0) 
    (align-regexp BEG END "\\(\\s-*\\)\\s-[^ ]*;" 1 0 0))) 

;; declare a key binding 
(add-hook 'verilg-mode-hook (lambda() (local-set-key (kbd "C-c =") 'align-decl-vertically))) 

Вы должны вставить его в ваш файл инициализации Emacs (например, .emacs или init.el). Когда вы находитесь в verilog-mode, вы можете выделить регион и нажать C-c =, чтобы выровнять объявления. Я протестировал его с вашим примером, и это сработало. Я не знаю, будет ли это работать в общем случае, поскольку я не знаю синтаксиса программирования verilog.

UPDATE

Первая версия не работает по той простой причине, что мы не должны сохранить начало и конец области в переменных, как они меняются после каждого align-regexp вызова. А вот версия, которая должна работать:

(defun align-decl-vertically() 
    "Align verilog declarations." 
    (interactive) 
    (align-regexp (region-beginning) (region-end) "\\(\\s-*\\)\\[" 1 1 0) 
    (align-regexp (region-beginning) (region-end) "\\(\\s-*\\)\\]" 1 1 0) 
    (align-regexp (region-beginning) (region-end) "\\(\\s-*\\)\\s-[^ ]*;" 1 0 0)) 
+0

Спасибо @homeless. Но ваш код не работает для последнего выравнивания строк. Я сделал небольшую модификацию и поместил ее в другой ответ. –

+0

Я просто понял, почему это не сработало. Я действительно опубликовал измененную версию здесь. Я обновлю свой ответ, и теперь он должен работать нормально с одним вызовом. – homeless