Как заменить вкладки пробелами в Atom?

Когда я начал работать с текстовым редактором Atom, я использовал вкладку табуляции, но хочу изменить на 4-пространственный отступ.

У меня есть несколько файлов, которые необходимо обновить соответственно

Каким будет самый простой способ сделать это?

Ответ 1

У Atom есть встроенный инструмент для этого

Активируйте палитру команд (Shift Cmd P на Mac, Ctrl Shift P в Windows/Linux) и найдите "конвертировать пространство" или "конвертировать вкладку". Вы должны найти эти три команды:

  • Пробел: преобразование пространств в вкладки
  • Пробел: конвертирование вкладок в пробелы
  • Пробелы: конвертировать все вкладки в пробелы

Конвертировать вкладки и конвертировать все вкладки

В комментариях вы заметили, что использование "Преобразовать вкладки в пробелы" приведет к поломке отступа в Python, но "Конвертировать все вкладки в пробелы" работает правильно. Вы спросили, какая разница между ними.

Я не знал ответа, поэтому посмотрел. Это определено в пакете "whitespace", источник которого можно найти в Github в atom/whitespace.

Глядя в lib/whitespace.js, я нашел это:

'whitespace:convert-tabs-to-spaces': () => {
  let editor = atom.workspace.getActiveTextEditor()

  if (editor) {
    this.convertTabsToSpaces(editor)
  }
},

'whitespace:convert-spaces-to-tabs': () => {
  let editor = atom.workspace.getActiveTextEditor()

  if (editor) {
    return this.convertSpacesToTabs(editor)
  }
},

'whitespace:convert-all-tabs-to-spaces': () => {
  let editor = atom.workspace.getActiveTextEditor()

  if (editor) {
    return this.convertTabsToSpaces(editor, true)
  }
}

Как вы можете видеть, здесь важна функция convertTabsToSpaces. В варианте "convert all" единственное отличие состоит в том, что передается второй (необязательный) аргумент и устанавливается в true.

return this.convertTabsToSpaces(editor, true)

Рассматривая определение convertTabsToSpaces, разница заключается в том, что регулярное выражение изменяется в зависимости от состояния этого логического аргумента.

convertTabsToSpaces (editor, convertAllTabs) {
  let buffer = editor.getBuffer()
  let spacesText = new Array(editor.getTabLength() + 1).join(' ')
  let regex = (convertAllTabs ? /\t/g : /^\t+/g)

  buffer.transact(function () {
    return buffer.scan(regex, function ({replace}) {
      return replace(spacesText)
    })
  })

  return editor.setSoftTabs(true)
}

Соответствующая строка здесь:

let regex = (convertAllTabs ? /\t/g : /^\t+/g)

Таким образом, в варианте "конвертировать все" регулярное выражение не заботится о привязке к началу строки (^ не используется), и каждая вкладка является собственной заменой (а не группами символов табуляции, обрабатываемых как одна замена - \t против \t+).

Почему это сломало отступ Python

Я не знаю, какой файл вы использовали, но я использовал довольно простой тестовый файл, подобный этому, полностью отступом с символами табуляции.

import foo

class Foo():
    def __init__(self):
        self.foo = True

    def bar(self, a, b):
        return a + b

После использования "Конвертировать вкладки в пробелы" это выглядело так:

import foo

class Foo():
    def __init__(self):
    self.foo = True

    def bar(self, a, b):
    return a + b

Ого! Это теперь SyntaxError. Повторите попытку с помощью "Преобразовать все вкладки в пробелы":

import foo

class Foo():
    def __init__(self):
        self.foo = True

    def bar(self, a, b):
        return a + b

Это происходит потому, что в первом случае группы вкладок на левом поле, как коллекция, сводятся к пространственному отступу. Поскольку регулярное выражение есть ^\t+, не имеет значения, если строка имеет отступ с 1, 2, 8, 24 вкладками... все они заменяются одним уровнем отступа, но сделаны из пробелов.

Честно говоря, я не знаю, в чем дело... это похоже на ошибку.

Во втором случае каждая вкладка преобразуется в эквивалентную ширину на основе пространства (т.е. каждая вкладка преобразуется в 4 пробела, даже если она смежна с другим символом табуляции).

Так что вы, возможно, захотите.

Одно предостережение: это уже не ограничивается левого края (нет ^ якорь), так что если вы встроили символы табуляции в другом месте, те также будут преобразованы. Это не нормальная практика в коде в моем опыте, но FYI, если это имеет для вас значение.

Ответ 2

Простое решение, которое я нашел после некоторых исследований, использует инструмент "Заменить все".

Просто откройте каждый файл и откройте панель поиска (cmd F в Mac).

Screenshot showing replacement of tabs by spaces

Найти в текущем буфере (с активированной опцией use regex):

\t

Заменить в текущем буфере:

    #that being just four spaces