Как автоматически удалить завершающие пробелы в Visual Studio 2008?

122

Можно ли настроить Visual Studio 2008 на автоматическое удаление пробелов в конце каждой строки при сохранении файла? Похоже, что встроенной опции нет, есть ли для этого какие-нибудь расширения?

ChrisN
источник
1
Обратите внимание на читателей, использующих Visual Studio 2010: если вы устанавливаете расширение PowerCommands от Microsoft, вы можете автоматически отформатировать документ при сохранении файла (включите эту функцию с помощью инструментов / параметров). Это, среди прочего, удалит ненужные конечные пробелы.
Steinar

Ответы:

68

CodeMaid - очень популярное расширение Visual Studio, которое делает это автоматически вместе с другими полезными очистками.

Я настроил его на очистку файла при сохранении, что, как мне кажется, используется по умолчанию.

arserbin3
источник
1
Это лучшее решение на этой странице. Его легко настроить, оно автоматически выполняется по запросу или при сохранении, прекрасно интегрируется с VS и имеет множество других очень полезных функций. Хорошая находка arserbin3.
Chris R
В этом расширении невозможно отключить полное форматирование кода, поэтому оно несовместимо, например, с настраиваемыми стилями отступов.
aemxdp
@ Андрей Я не понимаю, о чем ты. Он следует за любым настраиваемым отступом, который вы установили в Visual Studio. Установите их в Инструменты> Параметры> Текстовый редактор> [Язык]> Вкладки
arserbin3
@ arserbin3 Я имею в виду, что если вы хотите отформатировать свой код вот так - pastebin.com/uJqBQ1u2 - вам не повезло, потому что при сохранении он автоматически переформатирует код, например pastebin.com/761Lzra7 или что-то в этом роде, в зависимости от параметры. И нет возможности полностью отключить правила отступа. А без кодовой помощницы переформатирование файла не выполняется автоматически, поэтому вы можете сохранить файл с таким отступом.
aemxdp 06
6
@ arserbin3 Я думаю, вы упускаете точку зрения Андрея. Я работаю в огромном проекте с открытым исходным кодом. Я не собственный код - я свой вклад в код. Я не могу изменить правила отступов в проекте. Я хочу, чтобы VisualStudio удалял завершающие пробелы, когда я изменяю какой-либо файл, и я не хочу, чтобы это было связано с чем-либо еще в файле (вкладки, пробелы, отступы и т. Д.). Пока что VisualStudio - единственная IDE, с которой я работал, но не может этого сделать. Любой другой недоделанный редактор (не говоря уже о IDE) может это сделать. Я не могу настроить CodeMaid на некоторое форматирование, потому что форматирование различается.
kliteyn
71

Найти / заменить с помощью регулярных выражений

В диалоговом окне «Найти и заменить» разверните « Параметры поиска» , установите флажок « Использовать» и выберите « Регулярные выражения».

Что найти : " :Zs#$"

Заменить на : ""

нажмите " Заменить все"

В других редакторах ( обычном парсере регулярных выражений) " :Zs#$" было бы " \s*$".

Грег Огл
источник
44
В VS2012 я бы использовал:[^\S\r\n]+(?=\r?$)
М. Дадли
4
Если вы используете вкладки, [:Zs\t]#$это полезная адаптация.
dlanod 05
Как привязать его к событию File On Save, чтобы оно выполнялось каждый раз, когда я сохраняю файл, пожалуйста?
Давид Ференци Рогожан,
30

Вы можете создать макрос, который будет выполняться после сохранения, чтобы сделать это за вас.

Добавьте следующее в модуль EnvironmentEvents для ваших макросов.

Private saved As Boolean = False
Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
                                         Handles DocumentEvents.DocumentSaved
    If Not saved Then
        Try
            DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                                 "\t", _
                                 vsFindOptions.vsFindOptionsRegularExpression, _
                                 "  ", _
                                 vsFindTarget.vsFindTargetCurrentDocument, , , _
                                 vsFindResultsLocation.vsFindResultsNone)

            ' Remove all the trailing whitespaces.
            DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                                 ":Zs+$", _
                                 vsFindOptions.vsFindOptionsRegularExpression, _
                                 String.Empty, _
                                 vsFindTarget.vsFindTargetCurrentDocument, , , _
                                 vsFindResultsLocation.vsFindResultsNone)

            saved = True
            document.Save()
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
        End Try
    Else
        saved = False
    End If
