65.9K
CodeProject 正在变化。 阅读更多。
Home

一个用于缩进源代码的 awk 程序

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2021 年 7 月 13 日

CPOL

1分钟阅读

viewsIcon

11621

在某些情况下,Visual Studio 无法按预期缩进,因此这里提供一个 awk 程序来解决这个问题。

引言

如果前一行不以分号结尾,Visual Studio 在 C++ 文件中的自动缩进就无法按我的意愿工作。这会导致难以忍受的缩进代码,如下所示。这里的 awk 程序可以轻松解决这个问题,并且可以通过通过 工具->外部工具调用的批处理文件来自动执行当前文档的处理。下面展示了相同文件的后处理。当然,您可以修改代码以使用您喜欢的缩进字符串,并将块的开始/结束字符设置为您的语言要求的字符。请务必在保存的文件上调用此程序,否则系统会提示您选择是否重新加载它,即处理后的文件,并丢失您之前编辑的任何更改。请注意,代码已于 2021 年 7 月 21 日更新以修复一个错误。请注意,代码已于 2021 年 8 月 3 日更新,以可选地缩进包围大括号级别的类成员访问说明符。此外,代码还得到了增强,可以可选地搜索未匹配的大括号和圆括号。

BEGIN {
    # to indent the member access specifiers at the same level as the enclosing brace set below to 1
    # to indent the member access specifiers at the same level as the enclosed code set below to 0
    MEMBER_ACCESS_ENCLOSING_BRACE_LEVEL = 1
    # to search for unmatched braces or parentheses set below to 1 else 0
    # when searching the current brace depth and current parentheses depth will be displayed following each line of code
    SEARCH_UNMATCHED = 0

    INDENT_STRING = "\t"
    INCREASE_INDENT_CHARACTER = "{"; DECREASE_INDENT_CHARACTER = "}"
    MEMBER_ACCESS_STRINGS[0] = "private:"; MEMBER_ACCESS_STRINGS[1] = "PRIVATE:"; MEMBER_ACCESS_STRINGS[2] = "public:"; MEMBER_ACCESS_STRINGS[3] = "PUBLIC:"; MEMBER_ACCESS_STRINGS[4] = "protected:"; MEMBER_ACCESS_STRINGS[5] = "PROTECTED:";
    PRIVATE_LENGTH = 8 # length of "private:"
    PUBLIC_LENGTH = 7 # length of "public:"
    PROTECTED_LENGTH = 10 # length of "protected:"

    OPEN_PAREN = "("; CLOSE_PAREN = ")";
    INDENT_DEPTH = 0
    PAREN_DEPTH = 0
    NEED_NEWLINE = 0
}

END {
    # to only obtain a final value of unmatched braces and parentheses the line below can be uncommented and the above value "SEARCH_UNMATCHED" set to 0
    # if(SEARCH_UNMATCHED != 0) printf("\nFINAL: INDENT_DEPTH %d PAREN_DEPTH %d", INDENT_DEPTH, PAREN_DEPTH)
}

{OPEN = NUMBER_OF_OPEN(); INDENT_DEPTH += OPEN}
{CLOSE = NUMBER_OF_CLOSE(); INDENT_DEPTH -= CLOSE}
{PAREN_DEPTH += NUMBER_OF(OPEN_PAREN)}
{PAREN_DEPTH -= NUMBER_OF(CLOSE_PAREN)}
{INDENT()}
{if(SEARCH_UNMATCHED) {if (NEED_NEWLINE != 0) printf("\n"); printf("INDENT DEPTH %d PAREN DEPTH %d ", INDENT_DEPTH, PAREN_DEPTH); NEED_NEWLINE = 1} }

