Змінити відступ із 2 пробілами на 4 пробіли у vim


93

Я скопіював деякі коди з Інтернету, які мають відступ із двома пробілами, і я хочу змінити його на відступ із 4 пробілами. Цікаво, чи існує коротка процедура vim для виконання завдання без необхідності писати сценарій vim? Ось як я зараз роблю це з файлом HTML:

  • Записати макрос
  • Перехід до початку рядка
  • Візуально виділіть усі пробіли до першого появи "<"
  • Зніміть і вставте всі пробіли (в основному, щоб подвоїти їх)
  • Відтворити макрос до кінця файлу

Коротко qa0vt<yp<esc>jq

Підводні камені:

Помилка макросу для порожнього рядка або рядка, який не починається з "<". І я не маю уявлення про те, як розширити це рішення для файлу, який не є HTML.

Відповіді:


174

Загальним способом зміни відступу є зміна табулятора:

Вставте файл у порожній буфер, а потім:

:set ts=2 sts=2 noet
:retab!

Кожні 2 пробіли змінюються на символ TAB, а потім:

:set ts=4 sts=4 et
:retab

Це змінює кожну вкладку на 4 пробіли.

Перевага цього методу полягає в тому, що ви також можете використовувати його навпаки, наприклад, для перетворення з 4 в 2 пробіли.


16
@ XavierT. Я насправді думаю, що цю відповідь досить легко зрозуміти. А може бути , це буде більш зрозуміло , якщо коротке ім'я команда замінити їх повне ім'я: ts: = tabstop, sts: = softtabstopі [no]et: = [no]expandtab.
YaOzI

У якій ситуації retabаргумент може бути корисним, і чому ми не можемо використати його для цього завдання?
joeytwiddle

@joeytwiddle Як я розумію, ви можете використати це і досягти того самого ефекту, що і ця відповідь, використовуючи, :set sts=2 noetі :retab! 2таким чином він буде трохи коротшим (хоча, можливо, менш читабельним) таким чином.
Daan Bakker

Цей метод також змінює 2-пробіли на 4-пробіли в рядкових літералах та інших місцях, а не просто на початку рядка.
nacitar sevaht

3
Поєднайте їх усі: :set ts=2 sts=2 noet | retab! | set ts=4 sts=4 et | retab!а потім використовуйте @:в різних файлах, щоб швидко застосувати одну і ту ж дію.
L__

59

Це може бути можливим за допомогою :set shiftwidth=4і gg=G.


Зверніть увагу, що якщо це не працює, можливо, у вас увімкнений режим, який має якийсь інший вплив на відступ.
Dav Clark

1
Хоча питання не в загальному рішенні, зауважте, що це працює не завжди, особливо з кодом python.
0xc0de

5
Що gg=Gозначає екзат? Я розумію, що ggозначає "перейти до 1,1", а Gозначає "перейти до останнього рядка".
Джонатан Рейнхарт,

5
@JonathonReinhart =робить відступ, тому це просто означає відступ від початку до кінця тексту
alex

працював краще, ніж %retabнеправильно перетворені пробіли, вбудовані всередину рядкових літералів.
Альнітак,

34

Те, що я роблю, дуже схоже на підходи esneider та cforbish, але трохи швидше набирає:

:%s/^\s*/&&

Просто замінює пробіл (пробіли або вкладки) на подвійний пробіл ( &замінюється відповідним виразом).


2
Це зручно, оскільки він працює з візуальним виділенням (V), просто відпустіть %.
Тревор Робінсон

1
Мені цей також подобається, б / к, він не псується з будь-яким ручним вирівнюванням таблиць, які я маю в коментарях тощо
stephenmm

@TrevorRobinson Дві найкращі відповіді також працюють на діапазони.
Brian McCutchon

Це також має додаткову перевагу в тому, що ви можете розширити його для використання sedта застосувати до всіх файлів у каталозі superuser.com/a/159286/41494
icc97,

