jdtsmith / indent-bars

Fast, configurable indentation guide-bars for Emacs
GNU General Public License v3.0
272 stars 7 forks source link

Does not work as expected with tab-based indent #5

Closed zino23 closed 10 months ago

zino23 commented 11 months ago

Hardware: MacBook Pro 16-inch, 2021 with Apple M1 Pro chip OS: macOS Ventura 13.0.1 (22A400) Emacs: 28.2 installed from macos-mac with --with-native-compilation indent-bars: latest version

image

If I add blank lines in between, unexpected guide bars are displayed. image

I haven't got the time to look at the code. So far the package works great with rust-mode and lua-mode. Appreciate your work very much!

jdtsmith commented 11 months ago

Sorry, I see you said go-mode. Can you let me know what variable you use to configure the indent spacing for go-mode? Currently I have no config for that. I'm not sure why the blank lines sort of work, will see once we get the other bars working. You are not using indent-tabs-mode=t here are you?

zino23 commented 11 months ago
jdtsmith commented 11 months ago

Are you sure tabs aren't being inserted for indentation? It seems perhaps they are. If you go to the beginning of an indented line and press right-arrow, does it skip by 8 spaces?

Update: Looking at the source, go-mode does:

  (setq indent-tabs-mode t)

So it's hard-coding tabs for indent. I may consider adding a feature that displays a tab at the appropriate indent as a string of spaces (with appropriate :stipple face properties), but that's TBD (and will be less efficient).

jdtsmith commented 11 months ago

For now I've added an error message when indent-tabs-mode=t. Will revisit when I include tab support.

zino23 commented 11 months ago

Sorry, I can confirm go-mode enables indent-tabs-mode by default (which is because gofmt inserts tabs instead of spaces and does not provide an option to use spaces over the other). So at the moment, go-mode cannot take the advantage of indent-bars :(

jdtsmith commented 11 months ago

Yes, that seems to be the case. I have some ideas for handling tabs, and relaxing the requirement of indent-tabs-mode=nil. It will come with some slight speed penalty but should work with go-mode. Keep an eye out.

the42 commented 10 months ago

Just came here as I was excited about this package (as it also works in the terminal) just to see, that it can't handle tabs. I am also coding go. It's not so much go-mode inserting tabs (which it does) but gofmt enforcing tabs as indentation. I would say 95% of all go code is formatted according to these rules.

I wouldn't wonder if other programming languages or code beautifier are using tabs as indentation,

jdtsmith commented 10 months ago

Will see what I can do.

jdtsmith commented 10 months ago

OK, I've pushed to the dev branch a change that allows indent-bars to work with indent-tabs-mode, by applying a suitable 'display property to the tab characters. Note that dev also includes treesitter support and other new options, so if you have the ability to test this with your go files, please do. If you encounter any issues, please let me know.

the42 commented 10 months ago

I fetched last changes and did checkout the dev-branch As I am on Windows I set '(indent-bars-prefer-character t) However I do not see indent bars but on blank lines

zino23 commented 10 months ago

I checked out the dev branch and created a minimum configuration (in the right window). When I enabled indent-bars-mode, the code is reformatted as shown in the gif. Seems like tab-width is changed in lines where indent-bars should be displayed. I hope the gif can be of some help in illustrating the problems.

output

Thanks for you development!

jdtsmith commented 10 months ago

Thanks for testing. That's what I get for trying this only in emacs-lisp-mode with indent-tabs-mode: there were corner case bugs for "single bars aligned on tab boundaries". Please update dev and try again.

Also, I guess there is a treesitter go mode builtin now? Are people using that? If you want to try it out, you could enable indent-bars-treesit-support and play around with indent-bars-treesit-wrap (after using treesit-explore-mode to find out the node types which wrap: usually function parameters and argument lists). If you get something working with treesit, document it in the Wiki.

the42 commented 10 months ago

Hi,

thanks for your update. I fetched last changes and checked out dev branch. My config is

(use-package indent-bars
  :load-path "~/.emacs.d/local/indent-bars/")

As I am on Windows I configured '(indent-bars-prefer-character t)

When opening a go-buffer I disable indent-tabs-mode, enable indent-bar-mode. However all I get are indent bars on blank lines. Is your support for indent bars on tabs meant to work using characters? Because if not I need no longer investigate.

jdtsmith commented 10 months ago

You shouldn't disable indent-tabs-mode. I understand that that mode is required for go-mode. When indent-bars sees indent-tabs-mode, it knows it has to handle tabs, and does so, whether with stipple or characters.

the42 commented 10 months ago

That's it, looks good to me, thank you for your support and now works with tabs too.

jdtsmith commented 10 months ago

@zino23 any luck?

zino23 commented 10 months ago

@jdtsmith It works like a charm in go-mode and go-ts-mode now!

I haven't been able to get indent-bars-treesit-wrap to work though. As you can see in the picture, after I've set indent-bars-treesit-wrap with

(setq indent-bars-treesit-wrap '((golang function_declaration if_statement block select_statement)))

I still got indent bars with depth more than 1 inside the wrapping elements. I've tested with function_declaration, if_statement, block, select_statement, all without success.

image

jdtsmith commented 10 months ago

Ok great. I just made a few tweaks to how point is saved; please update dev again and give it a test.

The thing to do is M-x treesit-explore-mode, and select the beginning of the line where a wrap occurs, and you want it not to increase depth beyond the start. But I don't quite understand the indentation here (not a Go user): your var is indented from main? That doesn't look correct.

In any case, you need to use the correct language name go, and will also need to turn off no-descend-string since the go string literal is named something weird (I don't know if go supports multi-line strings anyway).

Here it is with indent-bars-treesit-wrap = ((go if_statement)).

image

Not sure you'd ever want this, but you can see it works, and does not add more bars beneath the outermost if. I'd suggest leaving treesit support off (even if using go-ts-mode), then keep a lookout for unwanted extra indentation bars, as in the README.