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

Missing bindings #1

Open
claychinasky opened this issue Apr 28, 2023 · 10 comments
Open

Missing bindings #1

claychinasky opened this issue Apr 28, 2023 · 10 comments

Comments

@claychinasky
Copy link

claychinasky commented Apr 28, 2023

Hello, great addon hope to see this improved with maybe more with c++ source editing, like better cursor visuals (faster blinks or solid block cursor etc.)

I think most of the binding there but w is missing, its the most important one I think.
Secondly when cursor at middle of a word, if you do dw, it deletes the whole word, so its doing diw, where it is the most useful, to delete half of the word.
Third one is probably easy too, D should delete everything after the cursor.

I tried to implement the first one, it is working I think, have no idea what I'm doing but here it is:

func move_to_next_word():
	var current_text = code_editor.get_line(curr_line())
	var i = curr_column()
	while i < len(current_text) - 1:
		i+= 1
		if current_text[i] in [' ',':','(',')','.',',']:
			break
		move_column_relative(1)
	move_column_relative(2)
	if i == len(current_text):
		move_line_relative(1)
		code_editor.set_caret_column(1)
	update_selection()	

It's not fully functioning as it should, when cursor at end of the line and the end character is listed in that if statement, you have to press 2 times w to go next word,
and if next line's first character is tab, it select the tab instead of the word.

@joshnajera
Copy link
Owner

Hey thanks!
Woo, It's super exciting to see someone interacting with the repo!! lol
I've been thinking about trying to do it with GDExtension, we'll see how it goes though...

Ooooh, ok! I got started with the changes (quickly implemented D (shift+d) on my machine). I I'll look into correcting dw and implementing w better, and push out an update when I can.
Thanks for the input! :)

@claychinasky
Copy link
Author

claychinasky commented Apr 28, 2023

Nice, I like to help also where I can, and I see some settings in godot editor for caret related values btw, you might wanna check that out, I will look into more at the source code.

Another thing I might add, when you do dw, if its in middle of the word, cursor should stay at same position but if the cursor at the beginning of the word after dw it should call w again to set cursor for the next word beginning. so in theory, you can spam dw per word one by one and delete them.

@joshnajera
Copy link
Owner

I saw something regarding the carets.... but I've only seen empty block style and vertical line style, but I will look again.

Also, I just pushed an update to github; fixing dw, adding w and Shift+d, found a problem with the b command, fixed that too!

Please try it out and let me know if you see any problems!
I'll probably push a new version to the godot asset lib after I get a few more tweaks in.

@claychinasky
Copy link
Author

claychinasky commented Apr 29, 2023

Found a few issues:
w is skipping the first word when it moves line +1 sometimes (most of the time) and also skips _ready() where it should break on _, like skipping func keyword on next line.

For example when w on this line, it should catch v a : A = [ a b c d ... ] and not the ' or ,

var alphanumeric : Array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