3

Я використав цей регулярний вираз (він подвоює кількість провідних пробілів):

%s;^\(\s\+\);\=repeat(' ', len(submatch(0))*2);g

не %s/\s\+/&&/робить те саме? До речі, я думаю, що gпрапор непотрібний (для одного, ^patternу кожному рядку буде лише 1 збіг , чи не так?)
doubleDown

Дякуємо, що вказали "&". У мене є невелике виправлення вашого, головним чином тому, що ви забули, що "^" %s/^\s\+/&&/gближче.
cforbish

1
Це схоже на відповідь spro, але я ціную відповідь, оскільки дозволяє вам налаштувати його легше, якщо вам потрібно зробити щось дещо складніше.
stephenmm

3

Це дуже давнє запитання, однак усі відповіді ... неправильні ... Vim має дуже простий спосіб перенаправити весь файл. Я дізнався про це після написання власної функції, щоб це зробити, тому я в тому самому човні незнання;)

типу

gg=G

це припускає, що у вас є табстоп, встановлений на те, що вам подобається, (для ОП це буде ts = 4)

Я дізнався про це з http://vim.wikia.com/wiki/Fix_indentation , де згадується

У звичайному режимі, ввівши gg = G, буде зроблено повторний ввід у весь файл. Це окремий випадок; = - оператор. Так само, як d або y, він діятиме на будь-який текст, який ви переміщуєте, за допомогою команди руху курсору. У цьому випадку gg розміщує курсор на першому рядку, потім = G робить повторний відступ від поточної позиції курсору до кінця буфера.


2
1. Якщо прокрутити вниз донизу, ви побачите відповідь, в якій згадується gg = G. 2. Це не завжди працює.
Lim H.

1

Подібно (але дещо простіше) до відповіді cforbish, цей регулярний вираз буде дублювати провідні пробіли

:%s/^\( \+\)/\1\1

Або ви можете використовувати цей інший регулярний вираз для перетворення 2-пробілів у 4-пробіли, зберігаючи одинарні пробіли (і непарні суми загалом)

:%s/^\(\(  \)\+\)/\1\1

Це є,

  • 1 пробіл ⇢ 1 пробіл
  • 2 пробіли ⇢ 4 пробіли
  • 3 пробіли ⇢ 5 пробілів
  • 4 пробіли ⇢ 8 пробілів

1

На додаток до відповіді @ spro, я помістив це у своєму .vimrc

command! -range=% Format :<line1>,<line2>s/^\s*/&&

Просто введіть :Format.

При візуальному виділенні це лише форматує вибрані рядки.

Без візуального виділення це форматує весь файл.


0

Це варіант відповідей на основі регулярних виразів.

У моєму локальному каталозі bin є сценарій bash, який подвоїть кількість пробілів на початку рядка. Введення може бути stdin або файл:

$ cat ~/bin/dblsp
#!/bin/bash

file=${1--}

while IFS= read -r line; do
    echo "$line" | sed 's/\s*/&&/'
done < <(cat -- "$file")

Я використовую це в межах vim, візуально виділяючи рядок і видаючи таку команду:

:'<,'>!dblsp

Це позбавляє мене необхідності вводити (або пам’ятати) регулярний вираз.

Я також використовую його на картах, як показано нижче:

nnoremap <leader>] `[V`]!dblsp<CR>

який застосує його до блоку нещодавно вставленого тексту. Я зазвичай використовую наступну карту, а не вставляю:set paste

nnoremap <leader>p :r !xclip -o<CR>

Мій звичайний робочий процес:

  • виберіть фрагмент коду (наприклад, приклад коду на цій сторінці - 2 пробіли, але я хочу 4)
  • вставити фрагмент коду (, p)
  • змінити інтервал (,])

або просто змінивши відступ на витягнутих блоках, вставлених з іншого буфера.

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