End Sub

Уже некоторое время пользуюсь без проблем. Я не создавал макрос, а модифицировал его из файла ace_guidelines.vsmacros, который можно найти с помощью быстрого поиска в Google.


источник
8
Обратите внимание, что это также заменяет табуляцию двумя пробелами.
crdx
Куда вы помещаете эти сценарии событий документа?
xagyg
Не лучше ли сделать это перед сохранением, чтобы не получить раздражающее приглашение VS, в котором говорится: «Эй, текст изменился с момента последнего сохранения. Вы хотите перезагрузить?»
jedmao 05
2
К сожалению, в VS 2013 больше нет макросов.
Натан Баулч
17

Перед сохранением вы можете использовать ярлык автоформатирования CTRL+ K+ D.

Vyrotek
источник
11

Вы можете легко сделать это с помощью следующих трех действий:

  • Ctrl+ A(выделить весь текст)

  • Правка -> Дополнительно -> Удалить горизонтальные пробелы

  • Правка -> Дополнительно -> Выбор формата

Подождите несколько секунд и готово.

Это Ctrl+ Zвозможно, если что-то пошло не так.

iPixel
источник
1
Для этого есть ярлык: ctrl + w, затем введите Edit.RemoveHorizontalWhitespace
Джош,
8

Взяв элементы из всех уже приведенных ответов, вот код, который у меня получился. (В основном я пишу код на C ++, но при необходимости легко проверить наличие различных расширений файлов.)

Спасибо всем, кто внес свой вклад!

Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
    Handles DocumentEvents.DocumentSaved
    Dim fileName As String
    Dim result As vsFindResult

    Try
        fileName = document.Name.ToLower()

        If fileName.EndsWith(".cs") _
        Or fileName.EndsWith(".cpp") _
        Or fileName.EndsWith(".c") _
        Or fileName.EndsWith(".h") Then
            ' Remove trailing whitespace
            result = DTE.Find.FindReplace( _
                vsFindAction.vsFindActionReplaceAll, _
                "{:b}+$", _
                vsFindOptions.vsFindOptionsRegularExpression, _
                String.Empty, _
                vsFindTarget.vsFindTargetFiles, _
                document.FullName, _
                "", _
                vsFindResultsLocation.vsFindResultsNone)

            If result = vsFindResult.vsFindResultReplaced Then
                ' Triggers DocumentEvents_DocumentSaved event again
                document.Save()
            End If
        End If
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try
End Sub
ChrisN
источник
2

Я использую VWD 2010 Express, где макросы, к сожалению, не поддерживаются. Так что я просто сделать копию / вставить в Notepad ++ в левом верхнем углу меню Edit> Blank Operations> Trim Trailing Spaceесть и другие связанные с ними операции доступны также. Затем скопируйте / вставьте обратно в Visual Studio.

Можно также использовать NetBeans вместо Notepad ++, в котором есть пункт «Удалить конечные пробелы» в меню «Источник».

Евгений
источник
Просто найдите / замените: b + $ пустой строкой, и вы можете сделать это в экспресс-версиях VS.
легализовать
1

Если это не проект одного человека, не делайте этого. Сопоставление ваших локальных файлов с репозиторием исходного кода должно быть тривиальным, а очистка пробелов изменит строки, которые вам не нужно изменять. Я полностью понимаю; Мне нравится, когда мои пробелы становятся единообразными, но от этого следует отказаться ради более чистого сотрудничества.

Кевин Коннер
источник
17
Большинство хороших инструментов сравнения игнорируют несущественные различия, такие как конечный пробел. Если инструмент не затем получить Beyond Compare из scootersoftware.com
Джим McKeeth
19
Если все в компании / проекте это делают, различия будут чистыми. Вам просто нужно будет один раз очистить все пробелы. Тогда у вас есть единственная фиксация, исправляющая только пробелы и никаких проблем с пробелами в будущем.
ThiefMaster
Это правда. Но будет ли это летать, будет зависеть от команды. Добавление одного дополнительного шага к каждой работе или даже одной дополнительной настройки для синхронизации, как правило, создает ненужное трение. Если команда может измениться, или если члены команды могут выбрать свою собственную IDE и т. Д., Я предлагаю вам просто оставить пробелы. Это не так уж важно.
Кевин Коннер,
3
Проблема с очисткой пробелов и отступов заключается в том, что она снижает эффективность таких функций системы управления версиями, как аннотирование, и эту проблему Beyond Compare не решит. Лучше сделать все правильно с первого раза.
jammycakes
4
@KevinConner Кажется, ИМО намного сложнее сохранить неправильные пробелы последовательными, чем исправить его один раз с гигантской фиксацией пробелов в начале проекта. Тогда любой, чей редактор глуп и сломан, узнает об этом, когда проверит свои различия перед фиксацией.
Дэн Бечард,
1

