web-dev-qa-db-ja.com

Atomでタブをスペースに置き換える方法は?

Atomテキストエディターの使用を開始したとき、タブインデントを使用していましたが、4スペースインデントに変更したいです。

それに応じて更新する必要があるいくつかのファイルがあります

それを行う最も簡単な方法は何ですか?

43
J0ANMM

Atomにはこのための組み込みツールがあります

コマンドパレットをアクティブにします(ShiftCmdP Macでは、 CtrlShiftP Windows/Linuxの場合)、「スペースの変換」または「タブの変換」を検索します。次の3つのコマンドが使用可能になっているはずです。

  • 空白:スペースをタブに変換
  • 空白:タブをスペースに変換
  • 空白:すべてのタブをスペースに変換

タブの変換とすべてのタブの変換

コメントでは、「タブをスペースに変換」を使用するとPythonのインデントが壊れることが確認されましたが、「Allタブをスペースに変換」は正しく機能しました。 2つの違いは何ですか?.

答えがわからなかったので、見に行きました。これは、「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です。 「すべて変換」バリアントでは、唯一の違いは、2番目の(オプションの)引数が渡され、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 vs. \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です。 「ConvertAllTabs to Spaces」で再試行してください:

import foo

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

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

これは、最初のケースでは、左マージンのタブのグループがコレクションとして、スペースベースのインデントに縮小されるために発生します。正規表現は^\t+であるため、行が1、2、8、24タブでインデントされているかどうかは関係ありません...それらはすべて単一のインデントレベルに置き換えられますが、スペースで構成されています。

正直なところ、私はそのポイントが何なのかわかりません...それはバグのようです。

2番目の場合、すべてのタブは同等のスペースベースの幅に変換されます(つまり、各タブは、別のタブ文字に隣接していても4つのスペースに変換されます)。

それがおそらくあなたが望むものです。

注意点:左マージンに制限されなくなった(^アンカーがない)ため、他の場所にタブ文字を埋め込んだ場合、それらも変換されます。それは私の経験ではコードの通常の慣行ではありませんが、あなたにとって重要な場合には参考までに。

69
Dan Lowe

いくつかの調査の後に見つけた簡単な解決策は、「すべて置換」ツールを使用することです。

各ファイルを開いてから、検索パネル(cmdF Macで)。

Screenshot showing replacement of tabs by spaces

現在のバッファで検索(use regexオプションを有効化):

\t

現在のバッファーで置換:

    #that being just four spaces
13
J0ANMM