Help to build pluggin show cursor out of scope

Hi,
With multiple selection we sometime have cursors lost in the buffer, and sometime they are located out of our view.

In case I have cursors out of my view and to avoid accident, I would like to make a plugin that replace the top and/or bottom line of my buffer with a text informing of the other cursor.
Something like this: ( maybe with a red background )
" ↑ 3 more cursors on the above text"

How could I achieve such a thing ? Do I have to mess with the JSON-RPC api ? Any tips welcome !

define-command show-cursor-out-of-scope -docstring 'Show cursor out of scope' %{
  # Restore _t_ (top) and _b_ (bottom) registers.
  evaluate-commands -save-regs 'tb' %{
    # Window top line:
    evaluate-commands -draft %{
      execute-keys 'gt'
      set-register t %val{cursor_line}
    }
    # Window bottom line:
    evaluate-commands -draft %{
      execute-keys 'gb'
      set-register b %val{cursor_line}
    }
    # Proceed selections
    evaluate-commands %sh{
      selection_above_count=0
      selection_below_count=0
      window_top_line=$kak_reg_t
      window_bottom_line=$kak_reg_b
      eval "set -- $kak_selections_desc"
      # Selection description format: {anchor-line}.{anchor-column},{cursor-line}.{cursor-column}
      for selection do
        cursor=${selection#*,}
        cursor_line=${cursor%.*}
        cursor_column=${cursor#*.}
        if test "$cursor_line" -lt "$window_top_line"; then
          selection_above_count=$((selection_above_count + 1))
        elif test "$cursor_line" -gt "$window_bottom_line"; then
          selection_below_count=$((selection_below_count + 1))
        fi
      done
      # Display message:
      if test "$selection_above_count" -gt 0 -o "$selection_below_count" -gt 0; then
        printf 'echo -markup {Information} ↑ (%d) | ↓ (%d)' "$selection_above_count" "$selection_below_count"
      fi
    }
  }
}

Probably not the best hook, but enough to try:

hook -group show-cursor-out-of-scope global NormalIdle .* show-cursor-out-of-scope
1 Like

Second version:

Implementation

hook global ModuleLoaded out-of-view %{
  out-of-view-enable
}

provide-module out-of-view %{
  declare-option -docstring 'out-of-view format' str out_of_view_format '↑ (%opt{out_of_view_selection_above_count}) | ↓ (%opt{out_of_view_selection_below_count})'
  declare-option -hidden str out_of_view_status_line
  declare-option -hidden int out_of_view_selection_above_count 0
  declare-option -hidden int out_of_view_selection_below_count 0

  define-command -docstring 'Enable out-of-view' out-of-view-enable %{
    hook -group out-of-view global NormalIdle .* %{
      out-of-view-update
      set-option window out_of_view_status_line ''
      evaluate-commands %sh{
        if test "$kak_opt_out_of_view_selection_above_count" -gt 0 -o "$kak_opt_out_of_view_selection_below_count" -gt 0; then
          printf 'set-option window out_of_view_status_line "%s"\n' "$kak_opt_out_of_view_format"
        fi
      }
    }
  }

  define-command -docstring 'Disable out-of-view' out-of-view-disable %{
    remove-hooks global out-of-view
    set-option window out_of_view_status_line ''
    set-option window out_of_view_selection_above_count 0
    set-option window out_of_view_selection_below_count 0
  }

  define-command -hidden out-of-view-update %{
    # Restore _t_ (top) and _b_ (bottom) registers.
    evaluate-commands -save-regs 'tb' %{
      # Window top line:
      evaluate-commands -draft %{
        execute-keys 'gt'
        set-register t %val{cursor_line}
      }
      # Window bottom line:
      evaluate-commands -draft %{
        execute-keys 'gb'
        set-register b %val{cursor_line}
      }
      # Proceed selections
      evaluate-commands %sh{
        selection_above_count=0
        selection_below_count=0
        window_top_line=$kak_reg_t
        window_bottom_line=$kak_reg_b
        eval "set -- $kak_selections_desc"
        # Selection description format: {anchor-line}.{anchor-column},{cursor-line}.{cursor-column}
        for selection do
          cursor=${selection#*,}
          cursor_line=${cursor%.*}
          cursor_column=${cursor#*.}
          if test "$cursor_line" -lt "$window_top_line"; then
            selection_above_count=$((selection_above_count + 1))
          elif test "$cursor_line" -gt "$window_bottom_line"; then
            selection_below_count=$((selection_below_count + 1))
          fi
        done
        printf 'set-option window out_of_view_selection_above_count %d\n' "$selection_above_count"
        printf 'set-option window out_of_view_selection_below_count %d\n' "$selection_below_count"
      }
    }
  }
}

require-module out-of-view

Configuration

set-option global modelinefmt '{red}%opt{out_of_view_status_line}{default} {{mode_info}} {magenta}%val{client}{default} at {yellow}%val{session}{default} on {green}%val{bufname}{default} {{context_info}} {cyan}%val{cursor_line}{default}:{cyan}%val{cursor_char_column}{default}'
1 Like