Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Delete duplicated part of the original symbol after expanded candidate #57

Merged
merged 1 commit into from

4 participants

York Zhao Dmitry Gutov Andrea Richiardi Tomohiro Matsuyama
York Zhao

Delete the remaining part of the original symbol after expanded a candidate if
the remaining part of the original symbol is the end part of the expanded
candidate. For example, if the buffer is "some|thing" where '|' is the cursor
position, if "something" is also a candidate and is being expanded, the result
will be "something|" rather than "something|thing". Note that if the buffer is
"|something" and we expanded the candidate "otherthing", the result will be
"otherthing|something" rather than "otherthing|" because in this case I believe
"otherthing" should NOT be replaced by the expanded candidate. Always replacing
the existing symbol with the expanded candidate is not good because in case that
you don't want "something" to be replaced by "otherthing" you will have to move
the cursor one position back first and enter a space, but if "something" is
already at the beginning of the line then you will have to enter a space first
and then press the LEFT arrow to get back which is painful if you use vi
key binding within emacs like myself. Even if you are not using vi key binding,
this is also a very unnatural way of editing.

Dmitry Gutov

I think your code is doing pretty much the same thing as @purcell's #50.

I don't really see a real life scenario where this behavior is better.

My scenario is I think common one - you're editing some C++/JavaScript/Ruby code, see that in some place you called .makeFoo, whereas you should've called .makeBar or something like that. So you go to .make|Foo, initiate the completion, choose the candidate, "Foo" is replaced. That's how all IDEs do it, AFAIK.

The situations when I wouldn't want to replace the rest of the original symbol are quite contrived: I'm writing some Lisp code, I forgot an extra argument in a function call, and it starts with the first half of the next argument, and I in fact need only the rest of the next argument's symbol in that call, for some reason.
Do you have a better scenario? How do you reach this peculiar situation?

York Zhao

I think your code is doing pretty much the same thing as @purcell's #50.

If you compare my code with purcell's you will find them different. At least my
approach doesn't have to take into consideration the "point-max" kind of thing.

I don't really see a real life scenario where this behavior is better.

Let's say the buffer is "|something" and we expanded the candidate "otherthing",
in your approach the original "something" will be replaced, but what if I don't
want "something" to be replaced by "otherthing"? If I want both "something" and
"otherthing" I will have to move the cursor one position back first, enter a
space and start typing and completing, even worse, if "something" is already at
the beginning of the line then I will have to enter a space first, press LEFT
arrow to get back before start typing and completing which is painful if you use
vi key binding within emacs like myself.

My scenario is I think common one - you're editing some C++/JavaScript/Ruby
code, see that in some place you called .makeFoo, whereas you should've called
.makeBar or something like that. So you go to .make|Foo, initiate the
completion, choose the candidate, "Foo" is replaced. That's how all IDEs do it,
AFAIK.

You are right, this is where your approach excels and I took my approach just
because I found myself getting into the scenario I described above more often
than the scenario you provided. I think the idea solution is that if the point
was within the boundary of the current symbol before started typing then replace
the entire symbol, otherwise if the point was at the beginning of the existing
symbol before started typing then just insert the new candidate without touching
the existing symbol.

The situations when I wouldn't want to replace the rest of the original symbol
are quite contrived: I'm writing some Lisp code, I forgot an extra argument in a
function call, and it starts with the first half of the next argument, and I in
fact need only the rest of the next argument's symbol in that call, for some
reason. Do you have a better scenario? How do you reach this peculiar
situation?

I think the scenario you described here is the same as the one I have provided
in my commit message and in this post. The idea solution is what I have wrote
the my previous paragraph.

Dmitry Gutov

Ah, so you're triggering the completion by typing, with ac-auto-start. I disabled it long ago, and only trigger the completion manually. Sorry about the confusion.

The idea looks viable. I'm not going to work on this in the near future, so feel free to pick it up.

York Zhao YorkZ Delete duplicated part of the original symbol after expanded candidate
Delete the remaining part of the original symbol after expanded a candidate if
the remaining part of the original symbol is the end part of the expanded
candidate. For example, if the buffer is "some|thing" where '|' is the cursor
position, if "something" is also a candidate and is being expanded, the result
will be "something|" rather than "something|thing". Note that if the buffer is
"|something" and we expanded the candidate "otherthing", the result will be
"otherthing|something" rather than "otherthing|" because in this case I believe
"otherthing" should NOT be replaced by the expanded candidate. Always replacing
the existing symbol with the expanded candidate is not good because in case that
you don't want "something" to be replaced by "otherthing" you will have to move
the cursor one position back first and enter a space, but if "something" is
already at the beginning of the line then you will have to enter a space first
and then press the LEFT arrow to get back which is painful if you use vi key
binding within emacs like myself. Even if you are not using vi key binding, this
is also a very unnatural way of editing.
a5e2d19
York Zhao

