Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smart indenting multi-line `define #1082

Closed
veripoolbot opened this issue Aug 16, 2016 · 9 comments
Closed

Smart indenting multi-line `define #1082

veripoolbot opened this issue Aug 16, 2016 · 9 comments

Comments

@veripoolbot
Copy link
Collaborator


Author Name: Kaushal Modi
Original Redmine Issue: 1082 from https://www.veripool.org
Original Date: 2016-08-16


For auto-indentation does not handle `define macros that extend multiple-lines.

Example (manually indented code before calling @indent-region@):

`define drive_agt(AGT_ID) \
  begin \
      some_agt_seq seq; \
      seq = some_agt_seq::type_id::create \
                 (.name({"some_agt_seq_",$sformatf("%0d", AGT_ID)}), \
                  .contxt(get_full_name())); \
      seq.start(env.adc_agt[AGT_ID].sqr_l1); \
  end

Here is what calling @indent-region@ over that code does!:

`define drive_agt(AGT_ID) \
begin \
    some_agt_seq seq; \
      seq = some_agt_seq::type_id::create \
            (.name({"some_agt_seq_",$sformatf("%0d", AGT_ID)}), \
             .contxt(get_full_name())); \
            seq.start(env.adc_agt[AGT_ID].sqr_l1); \
            end

It would be nice if multi-line defines were handled well.

My work-around is to remove the trailing @@ characters, indent the code and then add them back. But I need to remember to not indent the whole buffer for files containing such `defines.

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2016-08-23T11:06:15Z


Thanks, this is a good suggestion.

Just so you know, the indentation code is pretty fragile and this would add more complication and perhaps performance issues, so it's unlikely to be fixed soon unless you take it on yourself.

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Kaushal Modi
Original Date: 2016-08-23T16:15:52Z


Is not trying to indent the lines ending in @\$@ at all a viable 'solution'?

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Wilson Snyder (@wsnyder)
Original Date: 2016-08-25T10:51:49Z


Is not trying to indent the lines ending in \$ at all a viable 'solution'?

A reasonable thing to be tried.

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Alex Reed
Original Date: 2016-08-25T16:39:50Z


Wilson Snyder wrote:

Is not trying to indent the lines ending in \$ at all a viable 'solution'?

A reasonable thing to be tried.

I tend to agree. I like the idea of semantically-aware indentation inside macros, but it's really not feasible. There's no guarantee that the `define is a complete (System)Verilog statement, therefore we cannot accurately indent the "Right Way" each and every time. Maybe abandoning all attempt at indentation is the best approach.

As a trivial example, consider a multi-line macro that contains quoted text (maybe it's part of a debug/error message). The user most definitely doesn't want their pretty message formatting perturbed by verilog-mode.

@veripoolbot
Copy link
Collaborator Author


Original Redmine Comment
Author Name: Kaushal Modi
Original Date: 2016-08-25T17:41:31Z


Below tests fine in my personal config .. If that looks fine, I can start working on a patch for @verilog-indent-line-relative@ and @verilog-indent-line@.

(defvar modi/verilog-multi-line-define-line-cache nil
  "Variable set to non-nil if the current line is detected as any but the
last line of a multi-line `define such as:

  `define foo(ARG) \          <- non-nil
     begin \                   <- non-nil
       $display(\"Bar\"); \    <- non-nil
       $display(\"Baz\"); \    <- non-nil
     end                       <- nil
 ")

(defun modi/verilog-selective-indent (&rest args)
  "Return non-nil if point is on certain types of lines.

Non-nil return will happen when the current line is part of a multi-line `define like:
     `define foo(ARG) \
       begin \
         $display(\"Bar\"); \
         $display(\"Baz\"); \
       end

This function is used to tweak the `verilog-mode' indentation functions. "
  (save-excursion
     (beginning-of-line)
     (let* ((is-in-multi-line-define (looking-at "^.*\\\\$")) ; \ at EOL
            (do-not-run-orig-fn (or is-in-multi-line-define
                                    modi/verilog-multi-line-define-line-cache)))
       ;; Cache the current value of `is-in-multi-line-define'
       (setq modi/verilog-multi-line-define-line-cache is-in-multi-line-define)
       do-not-run-orig-fn)))
;; Advise the indentation behavior of `indent-region' done using `C-M-\'
(advice-add 'verilog-indent-line-relative :before-until #'modi/verilog-selective-indent)
;; Advise the indentation done by hitting `TAB'
(advice-add 'verilog-indent-line :before-until #'modi/verilog-selective-indent)

@gmlarumbe
Copy link
Contributor

Hi @kaushalmodi , @wsnyder

I have written some code that supports ignoring indentation of multiline macros and custom regexps conditionally through defcustoms (5b9bc2a). It works on GNU Emacs 28.1.

This would enable ignoring indentation for outshine comments (#885), custom "keep indent" markers (#922), or any other custom regexp.

Since this does not rely on advice-add, could this be merged into master?

Thanks!

@wsnyder
Copy link
Member

wsnyder commented Jun 29, 2022

Can you please convert to a pull request? With that not sure we need ignore-regexp.

Also should we say verilog-indent-ignore-multiline-defines instead of -macros?

I don't think we should be changing indentation of any comments that are outside `defines, not sure if you are.

@gmlarumbe
Copy link
Contributor

The verilog-indent-ignore-regexp variable is meant to be used for different things than multiline defines. It defaults to nil so there is no change unless enabled explicitly.

In #885 @kaushalmodi explains why it would be nice to be able to ignore indentation on some specific lines. I also use outshine along with modi's advice function and it works really well for buffer navigation. However, since his solution seems very user-specific the use of a variable with a custom regexp would be much more generic.

If this variable is set to "// \\*" it has the same effect as modi's adviced function. If set to ".*//\\." it will match expressions mentioned in #922. Most likely this function will not be of much use to most people, but it could be very helpful for some particular cases.

@gmlarumbe
Copy link
Contributor

Implemented in #1778

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants