clang-format配置与使用

clang-format配置与使用

参考教程.

1. 安装

下载clang-format,设置环境变量。我使用的是vscode扩展中的clang-format

位于: extensions/ms-vscode.cpptools-1.7.0-insiders/bin/

将程序放置到系统边境变量的路径中,或者将软件路径添加到系统环境变量。

2. 配置

--style=指定配置文件。不指定将使用默认配置。默认情况下会先从当前目录寻找 .clang-format配置文件。这个配置有点弱智,难道就不能指定路径吗?

因此,自己定义的配置只能通过将.clang-format放置到需要格式化文件的路径下。因此,通过脚本或者程序的方式来复制配置文件到工作目录中。并在格式化完成后将其移除,这样可以不在工作目录下引入新的文件。

使用 Go来完成这个任务。(成功掌握可变参数和信道的使用-.-)

package main

import (
	"fmt"
	log "fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
)

func main() {

	clang_format_process(os.Args...)
}

func clang_format_process(args ...string) {
	conf_dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	work_dir, _ := os.Getwd()

	if conf_dir == work_dir {
		if os := runtime.GOOS; os == "linux" {
			conf_dir = filepath.Clean("/usr/local/sbin/clang_format_config.d")
		} else if os == "windows" {
			conf_dir = filepath.Clean("D:\\Program Files\\app")
		}
	}

	work_dir_config := filepath.Join(work_dir, ".clang-format")
	var config string = "config/.clang-format"
	conf_dir_config := filepath.Join(conf_dir, filepath.Clean(config)) /* 使用clean生成与平台无关的路径 */

	/* 根据不同的平台选择不同的格式化工具 */
	var tool_dir string
	switch os := runtime.GOOS; os {
	case "windows":
		tool_dir = filepath.Join(conf_dir, "bin/clang-format.exe")
	case "linux":
		tool_dir = filepath.Join(conf_dir, "bin/clang-format")
	}

	if _, err := os.Stat(tool_dir); err != nil {
		log.Println("Error: no such file: ", tool_dir)
		return
	}

	// is_custom := flag.Bool("nc", false, "custom argurement lists")
	// flag.Parse()
	if len(os.Args) <= 1 {
		log.Println("Usage: \nclang_format_custom file.c file1.c\nor clang_format_custom -nc (= clang-format[.exe] )")
		return
	}

	// 使用-cu参数,请删除true和修改os.Args[2:]
	if os.Args[1] != "-nc" {
		arg_pos := 1
		print_args(os.Args[1:]...)

		if _, err := os.Stat(work_dir_config); err == nil {
			log.Println(work_dir_config)
			log.Println(".clang-format has existed.")
			return
		}

		/* 复制配置文件当工作目录中 */
		if _, err := copy(conf_dir_config, work_dir_config); err != nil {
			log.Println(err)
		}

		ch := make(chan int)
		for _, arg := range os.Args[arg_pos:] {
			go clang_format_exec(ch, tool_dir, work_dir, arg)
		}

		// 阻塞在此,等待所有goroutine完成
		for i := arg_pos; i < len(os.Args); i++ {
			<-ch
		}
		os.Remove(work_dir_config)
		return
	} else {
		cmd := exec.Command(tool_dir, os.Args[2:]...) /* 不使用自定义参数时,直接调用clang-format */
		output, err := cmd.CombinedOutput()
		if err != nil {
			log.Println(err)
		}
		fmt.Print(string(output))
		return
	}
}

func print_args(args ...string) {
	log.Println("----------args list--------------")
	for _, arg := range args {
		log.Println(arg)
	}
	log.Println("-------------end-----------------")
}

func clang_format_exec(ch chan int, tool_dir, work_dir, file string) {
	log.Println("format ", file)
	cmd := exec.Command(tool_dir, "-i", file)
	err := cmd.Run()
	if err != nil {
		log.Println(err)
	}
	ch <- 1
}

func copy(src, dst string) (int64, error) {
	sourceFileStat, err := os.Stat(src)
	if err != nil {
		return 0, err
	}
	if !sourceFileStat.Mode().IsRegular() {
		return 0, fmt.Errorf("%s is not a regular file", src)
	}

	source, err := os.Open(src)
	if err != nil {
		return 0, err
	}
	defer source.Close()

	destination, err := os.Create(dst)
	if err != nil {
		return 0, err
	}
	defer destination.Close()

	nBytes, err := io.Copy(destination, source)
	return nBytes, err
}

程序目录结构:

.
├── bin
│   ├── clang-format
│   └── clang-format.exe
├── clang_format_custom
├── clang_format_custom.exe
├── config
    ├── .clang-format
    └── .clang-format_backup

执行结果:

好了,宏定义对齐终于酸爽了。根据自己的喜好配置.clang-format配置文件。我的配置如下:

---
Language:        Cpp
# BasedOnStyle:  LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: true
AlignConsecutiveBitFields: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Right
AlignOperands:   Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
  AfterCaseLabel:  false
  AfterClass:      false
  AfterControlStatement: Never
  AfterEnum:       false
  AfterFunction:   false
  AfterNamespace:  false
  AfterObjCDeclaration: false
  AfterStruct:     false
  AfterUnion:      false
  AfterExternBlock: false
  BeforeCatch:     false
  BeforeElse:      false
  BeforeLambdaBody: false
  BeforeWhile:     false
  IndentBraces:    false
  SplitEmptyFunction: true
  SplitEmptyRecord: true
  SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit:     120
CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat:   false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
IncludeBlocks:   Preserve
IncludeCategories:
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
    Priority:        2
    SortPriority:    0
  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
    Priority:        3
    SortPriority:    0
  - Regex:           '.*'
    Priority:        1
    SortPriority:    0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentWidth:     4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments:  true
SortIncludes:    true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles:  false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard:        Latest
StatementMacros:
  - Q_UNUSED
  - QT_REQUIRE_VERSION
TabWidth:        4
UseCRLF:         false
UseTab:          Never
WhitespaceSensitiveMacros:
  - STRINGIZE
  - PP_STRINGIZE
  - BOOST_PP_STRINGIZE
...


posted @ 2021-09-30 15:08  duapple  阅读(471)  评论(0编辑  收藏  举报  来源