Об’єднайте блоки переплетенням ліній


15

Чи є спеціальний спосіб об'єднати два блоки тексту переплетенням рядків, як-от перехід від цього:

a1
a2
a3
a4
  b1
  b2
  b3
  b4

до цього:

a1
  b1
a2
  b2
a3
  b3
a4
  b4

за декілька команд?

EDIT : Мені дуже подобається рішення Сато Кацури , ось як я його реалізував:

function! Interleave()
    " retrieve last selected area position and size
    let start = line(".")
    execute "normal! gvo\<esc>"
    let end = line(".")
    let [start, end] = sort([start, end], "n")
    let size = (end - start + 1) / 2
    " and interleave!
    for i in range(size - 1)
        execute (start + size + i). 'm' .(start + 2 * i)
    endfor
endfunction

" Select your two contiguous, same-sized blocks, and use it to Interleave ;)
vnoremap <pickYourMap> <esc>:call Interleave()<CR>

Зараз мені цікаво - який ви маєте справу з використанням? Ви блокуєте перейменування субтитрів на телевізійний сезон?
VanLaser

@VanLaser Ха-ха, я ні. Переважно, я розглядаю вихід з програми, яку мені потрібно перевірити на узгодженість щодо порядку створення / потім затримки читання об'єктів. Блоки перемежування полегшують відповідність відповідних рядків у блоках із затримкою виведення. Також мені іноді потрібно переплутати рядки кодів з повторними, схожими інструкціями щодо ведення журналів або тестування. Створити ці інструкції легко за допомогою макросів, потім переплетення їх із фактичним кодом зараз лише за кілька натискань клавіш за допомогою цієї функції, яка чудово почувається :)
iago-lito

1
@ lago-lito - дякую за відповідь! Так, Vim досить універсальний :) Ваше вираз "розбір очей" змусив мене також задуматися у scroll-bindingдвох вікнах Vim.
VanLaser

У мене виникають проблеми з цим, як ви вибираєте два блоки поспіль? Чи повинні вони бути сусідніми?
cbcoutinho

@cbcoutinho Так вони є :) Я не впевнений, що ви могли обирати їх обидва інакше. У прикладі, який я показую, я кладу курсор (скажіть) b1, після чого натискаю, vipщоб вибрати цілий фрагмент, ,itякий є <map-I've-Picked>. Це не працює на вашому боці?
iago-lito

Відповіді:


8

Немає спеціального способу зробити це (наскільки я знаю), але так, це можна зробити за допомогою декількох команд:

function! Interleave(start, end, where)
    if a:start < a:where
        for i in range(0, a:end - a:start)
            execute a:start . 'm' . (a:where + i)
        endfor
    else
        for i in range(a:end - a:start, 0, -1)
            execute a:end . 'm' . (a:where + i)
        endfor
    endif
endfunction

Ви можете запустити його :call Interleave(5, 8, 1). Перший параметр - перший рядок, який потрібно перемістити, другий - останній рядок, а третій - куди їх перемістити. Можливо, ви хочете ввімкнути номери рядків, щоб побачити, що ви робите ( :set number).

Це передбачає, що блоки не перетинаються. Подивіться :help :moveта :help range()зрозумійте, як функціонує функція.

Можливо, є кращі способи підібрати два блоки. Навколо плаває плагін, який повинен дозволяти вам поміняти два блоки. Я не можу згадати ім'я плагіна, але автор (можливо, знаменитий доктор Чіп?) Більше вдумався у пошук інтерфейсу, ніж я. :)


Солодке! Мені потрібні лише два аргументи, оскільки два блоки суміжні і мають однаковий розмір: startі size. З функцією домашньої кави, яка отримує ці значення з вибору, це буде просто ідеально. Я над цим працюю. :)
iago-lito

Цікаве зшивання ? ;)
iago-lito

13

Ось ще одна альтернатива:

:g/^a/+4t .
:+,+5d 

Спочатку скопіюйте рядки, які на 4 рядки нижче, у поточний рядок ( :h :t), а потім видаліть послідовні b рядки ( :h :d)

Ще краще ця команда:

 :g/^a//^\s*b/m .

Що означає, що для кожного рядка, починаючи з знаходження наступного рядка, починаючи з 'b', і переміщуємо його нижче поточного рядка.


1
У другій команді я отримав "E16: Недійсний діапазон". Я спробував .+,$dнатомість, і це спрацювало (як це було .+,.+4d).
Пітер Леверін

Не впевнений, чому це відбувається
Крістіан Брабандт

1
ні, це не так. Читайте: h: діапазон, ви завжди можете використовувати пряму нумерацію замість пошуку регулярних
виразів

2
@ iago-lito Другий трюк завжди працює, але вам потрібно змінити /^\s*bінший :range. наприклад: виберіть 1-й блок, виконайте'<,'>g/^/'>+1m.
dedowsdi

1
@ iago-lito Це по суті те саме, що відповідь Крістіана. Ніщо не є жорстким кодом, якщо візуально вибираєте 1-й блок, який '>+1позначає початок 2-го блоку.
dedowsdi

3

Якщо ви хочете трохи розважитися макросами та позначками, ви можете спробувати щось подібне:

  • Спочатку поставте позначку (тут a) на рядку, що містить a1сma

  • Перейдіть до рядка, що містить b1і позначте йогоmb

  • Почніть записувати макрос у потрібному реєстрі (тут реєстр q)qq

  • Вставте наступне в свій макрос: ddmb'apjma'b

  • Зупиніть записувати макрос за допомогою q

  • Відіграйте його стільки разів, скільки потрібно, X@qде Xкількість часу, щоб грати.

Щоб деталізувати макрос:

dd mb 'a p j ma 'b
 |  |  | | |    |
 |  |  | | |    go back to line marked `b`
 |  |  | | |
 |  |  | | move of one line and replace the mark `a`
 |  |  | insert the deleted line under the line marked `a`
 |  |  go to line marked `a`
 |  mark the future line to move with `b`
 delete the line to move

Редагувати Як згадував lago-lito у коментарях, цей метод замінить позначки та буфери.

  • Щодо знаків, я не думаю, що це справжня проблема: я рідко використовую всі 26 марок у буфері і думаю, що більшість часу знайдуться 2 вільних позначки.

  • Для буфера можна зберегти його у тимчасовій змінній: Перед записом використання макросу :let saveReg=getreg('"')збережіть регістр, і як тільки буде виконана дія, використовуйте :call setreg('"', saveReg)для повернення реєстру до його попереднього стану.

У будь-якому разі я повинен визнати, що це рішення - це просто швидке вирішення та не є оптимальним: на мою думку , відповідь Крістана найкраща, і її слід прийняти, оскільки вона не псується з буферами та позначками, не змушує користувача створювати функція і показує силу глобальної команди.


Цікаво. На жаль, це переписує вміст знаків та регістрів, якими я можу користуватися;)
iago-lito

@ lago-lito: він дійсно перезаписує позначки та буфери. Для знаків я ніколи не використовую всі 26 знаків у своїх буферах, тому не думаю, що це справді проблема. Для буферів це може бути більшою проблемою, я думаю, що ви часто можете знайти невикористаний буфер або, якщо ви справді не можете, використовувати тимчасову змінну та функції getreg()та setreg()зберегти буфер. Але я згоден, що це не оптимальне рішення :-)
statox

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.