abo-abo / lispy

Short and sweet LISP editing
http://oremacs.com/lispy/
1.21k stars 132 forks source link

Variables for Valid Syntax Preceding Delimiters #245

Open noctuid opened 8 years ago

noctuid commented 8 years ago

Various lispy commands rely on knowing what characters (such as ') can precede an opening delimiter (lispy-parens, lispy-splice, lispy-delete, etc.). It might be nice to have variables for these characters to allow changing/updating them in one place. Currently things work fairly well, but there are some occasional problems. It may not be common in emacs lisp to write lambas as #'(lambda...), but splicing or deleting in such a case will leave the # since lispy--delete-quote-garbage doesn't delete #. This also is a problem when dealing with literal vectors (#(...)) in common lisp and scheme. There are some other standard cl reader macros that aren't handled properly (e.g. #= and #.) for lispy-parens.

Also, it probably wouldn't hurt to be more lenient with the space-unless regex in lispy-brackets, since in some scheme implementations, square brackets act the same as parens.

In addition to the differences between various lisp dialects and delimiter types, the user might want to add their own reader macro, so user-customizable variables could be helpful. For example, there is a cl library that adds a #H(...) syntax for creating hash tables.

abo-abo commented 8 years ago

Have a look at the new lispy-quote-regexp-alist. Feel free to customize it for the modes that you're interested in.

We might need to change skip-chars-backward to re-search-backward at some point, but maybe the former is good enough.

noctuid commented 8 years ago

Thanks for adding this.

What do you think about integrating this with other functions as well (maybe with additional variables if necessary)? I think it would also be nice to be able to prevent lispy-parens, lispy-brackets, and lispy-braces from automatically adding a space after valid preceding syntax. Some other functions that don't work properly (besides with the common quote characters) are the various movement functions such as s, w, ol, oh, oj, lispy-teleport, and lispy-newline-and-indent (they will leave behind preceding syntax). lispy-mark-list also won't mark more complicated preceding syntax (due to lispy--bounds-dwim), and lispy-delete-backward will leave the preceding syntax because of its own skip-chars-backward.

I think using regex for things would be nice, especially in the case of common lisp where some of the standard reader macros involve letters and numbers (e.g. #nA(...) for an n-dimensional array).

abo-abo commented 8 years ago

What do you think about integrating this with other functions as well

Good idea, of course. But I don't have the time to do it. If you want to do it, please go ahead.

noctuid commented 8 years ago

I can try to work on this in the next few weeks.

noctuid commented 8 years ago

Would it be okay for some of these commands to look back for whitespace, a delimiter, or the beginning of the line instead of checking for specific characters?

For most commands, I think that would simplify things. For example, for lispy-delete and lispy-splice, when at a left delimiter, instead of calling lispy--delete-quote-garbage, they could delete to the previous whitespace char, delimiter, or to the beginning of the line. I think the same strategy would work for lispy-newline-and-indent-plain and lispy-newline-and-indent. Calling lispy-mark-list with an active region could instead jump to the ( or ) instead of skipping over characters. The region would need to be expanded to the left in this manner for lispy--bounds-dwim when returning the list bounds (which would fix most of the other commands I mentioned).

On a side note, shouldn't the string check be first in lispy--bounds-dwim? Otherwise it will return nil here: "This is a string with some parens. |()".

For the space-unless syntax for the lispy-pair commands, I could add three separate variables like lispy-paren-preceding-syntax. Would that be acceptable?

abo-abo commented 8 years ago

Would it be okay for some of these commands to look back for whitespace, a delimiter, or the beginning of the line instead of checking for specific characters?

Sure, write the way you like. We can optimize/refactor it later if really needed.

For most commands, I think that would simplify things. For example, for lispy-delete and lispy-splice, when at a left delimiter, instead of calling lispy--delete-quote-garbage, they could delete to the previous whitespace char, delimiter, or to the beginning of the line. I think the same strategy would work for lispy-newline-and-indent-plain and lispy-newline-and-indent. Calling lispy-mark-list with an active region could instead jump to the ( or ) instead of skipping over characters. The region would need to be expanded to the left in this manner for lispy--bounds-dwim when returning the list bounds (which would fix most of the other commands I mentioned).

OK.

On a side note, shouldn't the string check be first in lispy--bounds-dwim? Otherwise it will return nil here: "This is a string with some parens. |()".

OK, I'll increase the priority. I think the region's priority should be the first, then the string's.

For the space-unless syntax for the lispy-pair commands, I could add three separate variables like lispy-paren-preceding-syntax. Would that be acceptable?

OK. Just add a test or two because it's not really clear what these commands are expected to do.