Skip to content

mini.move: less intrusive blockwise movement #838

@matu3ba

Description

@matu3ba

Contributing guidelines

Module(s)

mini.move

Description

Use case
Drawing block selections up and down breaks right-wards indentation, which can make virtual edits for adjusting graphics unnecessary painful. I hope below drawings show the problem. Any kind of ideas would be appreciated.

Problem Description

got

                           ┌──────────────┐
                           │              │
                           │              │
          ┌────────────┐   │              │
          │    upsii   │   │              │
          │     123    │   │              │
          │            │   └──────────────┘
          │            │
          │            │
          └────────────┘

want without redundant steps
1 box selection copy
2 selection replace whitespace
3 selection wanted position and paste

                           ┌──────────────┐
                           │              │
                           │              │
          ┌────────────┐   │              │
          │            │   │              │
          │            │   │              │
          │    upsii   │   └──────────────┘
          │     123    │
          │            │
          └────────────┘

current behavior:
1 line selection movements dont work for multiple lines
2 minimove.move_selection up/down breaks right-hand intendation

                           ┌──────────────┐
                           │              │
                           │              │
          ┌────────────┐   │              │
          │       │   │              │
          │       │   │              │
          │    upsii        │   └──────────────┘
          │     123         │
          │            │
          └────────────┘

It would be nice, if move_selection would have another mode
so that a move is an actual swap of text elements freely
into the buffer positions, so moving 1 upwards does

                           ┌──────────────┐
                           │              │
                           │              │
          ┌────upsii───┐   │              │
          │     123    │   │              │
          │    ─────   │   │              │
          │            │   └──────────────┘
          │            │
          │            │
          └────────────┘

and moving 1 more upwards does

                           ┌──────────────┐
                           │              │
               upsii       │              │
          ┌──── 123 ───┐   │              │
          │    ─────   │   │              │
          │            │   │              │
          │            │   └──────────────┘
          │            │
          │            │
          └────────────┘

until

               upsii       ┌──────────────┐
                123        │              │
                           │              │
          ┌────────────┐   │              │
          │            │   │              │
          │            │   │              │
          │            │   └──────────────┘
          │            │
          │            │
          └────────────┘

with the internal position of the collision range be kept.
To me it looks like you have implemented collision detection,
but nothing to keep track of correct fixups after nothig collides.
For example, left and right movements have the same behavior:

                           ┌──────────────┐
                           │              │
                           │              │
          ┌────────────┐   │              │
  upsii        │       │   │              │
   123         │       │   │              │
          │            │   └──────────────┘
          │            │
          │            │
          └────────────┘
local selmove_hint = [[
 Arrow^^^^^^
 ^ ^ _k_ ^ ^
 _h_ ^ ^ _l_
 ^ ^ _j_ ^ ^                      _<C-c>_
]]

local ok_minimove, minimove = pcall(require, 'mini.move')
assert(ok_minimove)
if ok_minimove == true then
  local opts = {
    mappings = {
      left = '',
      right = '',
      down = '',
      up = '',
      line_left = '',
      line_right = '',
      line_down = '',
      line_up = '',
    },
  }
  minimove.setup(opts)
  -- setup here prevents needless global vars for opts required by `move_selection()/moveline()`
  M.minimove_box_hydra = Hydra {
    name = 'Move Box Selection',
    hint = selmove_hint,
    config = {
      color = 'pink',
      invoke_on_body = true,
    },
    mode = 'v',
    body = '<leader>vb',
    heads = {
      {
        'h',
        function() minimove.move_selection('left', opts) end,
      },
      {
        'j',
        function() minimove.move_selection('down', opts) end,
      },
      {
        'k',
        function() minimove.move_selection('up', opts) end,
      },
      {
        'l',
        function() minimove.move_selection('right', opts) end,
      },
      { '<C-c>', nil, { exit = true } },
    },
  }
  M.minimove_line_hydra = Hydra {
    name = 'Move Line Selection',
    hint = selmove_hint,
    config = {
      color = 'pink',
      invoke_on_body = true,
    },
    mode = 'n',
    body = '<leader>vl',
    heads = {
      {
        'h',
        function() minimove.move_line('left', opts) end,
      },
      {
        'j',
        function() minimove.move_line('down', opts) end,
      },
      {
        'k',
        function() minimove.move_line('up', opts) end,
      },
      {
        'l',
        function() minimove.move_line('right', opts) end,
      },
      { '<C-c>', nil, { exit = true } },
    },
  }
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions