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





5.00/5 (4投票s)
在某些情况下,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 日:初始版本