vhda / verilog_systemverilog.vim

Verilog/SystemVerilog Syntax and Omni-completion
359 stars 86 forks source link

How can I set things to indent like this? #205

Closed yosemitescott closed 1 year ago

yosemitescott commented 3 years ago

Thanks for creating such a great plugin!

I recently changes jobs where my old setup had an ancient vim setup where I had tweaked the indent of whatever I had been using to be able to indent like the following (please forgive the missing elements to make this legit code):

module foo (
    clk,
    reset_n,
    i_data,
    o_data
);

input clk;
input reset_n;

always @ (posedge clk or negedge reset_n) 
    begin
        if (!reset_n) 
            begin
                o_data <= 4'b0;
            end 
        else 
            begin
                o_data <= i_data;

                case ( abc )
                    0       :   begin
                                    x <= 0;
                                    y <= 0;
                                end
                    default :   begin
                                    x <= y;
                                    y <= z;
                                end
                endcase
            end
    end
endmodule

Now I use neovim with this fantastic plugin but usually I need to shift things around as the following is how things are aligned from the above example (with let g:verilog_disable_indent_lst="eos,module"):

module foo (
    clk,
    reset_n,
    i_data,
    o_data
);

input clk;
input reset_n;

always @ (posedge clk or negedge reset_n) 
begin
    if (!reset_n) 
    begin
        o_data <= 4'b0;
    end 
    else 
    begin
        o_data <= i_data;

        case ( abc )
            0       :   begin
                x <= 0;
                y <= 0;
            end
            default :   begin
                x <= y;
                y <= z;
            end
        endcase
    end
end
endmodule

Are there some other variables I can set to make this happen or even how to put something in "after"? There are other areas that I need to change the resulting align but I think if I can get each begin not to indent back as you enter the above code as the code following the begin including the end will align the way I prefer. That and maybe the code following the begin would need to key off the begin and not something above it (as in my case statements.)

Thanks!

-Scott

vhda commented 3 years ago

Did some initial work to support that by including a new keyword for g:verilog_disable_indent_lst "standalone". Could you please checkout the branch indent/standalone_blocks and give it a try? Thanks!

yosemitescott commented 3 years ago

Wow thanks for the quick branch on this! It's almost there... the assertion of "standalone" is off though. Things align as before with "standalone" set but do align as expected when "standalone" is not set, which is opposite of what you probably intended.

I tried a few other things and maybe these are a different area then what "standalone" is addressing. Is there a way to indent after similar keywords as always (like initial, forever, repeat, etc)? These are no biggie but yeah, the begin related change is so great to me!

Thanks again!

vhda commented 3 years ago

That is intentional because the variable defines the list of indents we want to disable, so it has inverted behavior. I've included it in the default list, but you noticed it because you have this list in your vimrc. The problem is that most people will have that also and will not be aware of this change. I'll have to resolve that before merging.

Apparently there were some missing keywords for those indentations. Please warn me if you find more.

yosemitescott commented 3 years ago

Sounds good about the variable defines... I was just thinking of user impact if they set up the disable list like you mentioned.

When I first checked this out, I thought I saw the begin indents working wrt the case construct. I starting editing something today and it's not working. Maybe I imagined it working beforehand but now it looks like there is no difference with the standalone option either present or not. I just updated my plugin and still no case joy. The if construct looks good tho.

vhda commented 3 years ago

Could you provide some examples of what's still broken?

yosemitescott commented 3 years ago

Sure.... I copied the example I first posted and ran it thru the filter motion (=) and got this with let g:verilog_disable_indent_lst ="module,eos":

module foo (
    clk,
    reset_n,
    i_data,
    o_data
);

input clk;
input reset_n;

always @ (posedge clk or negedge reset_n) 
    begin
        if (!reset_n) 
            begin
                o_data <= 4'b0;
            end 
        else 
            begin
                o_data <= i_data;

                case ( abc )
                    0       :   begin
                        x <= 0;
                        y <= 0;
                    end
                    default :   begin
                        x <= y;
                        y <= z;
                    end
                endcase
            end
    end
