Navigating line-wrapped text

I frequently edit markdown files with paragraphs greater than one line long. I’d like to navigate up and down lines based on what I see rather than what Kakoune sees. Does anyone have a user script that adds this behavior? I figure a basic script would count the number of characters on the line, check the tmux pane width, and map up/down keys to the correct number of left/right keypresses, but this leaves out C, ge, gi, etc etc.

Any chance you can provide a visual example?

Sure, I’ll use this example text:

Something something, blah blah blah, I didn’t edit this, it’s just me pontificating and bloviating on a topic of my own choosing — which is █ine I guess. Some more extra characters just to make sure this is long enough.

Note that that renders for me as three lines, the last of which is very short. This will vary depending on the width of your screen.

Desired behavior:

  • If I hit k, I’d like the cursor on the next character up.
  • If I hit j, I’d like the cursor to be one line down, at the end of the third line.
  • gh should put the cursor on the first letter of the second line
  • <a-C> should keep the current selection and select the character directly above the cursor (same character as k navigates to.

This is the way the textarea I’m writing in works, as well as every other editor out there (maybe not vim/emacs?).

Actual behavior:

  • k does nothing because it’s on the “top line”. Same for j.
  • gh goes to the first letter of the first line.
  • <a-C> do nothing for the same reason as k and j.

Another way to put it is that I’d like automatic line breaks to work the same way in a markdown file as hard linebreaks work in a code file. I’d also be interested in getting Kakoune to wrap at word boundaries.

I’m with ya, I often experience the same thing when working with markdown text. Regretfully I don’t have a good solution for you, only workarounds that don’t address your actual problem:

  • Sometimes I use the autowrap-enable command. This works well for writing new content, as it just automatically makes new lines instead of wrapping, but editing existing content is a pain because then I have a bunch of different line lengths
  • Or I setup prettier as my formatter to format my markdown files everytime I save. Then each time I save a line break is inserted at my preferred line width (80 chars for me)

Neither of these directly solve your issue (and just manually insert line breaks), but maybe it’ll help

Hi @jstaab, I write reports using tex format and line lengths tend to form into a single lined wrapped paragraph on the screen. Give this a go word-movement.kak.

# used with alexs wordmovement.kak
define-command -params 1 jump-word %{
    execute-keys -with-hooks "<a-:>%arg{1}whl"
map global normal 'D' ': jump-word %val{count}<ret>' -docstring "jump words"

On the todo list is to put the cursor in 1/4, 2/4, 3/4 position on the selected wrapped line.

# <>
define-command count-selections -docstring "count total number of selections" %{
    evaluate-commands %sh{
       eval "set -- $kak_selections"
       printf "%s\n" "echo $#"

define-command count-selections-length -docstring "count total number of characters in selection" %{
    evaluate-commands %sh{
        eval "set -- $kak_selections_length"
        printf "%s\n" "echo $#"

Hope this helps, thanks mate.

Use it, lose it, or improve it.
⌥ L
Option small L is your friend to get from the middle of a sentence to the next jump point (what ever is the same keys on windows). If you make improvements let me know post it here. Cool, talk later.

# <>
define-command -hidden -docstring "alt-x: wrapper around alt x" \
    alt-x %{ evaluate-commands %sh{
        words=$(printf "%s" "${kak_selection}" | wc -w)
        jump=$(( $words / 2 ))
        printf "%s\n" "execute-keys <a-\;>'$jump'whl"
        unset words
        unset jump

map global user 'j' ': alt-x<ret>' -docstring "mid jump point on sentence selection"

This will drop your cursor down a line (give or take) on current cursor position.
Check out Wrapping on kakoune wiki for more details.

# <>
define-command -hidden alt-x %{
    evaluate-commands %sh{
        printf "%s\n" "execute-keys <a-:>'$width'l<a-b>hl"
        unset width

define-command -hidden alt-X %{
    evaluate-commands %sh{
        printf "%s\n" "execute-keys <a-\;>'$width'h<a-b>lh"
        unset width

map global user 'j' ': alt-x<ret>' -docstring "jump forward window width"
map global user 'J' ': alt-X<ret>' -docstring "jump back window width"

Thanks for these commands!

What is the purpose of unset? I always assumed that when the %sh block is finished, the variables are automatically unset.

this is true, since we start separate shell processes and after command finishes process is killed, so there’s no state, so unset can be removed without any problems.

Because this solution deserved a crowd.

Thank you :sparkles: :trophy: :sparkles: now where did I park that unicorn :unicorn: :metal:

define-command -hidden unset-j %{
    try %{ execute-keys "<a-:>%val(window_width)l<a-b>hl" }

define-command -hidden unset-J %{
    try %{ execute-keys "<a-;>%val(window_width)h<a-b>lh" }

map global user 'j' ': unset-j<ret>' -docstring "jump forward window width"
map global user 'J' ': unset-J<ret>' -docstring "jump back window width"
1 Like