Closed fommil closed 9 years ago
back should also go to the start of the block. default emacs "back word" will make
test("do things") {
^doAllTheThings(things)
}
go to
test("do ^things") {
doAllTheThings(things)
}
instead of
test("do things") ^{
doAllTheThings(things)
}
which is very important for greedy delete behaviour.
Hmm... I'm not a big fan of changing the default behavior of emacs movement, so I've tried to keep the word-movement as close as possible to what emacs does in lisp-mode.
I think what you really should ask for is a function that jumps to the beginning (outside) of the current code block. So that would jump from anywhere inside the block in you example to where the cursor is in your last example. Then you could use forward-sexp
(M-C-f
) to jump to the end of it if you want to, for example, mark it.
Also on the todo-list is working versions of beginning-of-defun
function.
All pull requests on these issues are welcome.
I had the feeling there was already something for moving into/out from blocks. The command are down-list
and up-list
, normally bound to M-C-d
and M-C-u
.
@hvesalai it's not so much being able to do this as the ability to bind it to forward/backward-word. That way other emacs features behave as expected (especially delete word).
Sorry, my ENSIME backlog is so long at the moment I won't be able to submit PRs for a long time.
There is also forward-list
and backward-list
, bound normally to M-C-n
and M-C-p
Btw... what do you mean by this+that
? Do you mean that +
should be a word? It is a sexp so backward-sexp
and forward-sexp
consider it as a separate token.
For the CamelCase thing to work, I think we should first try if any of the existing solutions work, such as http://www.emacswiki.org/emacs/CamelCase
@hvesalai yeah, I looked at that one but it seems unmaintained now as its not on melpa
As to your original question, would this be the "specification" of what you want (for the forward directin):
([{
), then down-list
(i.e. M-C-d
)}])
), then forward-char
(i.e. C-f
)forward-sexp
(i.e. M-C-f
)For backward direction:
backward-char
(i.e. C-b
)up-list
(i.e. M-C-u
)backward-sexp
(i.e. M-C-b
)Can you simulate if this behavior matches what you wanted.
I wouldn't want to skip over comments. I'd still expect next/prev word to work as usual.
I don't think it really matters what is currently at the point, it's more about what the next boundary before and after the point is. If I interpret "the thing at the cursor" to mean "the closest thing after/before the cursor" then this sounds sensible.
Default emacs "word" rules are very tailored to English (and elisp) that it doesn't cope well with special characters and often considers them part of the word.
scala-mode2 uses the default emacs word movements, but the syntax table decides what is a word char and what isn't. That's why in this+that
+
is not considered as a word.
yes exactly, so I'm basically asking for a scala-specific syntax table :-)
The syntax table IS scala-specific. Highly so. We even have a syntactify function that extends it.
hmm, maybe it's not working for me then. Should what I'm asking for be working already?
No, but that's how it should be from the syntax-table point of view. +
is not a word and it should not be. It's a "symbol constituent"
Rather, this is what I've documented
;; by default all opchars are punctuation, but they will be
;; modified by syntax-propertize-function to be symbol
;; constituents when a part of varid or capitalid
So actually a +
on it's own is just punctuation from emacs point of view. Only the +
is foo_+
is considered as symbol constituent.
And the reason why +
cannot be a symbol constituent is that then this+that
would be considered as one token. With the current syntax-table
and syntax-propertize-function
that +
is considered as punctuation, which separates the two words.
@hvesalai actually the +
thing was the low priority thing here... I'm much more interested in braces and camelcase being considered word boundaries.
Please try the new scala-syntax:forward-token
function. I'll write the respective backward-token
later after I get feedback on this one.
Here's how I bind it in my scala-mode-hook
(add-hook 'scala-mode-hook '(lambda ()
(local-set-key (kbd "RET") '(lambda ()
(interactive)
(newline-and-indent)
(scala-indent:insert-asterisk-on-multiline-comment)))
(local-set-key (kbd "M-RET") 'scala-indent:join-line)
(local-set-key (kbd "<backtab>") 'scala-indent:indent-with-reluctant-strategy)
(local-set-key (kbd "M-.") 'sbt-find-definitions)
(local-set-key (kbd "C-x '") 'sbt-run-previous-command)
(local-set-key (kbd "<ESC> <right>") 'scala-syntax:forward-token)
(local-set-key (kbd "<ESC> <up>") 'backward-up-list)
(local-set-key (kbd "<ESC> <down>") 'down-list)
))
btw. It doesn't handle camelCase or under_score_separated words yet.
great! But by some bitter rebuke by the universe, I have to work on the only .java
files in our codebase today... shudder
I tried the elpa scala-mode2-20140627.203
today and I can see some differences between the scala forward token and the usual emacs forward word... but I couldn't see if you had created a backwards equivalent yet.
I think it is potentially better, but in order to work well with my existing setup I'm really hoping that I can cook this into forward/backward-word (not just rebind (alt/ctrl)-(left/right) to use this different function) because I have some other scripts that depend on forward/backward-word behaving well for the mode (e.g. hungry delete).
you can easily re-define forward-word
in the scala-mode-hook
(set (make-local-variable 'forward-word) 'scala-syntax:forward-token)
the respective backward-token has not yet been implemented.
p.s. may I ask how you use that hungry delete? I don't know that feature. Tried to google it, but didn't find a good explanation of what it does.
This is my config that gets CamelCase navigation, but not yet integrated with your forward-word. I think having this subword mode working with your boundary logic would be very good! (And I would rebound forward/backward-word in the scala buffers to be your implementation instead... I'm not sure how to do it for my contextual-backspace though)
(subword-mode 1)
(defun contextual-backspace ()
"Hungry whitespace or delete word depending on context"
(interactive)
(if (looking-back "[\t\s\n\r]\\{2,\\}" (- (point) 3))
(hungry-delete-backward 1)
(if (subword-mode)
(subword-backward-kill 1)
(backward-kill-word 1))))
(global-set-key (kbd "C-<backspace>") 'contextual-backspace)
(global-set-key (kbd "C-<left>") 'subword-backward)
(global-set-key (kbd "C-<right>") 'subword-forward)
if you could provide a scala:backward-kill-word
then I could do something with that (unless it uses backward-word
under the hood, in which case it should just work if I remove the special logic for subword-mode
).
I've done a lot of soul searching on this issue, and I am pretty convinced that "standard emacs navigation" is correct... but that regexes don't quite cut it. Therefore for block movement, we're looking at implementing https://github.com/ensime/ensime-server/issues/973 ... so scala-mode2
doesn't need to look at implementing any of the sexpression navigation. regex brace-only sexp navigation is ok but obviously depends on the style of scala being navigated.
For forward/backward word, default emacs works fine and to get subword navigation I use (global-subword-mode 1)
It would be great if alt-{left,right} had special behaviour in scala files, e.g. camel case words are respected, differentiating between variables and operators ("this+that" will be skipped entirely as a single word by default behaviour), etc