endmodule
vhda commented 3 years ago

Added new variable verilog_indent_block_on_keyword that should enable the behavior you are looking for. Please try and provide feedback. Thanks.

yosemitescott commented 3 years ago

After "let b:verilog_indent_block_on_keyword = 1", I got this when I ran the example thru the filter motion:

module foo (
    clk,
    reset_n,
    i_data,
    o_data
);

input clk;
input reset_n;

always @ (posedge clk or negedge reset_n) 
    begin
        if (!reset_n) 
            begin
                o_data <= 4'b0;
end 
        else 
            begin
                o_data <= i_data;

                case ( abc )
                    0       :   begin
                        x <= 0;
                        y <= 0;
end
                    default :   begin
                        x <= y;
                        y <= z;
end
                endcase
end
end
endmodule

As you can see, all of the end keywords have no ident now and the stuff under the begin in the cases were not aligned as intended. Maybe I'm missing some other variable that I should be setting?

vhda commented 3 years ago

I can't replicate this behavior. Do :let g:verilog_verbose=1 and then press == in on of those end keywords. Then do :messages and copy&paste the result here.

yosemitescott commented 3 years ago

I got these messages when I == on line 31:

SearchForBlockStart: returning l:lnum 18
Return indent to start of block keyword

vhda commented 3 years ago

This is real strange. I've updated the branch to increase the verbosity of the message (you may have to reset your branch). Could you share the message again? Could you also run the following command :echo indent(18)? Thanks!

yosemitescott commented 3 years ago

Here's the message after == on line 31:

SearchForBlockStart: \<begin> returning l:lnum 18

Output of :echo indent(18):

12

vhda commented 3 years ago

That looks good. Can you do the same on line 25?

This is what I have:

SearchForBlockStart: \<begin\> returning l:lnum 22
Return indent to start of block keyword (offset=12)

The algorithm obtains the indent on line 22, which is 20, and measures the offset to begin keyword (12). This is a total of 32. On my end I get the correct indent:

:echo indent(25)
32
yosemitescott commented 3 years ago

This is what I got for line 25:

SearchForBlockStart: \<begin\> returning l:lnum 22

Notice that I didn't get the "Return indent...." message.

Also:

:echo indent(25)
0

I don't know if it makes a difference but I'm using Neovim 0.5

vhda commented 3 years ago

Sync and run the test again. I added a few more debug messages.

Sorry for taking so long, this behavior is really unexpected.

yosemitescott commented 3 years ago

Ok... I updated and got these messages for line 25:

SearchForBlockStart: \<begin\> returning l:lnum 22                                                                                                                                                                                                   
Start indent = 20

Still get 0 for indent(25)

vhda commented 3 years ago

Run:

:echo match(slice(getline(22), 20), 'begin')
yosemitescott commented 3 years ago

Interesting... I get this:

E117: Unknown function: slice
E116: Invalid arguments for function match
vhda commented 3 years ago

I've removed the use of slice(). It should work now :)

yosemitescott commented 3 years ago

It's getting a little closer for me. This is what I get now with b:verilog_indent_block_on_keyword=1

module foo (
    clk,
    reset_n,
    i_data,
    o_data
);

input clk;
input reset_n;

always @ (posedge clk or negedge reset_n) 
    begin
        if (!reset_n) 
            begin
                o_data <= 4'b0;
end 
        else 
            begin
                o_data <= i_data;

                case ( abc )
                    0       :   begin
                                    x <= 0;
                                    y <= 0;
end
                    default :   begin
                                    x <= y;
                                    y <= z;
end
                endcase
end
end
endmodule

The indents looks good except my ends are not indented correctly.

I do see the use of the slice function on line 131 of the indent/verilog_systemverilog.vim file:

let l:block_offset = match(slice(getline(l:start_lnum), l:start_indent), 'begin') 

So I'm guessing that's probably the cause.

vhda commented 3 years ago

Oh... completely forgot about that other one... Hopefully this is the last issue?

yosemitescott commented 3 years ago

Sweet!!! Thank you very much for adding this feature for me!!