Я думаю, что версию Jeff Muir можно было бы немного улучшить, если бы она только обрезала файлы исходного кода (в моем случае C #, но легко добавить дополнительные расширения). Также я добавил проверку, чтобы убедиться, что окно документа видно, потому что в некоторых ситуациях без этой проверки мне показываются странные ошибки (например, файлы LINQ to SQL '* .dbml').

Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) Handles DocumentEvents.DocumentSaved
    Dim result As vsFindResult
    Try
        If (document.ActiveWindow Is Nothing) Then
            Return
        End If
        If (document.Name.ToLower().EndsWith(".cs")) Then
            document.Activate()
            result = DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, ":Zs+$", vsFindOptions.vsFindOptionsRegularExpression, String.Empty, vsFindTarget.vsFindTargetCurrentDocument, , , vsFindResultsLocation.vsFindResultsNone)
            If result = vsFindResult.vsFindResultReplaced Then
                document.Save()
            End If
        End If
    Catch ex As Exception
        MsgBox(ex.Message & Chr(13) & "Document: " & document.FullName, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try
End Sub
Дэвид Абелла
источник
0

Думаю, у меня есть версия этого макроса, которая не приведет к сбою VS2010 при рефакторинге, а также не будет зависать в среде IDE при сохранении нетекстовых файлов. Попробуй это:

Private Sub DocumentEvents_DocumentSaved( _
    ByVal document As EnvDTE.Document) _
    Handles DocumentEvents.DocumentSaved
    ' See if we're saving a text file
    Dim textDocument As EnvDTE.TextDocument = _
        TryCast(document.Object(), EnvDTE.TextDocument)

    If textDocument IsNot Nothing Then
        ' Perform search/replace on the text document directly
        ' Convert tabs to spaces
        Dim convertedTabs = textDocument.ReplacePattern("\t", "    ", _
            vsFindOptions.vsFindOptionsRegularExpression)

        ' Remove trailing whitespace from each line
        Dim removedTrailingWS = textDocument.ReplacePattern(":Zs+$", "", _
            vsFindOptions.vsFindOptionsRegularExpression)

        ' Re-save the document if either replace was successful
        ' (NOTE: Should recurse only once; the searches will fail next time)
        If convertedTabs Or removedTrailingWS Then
            document.Save()
        End If
    End If
End Sub
юлианский
источник
0

Я использую ArtisticStyle (C ++) для этого, а также переформатирую свой код. Однако мне пришлось добавить это как внешний инструмент, и вам нужно запустить его самостоятельно, чтобы он вам не понравился.

Тем не менее, я считаю превосходным то, что я могу переформатировать код более индивидуальным образом (например, параметры многострочной функции), что я могу заплатить цену за его запуск вручную. Инструмент бесплатный.

Марчин Гил
источник
0

Основываясь на ответе Дьяуса и регулярном выражении из отчета о подключении , вот макрос, который обрабатывает все сохранения, не заменяет табуляции пробелами и не требует статической переменной. Возможный недостаток? Это кажется немного медленным, возможно, из-за нескольких обращений к FindReplace.

Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
                                         Handles DocumentEvents.DocumentSaved
    Try
        ' Remove all the trailing whitespaces.
        If vsFindResult.vsFindResultReplaced = DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                             "{:b}+$", _
                             vsFindOptions.vsFindOptionsRegularExpression, _
                             String.Empty, _
                             vsFindTarget.vsFindTargetFiles, _
                             document.FullName, , _
                             vsFindResultsLocation.vsFindResultsNone) Then
            document.Save()
        End If
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try
End Sub

Для всех, кто пытается использовать это в надстройке Visual Studio 2012, я использовал регулярное выражение [ \t]+(?=\r?$)(при необходимости не забудьте избежать обратной косой черты). Я прибыл сюда после нескольких попыток безуспешных , чтобы исправить проблемы с сырым преобразованием в {:b}+$неспособности соответствовать возврату каретки.

