4

I am using outshine to organize my code (verilog/systemverilog language).

Here is an example use:

// * Class definition
class my_class extends my_base_class;
   // code ..

   // ** Task 1 definition
   virtual task my_task1;
         // code ..
   endtask 

   // ** Task 2 definition
   virtual task my_task2;
         // code ..
   endtask 
endclass 

Currently, the // ** Task 1 definition and // ** Task 2 definition headers will not be detected as headers by the outshine/outline-mode code as they are auto-indented by my language major-mode: verilog-mode.

Question

Is it possible to tame the indentation logic to NOT certain lines; in this case, they would be the lines beginning with // *?

I have mentioned verilog-mode in this question but this can be a generic problem too, on how to make the indentation ignore certain lines irrespective of the major mode.

I have posted this question with correct contexts on the verilog-mode Forum as well as the outshine github IM.

Solution

Thanks to @glucas's answer, I now have the complete solution (my verilog setup on github) to this long-time problem!

Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179

2 Answers2

5

I believe the relevant Emacs function is indent-according-to-mode, which delegates to a mode-specific function registered with the variable indent-line-function.

Looking at the source for verilog mode, I see that it sets indent-line-function to verilog-indent-line-relative.

One option is to advise verilog-indent-line-relative to check for your special comment syntax and only call the actual function for lines that don't match. Something like this:

(defun my/verilog-selective-indent (&rest args)
  "Return t if the current line starts with '// *'."
  (interactive)
  (looking-at "^[[:blank:]]*// \\*"))

(advice-add 'verilog-indent-line-relative :before-until #'my/verilog-selective-indent)

Note that this uses the Emacs 24.4+ advice mechanism. The :before-until advice means that the advised function will not be called if the advice returns t, so in this case if the the current line starts with // * it will be skipped.

Update

You can delete the leading whitespace on your special matching lines with a slight variation:

(defun my/verilog-selective-indent (&rest args)
  "Return t if the current line starts with '// *'."
  (interactive)
  (let ((match (looking-at "^[[:blank:]]*// \\*")))
    (when match (delete-horizontal-space))
    match))
Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
glucas
  • 20,175
  • 1
  • 51
  • 83
  • Thanks! This works.. *just needed to escape the `\ ` in `\*"))` and make it `\\*"))` to make it work*. Technically this answers the question but can I request a related solution? It would also be great to remove any whites-space before `// \\*`. But I guess that would simply mean to add a regexp replace snippet to `after-write-hook` in `verilog-mode-hook`. – Kaushal Modi Feb 06 '15 at 21:30
  • I made the following additions to make it work for `TAB` initiated indents too, not just those initiated by `indent-region`. (1) Advise another function with the same advising function: `(advice-add 'verilog-indent-line :before-until #'my/verilog-selective-indent)` (2) Wrap the advising function's content in `(save-excursion (beginning-of-line) .. )` If I don't do this, `TAB` inserts a TAB and then calls `verilog-indent-line`. So the expression `(looking-at "^[[:blank:]]*// \\*")` always evaluates to `nil`. Seems to work perfectly so far. Let me know if I missed something obvious here. – Kaushal Modi Feb 06 '15 at 22:07
1

Not a direct answer to your indentation question - @glucas has provided that. But some info that might also help.

The lines in question are apparently comment lines. You can use Lisp macro with-comments-hidden to ignore comments. The comments are temporarily hidden for the duration of the macro body (though you do not see any visible change).

So you could, for example, wrap the problematic indentation code in with-comments-hidden, to effectively have it ignore the existence of any comments.

Just another tool for your tool belt, which might help in contexts like the one you describe.

Macro with-comments-hidden is in library hide-comnt.el.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Thanks Drew. I was unaware of this package. This package might not be useful in my case because I want to indent the whole code correctly including the comments except for the *special comments* that serve as `outline-mode` and `outshine` headers. It's good to know that the `hide-comnt` package option exists. – Kaushal Modi Feb 07 '15 at 00:38
  • I see. Sorry, I didn't realize that it was only particular kinds of comments that were problematic. – Drew Feb 07 '15 at 01:07
  • I didn't know about with-comments-hidden. Seems useful, thanks. – glucas Feb 07 '15 at 13:45