w on this line, it should break on v b : A = [ : ; ( ) [ ] , . ? (in theory, w shouldn't catch any symbol but if its in ' it is valued as a string) etc. cause those are the words inside the ' I think this is the where regex must be used in or more LSP helper or c++ parser, not sure how to solve this. but I think it could be assumed to break on every char AFTER the ' or " cause those are high chance are string values and words. But if you do that it will also break on closing ' or " which is mostly whitespace or ,, so if its whitespace or ,it should call w again on white space so it will jump to next word.

var breakers : Array = [':','(',')','[',']','.',',','?','+','=','-','$','%','\'','"']

I will test this more, maybe using regex is the key to move forward, so in theory you could create a long regex to catch wordson whole line, so it can parse a word between quotes fast and reliable. or to simplify, if you do regex.compile("\w+") it will catch every alphabet character and digits but not any other symbols. (in short all words) and if you want to also include _, regex.compile("\w+|_") or more characters.

But more string calculation added, it will get slower, however regex is known to be really fast so.
I know this exists https://github.com/onivim/libvim but it's far too complicated to look at and I'm not good at low level languages. I know this implementation can never be good as native vim, but I think it also really nice to have if it gets to a point where its good enough to use. I'm using chatGPT to create complicated regex'es and online tools to test the regex'es, so you might as well, really cool tools.

@joshnajera
Copy link
Owner

joshnajera commented Apr 29, 2023

Thanks for the follow up!
Yeah, it seems there was a bug with wrapping when nonwhitespace was on first column of a line... I think it should now be fixed for w,b,e,W,B,E functions. Additionally, it should no longer completely skip underscore prefixed things.

However regarding which specific characters they stop on ( ' and , ) I am confused about, as when I'm in vim or nvim, it breaks on all punctuations... I'm wary to stray from the original bindings.

The move to regex sounds like a good idea, I'll let the ideas for implementing it marinate in my mind, lol.

As for your original post

...like better cursor visuals (faster blinks or solid block cursor etc.)...

So I just learned that it is possible to change the blink speed, and thickness of the vertical caret, so now it is possible to do more with it. Also it is possible to set the caret color, but I don't know if that's too "extra".... lol

Thanks for your input so far 🙏🙏

@claychinasky
Copy link
Author

claychinasky commented Apr 29, 2023

yeah you are right about ' and ,, I think I'm used to use code specific custom configs and forgot about vanilla implementation, it's better to stick with original implementation I think.
According to documentation (don't think this is from official docs tho just found it searching for iskeyword settings):

							word
A word consists of a sequence of letters, digits and underscores, or a
sequence of other non-blank characters, separated with white space (spaces,
tabs, <EOL>).  This can be changed with the ['iskeyword'](http://neovim.io/doc/user/options.html#'iskeyword') option.  An empty line
is also considered to be a word.
							WORD
A WORD consists of a sequence of non-blank characters, separated with white
space.  An empty line is also considered to be a WORD.
A sequence of folded lines is counted for one word of a single character.
"w" and "W", "e" and "E" move to the start/end of the first word or WORD after
a range of folded lines.  "b" and "B" move to the start of the first word or
WORD before the fold.
Special case: "cw" and "cW" are treated like "ce" and "cE" if the cursor is
on a non-blank.  This is Vi-compatible, see [cpo-_](http://neovim.io/doc/user/options.html#cpo-_) to change the behavior.
Another special case: When using the "w" motion in combination with an
operator and the last word moved over is at the end of a line, the end of
that word becomes the end of the operated text, not the first word in the
next line.
The original Vi implementation of "e" is buggy.  For example, the "e" command
will stop on the first character of a line if the previous line was empty.
But when you use "2e" this does not happen.  In Vim "ee" and "2e" are the
same, which is more logical.  However, this causes a small incompatibility
between Vi and Vim.

The original implementation is created for creating text based documents I believe, then it's evolved more into technical modal editing. So any non-blank character is considered a word.
I updated the addon but it's still not breaking on _ prefix, and also same goes for ! : * etc. I think rewriting in regex with clear these things up better.

@joshnajera
Copy link
Owner

joshnajera commented Apr 29, 2023

I naively was guessing which special characters were included.... I shoulda just read the docs >.<;;;

Had ChatGPT generated another list of all the special characters in single quotes, comma separated. lol Added in de

Regarding the _ Could it be that you updated the plugin while godot was still running? If it was, you will need to either reload the plugin under project settings, or restart godot.

I'll be looking into regex solutions

@claychinasky
Copy link
Author

Yup, after the restart it worked as should. I think for now it's looking good, but yet to use it in serious manner but will do a list of findings properly.
And there is an addon called plugin refresher (4.x), you might want to install that also.
Thanks for the updates, cheers.

@claychinasky
Copy link
Author

claychinasky commented Apr 30, 2023

after playing with it a bit, these are my findings:

  • c-o and c-i cursor history is missing, I think that's the most used keys for many people for navigate around the document, tho not sure how this can be implemented, maybe store every cursor line and position, if line is changed?
  • document history shortcuts, dunno why my keybindings are not working, which is alt+left or alt+right arrow key, I don't have arrow keys in my keyboard but I can do it with function keys however it doesn't work. so the point is, a keybindings are needed for to go back in history which is the < and > buttons on UI top-right, if you open a docs page or jumped in another script file.
  • jklh movement over folds, where I think the cursor goes hidden inside the folded lines, if you fold all, document became impossible to navigate
  • when you /s for searching, n for next found match or s-n for previous found match could be very nice
  • z-a fold toggle binding
  • s-o doesn't work on first line
  • s-8 doesn't reset cursor to start of the word and if you press few times it loses the track of the symbol
  • w skips over ! and # and : maybe : could be skipped
  • s-k for documentation, ideally it's for inline popup symbol documentation, but I think Godot editor window doesn't have such thing,(but LSP backend does support this) it opens a new window and points to documentation page, like ctrl+click on a symbol
  • documentation hjkl movement, don't know if it can be done, but /s for searing and hjkl movement would be really nice
  • c-j and c-k movement for code completion popup could be really nice, instead of using arrow keys, which maybe if popup is open, maybe c-j can be bind to down arrow key event?
    Again, thanks for working on this. If some of the items are hard to implement I understand, since working on just the editor API, it can't be helped. I wouldn't even thought this even possible without touching the c++.

@data-flux
Copy link

I don't mean to be a negative nancy, and I appreciate the work you've already put into this plugin, but I think a major rewrite is in order, rather sooner than later, to make supporting more keybindings less painful in the future.

Specifically, you probably want to decouple commands from motions.

To prevent having to implement dw, diw, d2w, all seperately, using the d command should wait for the next motion, and after a motion has been entered perform its function. Implementing the motions separately means the same motion will work for movement, deletion, yanking, etc.

Unfortunately, there are also exceptions to this: yy and dd do not follow the <command><motion> paradigm exactly, so y should only be a motion for the yank command, and d only for the delete command.

 

I'm still very new to gdscript, so I can't help much, but I'm willing to help test your plugin :)

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

No branches or pull requests

3 participants