Измените отступ с 2 пробелами на 4 пробела в vim


93

У меня есть скопированные из Интернета коды с отступом в два пробела, и я хочу заменить его на четырехсторонний. Интересно, есть ли короткая процедура vim для выполнения задачи без написания сценария vim? Вот как я сейчас делаю это с файлом HTML:

  • Записать макрос
  • Перейти в начало строки
  • Визуально выделить все пробелы до первого появления символа «<»
  • Удалите и вставьте все пробелы (в основном, чтобы удвоить их)
  • Воспроизвести макрос до конца файла

Короче говоря qa0vt<yp<esc>jq

Подводные камни:

Макрос не работает для пустой строки или строки, которая не начинается с «<». И я понятия не имею, как распространить это решение на файл, отличный от HTML.

Ответы:


175

Общий способ изменить отступ - это изменить позицию табуляции:

Вставьте свой файл в пустой буфер, затем:

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

Это меняет каждые 2 пробела на символ TAB, затем:

:set ts=4 sts=4 et
:retab

Это изменяет каждый TAB на 4 пробела.

Преимущество этого метода в том, что вы также можете использовать его наоборот, например, для преобразования из 4 в 2 пробела.


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

В какой ситуации retabаргумент был бы полезен и почему мы не можем использовать его для этой задачи?
joeytwiddle

@joeytwiddle Насколько я понимаю, вы можете использовать это и добиться того же эффекта, что и этот ответ, используя, :set sts=2 noetи :retab! 2поэтому он будет немного короче (хотя, возможно, менее читаемым).
Даан Баккер,

Этот метод также заменяет 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 =делает отступы, поэтому это просто означает отступ от начала до конца текста
Алекс

работал лучше, чем %retab, который неправильно преобразовал пробелы, встроенные в строковые литералы.
Альнитак

34

То, что я делаю, очень похоже на подходы esneider и cforbish, но набираю немного быстрее:

:%s/^\s*/&&

Просто заменяет начальный пробел (пробелы или табуляции) вдвое большим начальным пробелом ( &заменяется совпадающим выражением).


2
Это удобно, потому что работает с визуальным выделением (V), просто опустите %.
Тревор Робинсон,

1
Мне также нравится этот, b / c он не
мешает

@TrevorRobinson Два верхних ответа также работают с диапазонами.
Брайан МакКатчон

Это также имеет дополнительное преимущество: вы можете расширить его, чтобы использовать sedи применить ко всем файлам в каталоге superuser.com/a/159286/41494
icc97

3

Я использовал это регулярное выражение (оно удваивает количество ведущих пробелов):

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

не %s/\s\+/&&/делает то же самое? Кстати, я думаю, что gфлаг не нужен (во- ^pattern
первых,

Спасибо, что указали на "&". У меня есть небольшая поправка к вашему, в основном потому, что вы забыли, что "^" %s/^\s\+/&&/gближе.
cforbish 04

1
Это похоже на ответ spro, но я ценю ответ, поскольку он позволяет вам проще настроить, если вам нужно сделать что-то немного более сложное.
Stephenmm

3

Это очень старый вопрос, однако все ответы ... неверны ... У Vim есть очень простой способ изменить отступ всего файла. Я узнал об этом после написания собственной функции для этого, так что я нахожусь в той же лодке невежества;)

тип

gg=G

это предполагает, что у вас есть табуляция, установленная на то, что вам нравится (поэтому для OP это будет ts = 4)

Я узнал об этом из http://vim.wikia.com/wiki/Fix_indentation , где упоминается

В обычном режиме ввод gg = G приведет к изменению отступа всего файла. Это особый случай; = - оператор. Как и d или y, он будет воздействовать на любой текст, который вы перемещаете с помощью команды перемещения курсора. В этом случае gg помещает курсор в первую строку, затем = G повторно отступает от текущей позиции курсора до конца буфера.


2
1. Если вы прокрутите вниз до конца, вы увидите ответ, в котором упоминается gg = G. 2. Не всегда получается.
Лим Х.

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

Это вариант ответов на основе регулярных выражений.

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

$ 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.