Dear auto-complete maintainer,

I've submitted this pull request more than three years ago. I've used my improvement since then and am extremely happy with it. At the time I submitted my original pull request I was new to Emacs Lisp. Three years later, I'm much more confident with my Emacs Lisp. Therefore, I've refactored my code recently and I'm now re-submitting this pull request again. Please consider my pull request and let me know if it can be accepted. My improvement is similar to the pull request #50, but is better in my opinion. I would appreciate it if you can read the discussion in both pull requests and make a decision.

Thank you,

York

Andrea Richiardi

Wow! Great!!! Can we merge it in? It would also solve my question.

Tomohiro Matsuyama
Owner

I think it is better to be able to handle other than symbol thing, but it might work perfectly in many cases. So I'd like to merge this PR and see results.

Tomohiro Matsuyama m2ym merged commit 32ec905 into from
Andrea Richiardi

Another scenario could be that you have made a mistake and would like to correct it through auto-comglete.
For instance, you would like to complete with some other function name instead of the one you have at the moment at the beginning of a lisp's list. So you go back and triggger auto-complete and select the new symbol.
Intellij Idea gives you the chance of overwriting the next symbol by pressing TAB. Can I achieve this with this patch?

Tomohiro Matsuyama
Owner

If you at the start or middle of the symbol, the answer is yes. Replacing a list like (1 2 3) with the completed symbol doesn't work for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 29, 2014
  1. York Zhao

    Delete duplicated part of the original symbol after expanded candidate

    YorkZ authored
    Delete the remaining part of the original symbol after expanded a candidate if
    the remaining part of the original symbol is the end part of the expanded
    candidate. For example, if the buffer is "some|thing" where '|' is the cursor
    position, if "something" is also a candidate and is being expanded, the result
    will be "something|" rather than "something|thing". Note that if the buffer is
    "|something" and we expanded the candidate "otherthing", the result will be
    "otherthing|something" rather than "otherthing|" because in this case I believe
    "otherthing" should NOT be replaced by the expanded candidate. Always replacing
    the existing symbol with the expanded candidate is not good because in case that
    you don't want "something" to be replaced by "otherthing" you will have to move
    the cursor one position back first and enter a space, but if "something" is
    already at the beginning of the line then you will have to enter a space first
    and then press the LEFT arrow to get back which is painful if you use vi key
    binding within emacs like myself. Even if you are not using vi key binding, this
    is also a very unnatural way of editing.
This page is out of date. Refresh to see the latest.
Showing with 18 additions and 2 deletions.
  1. +18 −2 auto-complete.el
20 auto-complete.el
View
@@ -1170,6 +1170,22 @@ You can not use it in source definition like (prefix . `NAME')."
"Abort completion."
(ac-cleanup))
+(defun ac-extend-region-to-delete (string)
+ "Determine the boundary of the region to delete before
+inserting the completed string. This will be either the position
+of current point, or the end of the symbol at point, if the text
+from point to end of symbol is the right part of the completed
+string."
+ (let* ((end-of-symbol (or (cdr-safe (bounds-of-thing-at-point 'symbol))
+ (point)))
+ (remaindar (buffer-substring-no-properties (point) end-of-symbol))
+ (remaindar-length (length remaindar)))
+ (if (and (>= (length string) remaindar-length)
+ (string= (substring-no-properties string (- remaindar-length))
+ remaindar))
+ end-of-symbol
+ (point))))
+
(defun ac-expand-string (string &optional remove-undo-boundary)
"Expand `STRING' into the buffer and update `ac-prefix' to `STRING'.
This function records deletion and insertion sequences by `undo-boundary'.
@@ -1189,10 +1205,10 @@ that have been made before in this function. When `buffer-undo-list' is
(progn
(let (buffer-undo-list)
(save-excursion
- (delete-region ac-point (point))))
+ (delete-region ac-point (ac-extend-region-to-delete string))))
(setq buffer-undo-list
(nthcdr 2 buffer-undo-list)))
- (delete-region ac-point (point)))
+ (delete-region ac-point (ac-extend-region-to-delete string)))
(insert (substring-no-properties string))
;; Sometimes, possible when omni-completion used, (insert) added
;; to buffer-undo-list strange record about position changes.
Something went wrong with that request. Please try again.