Майкл Урман
источник
-1

Это действительно хороший пример того, как удалить завершающие пробелы. Есть несколько вещей, которые я бы изменил в зависимости от того, что я обнаружил с помощью этого макроса. Прежде всего, макрос автоматически преобразует табуляции в пробелы. Это не всегда желательно и может ухудшить положение людей, которые любят вкладки (обычно на базе Linux). В любом случае проблема табуляции не то же самое, что проблема лишних пробелов. Во-вторых, макрос предполагает, что одновременно сохраняется только один файл. Если вы сохраните несколько файлов одновременно, пробелы не удаляются правильно. Причина проста. Текущий документ считается документом, который вы можете видеть. В-третьих, он не выполняет проверку на ошибки в результатах поиска. Эти результаты могут помочь лучше понять, что делать дальше. Например, если пробелы не найдены и заменены, нет необходимости повторно сохранять файл. В целом мне не понравилась необходимость сохранения глобального флага или нет. Он имеет тенденцию просить о проблемах из-за неизвестных состояний. Я подозреваю, что флаг был добавлен исключительно для предотвращения бесконечного цикла.

    Private Sub DocumentEvents_DocumentSaved(ByVal document As EnvDTE.Document) _
                                         Handles DocumentEvents.DocumentSaved
    Dim result As vsFindResult
    'Dim nameresult As String

    Try
        document.Activate()

        ' Remove all the trailing whitespaces.
        result = DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                             ":Zs+$", _
                             vsFindOptions.vsFindOptionsRegularExpression, _
                             String.Empty, _
                             vsFindTarget.vsFindTargetCurrentDocument, , , _
                             vsFindResultsLocation.vsFindResultsNone)

        'nameresult = document.Name & " " & Str$(result)

        'MsgBox(nameresult, , "Filename and result")

        If result = vsFindResult.vsFindResultReplaced Then
            'MsgBox("Document Saved", MsgBoxStyle.OkOnly, "Saved Macro")
            document.Save()
        Else
            'MsgBox("Document Not Saved", MsgBoxStyle.OkOnly, "Saved Macro")
        End If

    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Trim White Space exception")
    End Try

End Sub

Я добавил окна сообщения отладки, чтобы увидеть, что происходит. Он очень ясно дал понять, что сохранение нескольких файлов не работает. Если вы хотите поиграть с ними, раскомментируйте эти строки.

Ключевое отличие заключается в использовании document.Activate () для принудительного размещения документа в активном текущем документе переднего плана. Если результат 4, значит, текст был заменен. Ноль означает, что ничего не произошло. Вы увидите по два сохранения для каждого файла. Первый заменит, а второй ничего не сделает. Потенциально могут возникнуть проблемы, если при сохранении не удастся записать файл, но, надеюсь, это событие не будет вызвано, если это произойдет.

До создания исходного сценария я не знал, как сценарии работают в Visual Studio. Немного удивительно, что он использует Visual Basic в качестве основного интерфейса, но он отлично работает для того, что ему нужно.

Джефф Мьюир
источник
Одно из изменений заключается в поддержке сохранения и восстановления фокуса в окне, в котором был фокус при запуске сохранения. Просто сохраните активный документ после попытки (используя currdoc = DTE.ActiveDocument) и перед document.Activate (). После завершения сохранения просто сделайте активным исходный документ (currdoc.Activate ()). Это выглядит немного забавно, когда фокус переключается во время сохранения, но это лучше, чем терять фокус из-за кода, на который вы не смотрели.
Джефф Мьюир,
-1

Простое дополнение - убрать возврат каретки во время сохранения.

' Remove all the carriage returns.
result = DTE.Find.FindReplace(vsFindAction.vsFindActionReplaceAll, _
                             "\x000d\x000a", _
                             vsFindOptions.vsFindOptionsRegularExpression, _
                             "\x000a", _
                             vsFindTarget.vsFindTargetCurrentDocument, , , _
                             vsFindResultsLocation.vsFindResultsNone)

Ключ к этой работе - изменение \ x000d \ x000a на \ x000a. Префикс \ x указывает на шаблон Юникода. Это автоматизирует процесс подготовки исходных файлов для систем Linux.

Джефф Мьюир
источник