function NUMBER_OF_OPEN() { return NUMBER_OF(INCREASE_INDENT_CHARACTER) }
function NUMBER_OF_CLOSE() { return NUMBER_OF(DECREASE_INDENT_CHARACTER) }
function NUMBER_OF(_SUB_STRING)
{
    N = 0
        INDEX = 0
        STRING = $0
        while ((INDEX = index(STRING, _SUB_STRING)) > 0)
        {
            ++N
                if (INDEX < length(STRING))
                    STRING = substr(STRING, INDEX + 1)
                else
                    break
        }
    return N
}
function INDENT()
{
    if (NEED_NEWLINE != 0) printf("\n")
        if (length($0) == 0) { printf("\n"); NEED_NEWLINE = 0 }
        else
        {
            # find first non - blank character
                if (match($0, "[^[:blank:]]"))
                {
                    # RSTART is where the match of the pattern starts
                        # RLENGTH is the length of the matched pattern
                        # before = substr($0, 1, RSTART - 1)
                            # after = substr($0, RSTART + RLENGTH)
                        matched_pattern = substr($0, RSTART)
                        if (MEMBER_ACCESS_ENCLOSING_BRACE_LEVEL != 0 && MEMBER_ACCESS_CONTROL(matched_pattern) != 0)
                        {
                            for (i = 1; i < INDENT_DEPTH; ++i) printf("%s", INDENT_STRING)
                                printf("%s", matched_pattern)
                                NEED_NEWLINE = 1
                        }
                        else
                        {
                                i = 0;
                            if (OPEN > CLOSE) i = 1
                                for (; i < INDENT_DEPTH; ++i) printf("%s", INDENT_STRING)
                                    printf("%s", matched_pattern)
                                    NEED_NEWLINE = 1
                        }
                }
        }
}
function MEMBER_ACCESS_CONTROL(_STRING)
{
        for (i = 0; i < 2; ++i)
                if (substr(_STRING, 0, PRIVATE_LENGTH) == MEMBER_ACCESS_STRINGS[i]) return 1
        for (i = 2; i < 4; ++i)
                if (substr(_STRING, 0, PUBLIC_LENGTH) == MEMBER_ACCESS_STRINGS[i]) return 1
        for (i = 4; i < 6; ++i)
                if (substr(_STRING, 0, PROTECTED_LENGTH) == MEMBER_ACCESS_STRINGS[i]) return 1
    return 0
}

在使用从 Bruce Barnett 先生那里大量复制的上述 awk 程序进行处理之前:手动为五百行文件进行更正是无法忍受的。

       }
       template<typename scalarType> requires CONCEPT_scalar<scalarType>
           this_type& write(file_offset_type offset, 
           const unique_ptr<scalarType[]>&buffer, size_t count)
           {
               HANDLE_NO_HANDLE
                   seekp(offset);
               return write(buffer, count);
           }
           template<typename scalarType> requires CONCEPT_scalar<scalarType>
               this_type& write(file_offset_type offset, 
               const csmart_unique_ptr<scalarType[]>&buffer, size_t count)
               {
                   HANDLE_NO_HANDLE
                       seekp(offset);
                   return write(buffer, count);
               }
               template<typename scalarType> requires CONCEPT_scalar<scalarType>
                   this_type& write(file_offset_type offset, 
                   const csmart_unique_ptr<scalarType[]>&buffer)
                   {
                       HANDLE_NO_HANDLE
                           seekp(offset);
                       return write(buffer);
                   }
                   this_type& write(const void* buffer, size_t nbytes)
                   {
                       HANDLE_NO_HANDLE
                           if (nbytes == 0) return *this;
                       DEBUG_ASSERT(buffer != nullptr, nullptr_msg, ARGUMENT_VA_ARG(nbytes));
                       DWORD nbytes_written = 0;
                       osapi::WriteFile(m_handle, buffer, nbytes, &nbytes_written, NULL);
                       return *this;

使用上述 awk 程序处理后的相同行:瞧!只需通过 工具点击两次即可。

        }
        template<typename scalarType> requires CONCEPT_scalar<scalarType>
        this_type& write(file_offset_type offset, 
                         const unique_ptr<scalarType[]>&buffer, size_t count)
        {
            HANDLE_NO_HANDLE
            seekp(offset);
            return write(buffer, count);
        }
        template<typename scalarType> requires CONCEPT_scalar<scalarType>
        this_type& write(file_offset_type offset, 
        const csmart_unique_ptr<scalarType[]>&buffer, size_t count)
        {
            HANDLE_NO_HANDLE
            seekp(offset);
            return write(buffer, count);
        }
        template<typename scalarType> requires CONCEPT_scalar<scalarType>
        this_type& write(file_offset_type offset, 
        const csmart_unique_ptr<scalarType[]>&buffer)
        {
            HANDLE_NO_HANDLE
            seekp(offset);
            return write(buffer);
        }
        this_type& write(const void* buffer, size_t nbytes)
        {
            HANDLE_NO_HANDLE
            if (nbytes == 0) return *this;
            DEBUG_ASSERT(buffer != nullptr, nullptr_msg, ARGUMENT_VA_ARG(nbytes));
            DWORD nbytes_written = 0;
            osapi::WriteFile(m_handle, buffer, nbytes, &nbytes_written, NULL);
            return *this;
        }
        this_type& write(const_byte_ptr_type buffer, size_t nbytes)
        {
            HANDLE_NO_HANDLE
            if (nbytes == 0) return *this;

历史

  • 2021 年 7 月 13 日:初始版本
© . All rights reserved.