acme: vertical navigation with arrow keys

73 views
Skip to first unread message

Connor Taffe

unread,
Jun 20, 2025, 3:43:18 PMJun 20
to plan9port-dev
Hi folks,

I have really enjoyed using Acme over the last several months. However, there are a couple of features I missed badly enough to implement in Acme, one of those is vertical movement with the arrow keys. I instinctively reach for the arrow keys to move up or down, and moving my hand from the keyboard to the mouse, just to click the next line, then back, feels slow.

The justification I’ve heard for why Acme doesn’t support up/down is because it uses a variable width font by default. I must admit, I do not use a variable width font with Acme — I use /mnt/font/Iosevka/12a/font just like I do in VSCode, IntelliJ, and iTerm2.

There are existing patches for up/down, like the one incorporated into acme2k, but I found the changes to text.c are messy and functionality is not complete. So, I spent an afternoon implementing a simple up/down handler change which navigates to the same position as your cursor on the current line to the previous or next line, and takes into account tabstop such that in a monospaced font, the navigation across lines of varying indentation appears as a straight vertical line.

I am quite happy with the result, it meets my needs. I’ve opened a PR with the expectation that it may not be merged, but as a way to document my patch for anyone else who has the same need.

I’ve also documented the shortcomings I can think of in the PR, and I would love feedback on how to address them.


Jacob Vosmaer

unread,
Jun 20, 2025, 5:12:56 PMJun 20
to cpayn...@gmail.com, plan9port-dev
The justification I’ve heard for why Acme doesn’t support up/down is because it uses a variable width font by default.
I didn't know that but now that you say it that makes sense! FWIW I do use Acme with a variable width font. It took some getting used to but I really like it now. I use the 'Font' command to toggle a window to a monospaced font if I need it. But maybe you know all this already.

My hack for mouseless vertical cursor movement is ctrl-a followed by left arrow, or ctrl-e followed by right arrow. I also rely a lot on auto-formatting (e.g. clang-format) which takes care of vertical alignment of text.

Not trying to talk you out of wanting vertical cursor movement, just sharing. 


 
I must admit, I do not use a variable width font with Acme — I use /mnt/font/Iosevka/12a/font just like I do in VSCode, IntelliJ, and iTerm2.

There are existing patches for up/down, like the one incorporated into acme2k, but I found the changes to text.c are messy and functionality is not complete. So, I spent an afternoon implementing a simple up/down handler change which navigates to the same position as your cursor on the current line to the previous or next line, and takes into account tabstop such that in a monospaced font, the navigation across lines of varying indentation appears as a straight vertical line.

I am quite happy with the result, it meets my needs. I’ve opened a PR with the expectation that it may not be merged, but as a way to document my patch for anyone else who has the same need.

I’ve also documented the shortcomings I can think of in the PR, and I would love feedback on how to address them.


--

---
You received this message because you are subscribed to the Google Groups "plan9port-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to plan9port-de...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/plan9port-dev/922DDB89-135C-41E8-8185-FC6741370E49%40gmail.com.
Message has been deleted

Connor Taffe

unread,
Jun 20, 2025, 6:05:25 PMJun 20
to Jacob Vosmaer, plan9port-dev
Thanks Jacob,

I'm also a fan of ctrl+a/ctrl+e; however arrowing over from the beginning/end of a line is tedious.

The implementation I submitted is ideal for editing code, especially if it involves aligned text -- regardless of your font you will always end up on the next line at the character-aligned position. I've recompiled both my personal and work Acme and am enjoying it.

If the goal is go in a ~straight vertical line, then we have to take into account font-specific character width, and possibly line wrapping; which would involve calculating pixel widths. Obviously this is how most apps work, for instance Mail which I’m composing this in, Google Docs, etc. In a monospaced window, it would behave similarly, but not skip wrapped lines.

On Jun 20, 2025, at 16:12, Jacob Vosmaer <con...@jacobvosmaer.nl> wrote:

The justification I’ve heard for why Acme doesn’t support up/down is because it uses a variable width font by default. 
I didn't know that but now that you say it that makes sense! FWIW I do use Acme with a variable width font. It took some getting used to but I really like it now. I use the 'Font' command to toggle a window to a monospaced font if I need it. But maybe you know all this already.

My hack for mouseless vertical cursor movement is ctrl-a followed by left arrow, or ctrl-e followed by right arrow. I also rely a lot on auto-formatting (e.g. clang-format) which takes care of vertical alignment of text.

Not trying to talk you out of wanting vertical cursor movement, just sharing. 


 
I must admit, I do not use a variable width font with Acme — I use /mnt/font/Iosevka/12a/font just like I do in VSCode, IntelliJ, and iTerm2.

There are existing patches for up/down, like the one incorporated into acme2k, but I found the changes to text.c are messy and functionality is not complete. So, I spent an afternoon implementing a simple up/down handler change which navigates to the same position as your cursor on the current line to the previous or next line, and takes into account tabstop such that in a monospaced font, the navigation across lines of varying indentation appears as a straight vertical line.

I am quite happy with the result, it meets my needs. I’ve opened a PR with the expectation that it may not be merged, but as a way to document my patch for anyone else who has the same need.

I’ve also documented the shortcomings I can think of in the PR, and I would love feedback on how to address them.

Ethan Azariah

unread,
Jun 21, 2025, 9:52:11 AMJun 21
to plan9p...@googlegroups.com
On Fri, Jun 20, 2025, at 8:15 PM, Connor Taffe wrote:
> The justification I’ve heard for why Acme doesn’t support up/down is
> because it uses a variable width font by default.

The more I think about this, the less sense it makes. Vertical movement with a variable width font requires translating between character and pixel positions. Acme must have a way to turn pixel coordinates into character positions for mouse operations. It must have a way to find the pixel positions for the start and end of dot when redrawing the screen. I guess the latter or may not be obviously exposed, I don't know. I haven't read the code.

I also use another simple editor which supports variable width fonts but vertical movement goes by character count not pixel position. I haven't got around to fixing it because I rarely code in 2 dimensions; I don't have columns with comments on the right and don't often need to tweak large multiple-choice conditionals. When I do, well, I guess I'm lucky to have good muscle memory for just putting my hand on the mouse. This very much depends on ergonomics, it's impossible in some situations.

Connor Taffe

unread,
Jun 21, 2025, 7:46:32 PMJun 21
to eek...@fastmail.fm, plan9p...@googlegroups.com
I’d be interested in digging into that, currently all the keyboard shortcut handling takes place in text.c, on the Text of a given window (tag or body). I believe the Win can still be accessed there, or it could be handled earlier.

The latter is what I did to implement another mouse activity: executing commands. I missed ⌘N, ⌘W, ⌘S, ⌘B (go to definition: Ldef), etc. so I implemented them as an execute without a backing Text for the command. They need to be handled like mouse actions, because e.g. in the case of ⌘W (Del) the Win no longer exists. This approach works well, but breaks events because they require a pointer (q0, q1) to text in the tag or body, so they don’t work in e.g. win windows.

I think the options would be to add a new event type, or to paste the command in tag (if not apreset present) and execute it there. The latter is neater, can be done outside of Acme, and has the advantage of adding shortcuts to the tag if left instead of deleted — I gave this a shot with an aeval command with acmefocused and skhd for hotkey mapping. Unfortunately, it was terribly slow, so I’m still using my acme changes.

I’ll include my copy of aeval:

#!/usr/bin/env rc

fn tagevent {
9 awk -v s=$1 '(i=index($0, s)-1) >= 0 { printf "%s%d %d \n", "Mx", i, i+length(s) }'
}

if (~ $winid '') {
winid=`{dial 'unix!'`{namespace}/acmefocused}
}

tag=acme/$winid/tag
event=`{9p read $tag | tagevent $"*}
if (~ $event '') {
printf ' '$* | 9p write $tag
event=`{9p read $tag | tagevent $"*}
}
echo $event >[2=1] | 9p write acme/$winid/event

Best,
Connor Taffe

On Jun 21, 2025, at 08:52, Ethan Azariah <eek...@fastmail.fm> wrote:

--

---
You received this message because you are subscribed to the Google Groups "plan9port-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to plan9port-de...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages