Skip to content

Commit 88cb353

Browse files
committed
Add option to specify custom location of .scalafmt.conf for fmt command.
1 parent 6f08f00 commit 88cb353

File tree

7 files changed

+59
-16
lines changed

7 files changed

+59
-16
lines changed

modules/cli-options/src/main/scala/scala/cli/commands/FmtOptions.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ final case class FmtOptions(
4646
scalafmtArg: List[String] = Nil,
4747

4848
@Group("Format")
49+
@HelpMessage("Custom path to the scalafmt configuration file.")
50+
@Name("scalafmtConfig")
51+
scalafmtConf: Option[String] = None,
52+
@Group("Format")
4953
@HelpMessage("Pass a global dialect for scalafmt. This overrides whatever value is configured in the .scalafmt.conf file.")
5054
@Name("dialect")
5155
scalafmtDialect: Option[String] = None,

modules/cli/src/main/scala/scala/cli/commands/Fmt.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ object Fmt extends ScalaCommand[FmtOptions] {
3737
(s, i.workspace, Some(i))
3838
}
3939
CurrentParams.workspaceOpt = Some(workspace)
40-
val (versionMaybe, dialectMaybe, pathMaybe) = readVersionAndDialectFromFile(workspace, logger)
41-
val cache = options.shared.buildOptions().archiveCache
42-
val buildOptions = options.buildOptions
40+
val (versionMaybe, dialectMaybe, pathMaybe) =
41+
readVersionAndDialectFromFile(workspace, options.scalafmtConf, logger)
42+
val cache = options.shared.buildOptions().archiveCache
43+
val buildOptions = options.buildOptions
4344

4445
if (sourceFiles.isEmpty)
4546
logger.debug("No source files, not formatting anything")

modules/cli/src/main/scala/scala/cli/commands/util/FmtUtil.scala

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ object FmtUtil {
3535
*/
3636
def readVersionAndDialectFromFile(
3737
workspace: os.Path,
38+
customConfPath: Option[String],
3839
logger: Logger
3940
): (Option[String], Option[String], Option[os.Path]) = {
4041
case class RunnerMetaconfig(dialect: String = "")
@@ -58,17 +59,25 @@ object FmtUtil {
5859
}
5960

6061
val confName = ".scalafmt.conf"
61-
val pathMaybe = {
62-
logger.debug(s"Checking for $confName in cwd.")
63-
val confInCwd = workspace / confName
64-
if (os.exists(confInCwd)) Some(confInCwd)
65-
else {
66-
logger.debug(s"Checking for $confName in git root.")
67-
val gitRootMaybe = getGitRoot(workspace, logger)
68-
val confInGitRootMaybe = gitRootMaybe.map(os.Path(_) / confName)
69-
confInGitRootMaybe.find(os.exists(_))
62+
val pathMaybe =
63+
customConfPath.flatMap { p =>
64+
val confPath = os.Path(p, os.pwd)
65+
logger.debug(s"Checking for $confPath.")
66+
if (os.exists(confPath)) Some(confPath)
67+
else
68+
logger.message(s"WARNING: provided file doesn't exist $confPath")
69+
None
70+
}.orElse {
71+
logger.debug(s"Checking for $confName in cwd.")
72+
val confInCwd = workspace / confName
73+
if (os.exists(confInCwd)) Some(confInCwd)
74+
else {
75+
logger.debug(s"Checking for $confName in git root.")
76+
val gitRootMaybe = getGitRoot(workspace, logger)
77+
val confInGitRootMaybe = gitRootMaybe.map(os.Path(_) / confName)
78+
confInGitRootMaybe.find(os.exists(_))
79+
}
7080
}
71-
}
7281

7382
val confContentMaybe = pathMaybe.flatMap { path =>
7483
val either = metaconfig.Hocon.parseInput[ScalafmtMetaconfig](

modules/cli/src/test/scala/cli/tests/ScalafmtTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ class ScalafmtTests extends munit.FunSuite {
1616
os.write(confFilePath, confFile)
1717

1818
val readVersionAndDialect =
19-
FmtUtil.readVersionAndDialectFromFile(workspace = dirPath, TestLogger())
19+
FmtUtil.readVersionAndDialectFromFile(workspace = dirPath, None, TestLogger())
2020
expect(readVersionAndDialect == (Some("3.1.2"), Some("scala213"), Some(confFilePath)))
2121
}
2222
}
2323

2424
test("readVersionFromFile with missing .scalafmt.conf file") {
2525
TestInputs.withTmpDir("temp-dir") { dirPath =>
2626
val readVersionAndDialect =
27-
FmtUtil.readVersionAndDialectFromFile(workspace = dirPath, TestLogger())
27+
FmtUtil.readVersionAndDialectFromFile(workspace = dirPath, None, TestLogger())
2828
expect(readVersionAndDialect == (None, None, None))
2929
}
3030
}

modules/integration/src/test/scala/scala/cli/integration/FmtTests.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ class FmtTests extends ScalaCliSuite {
5454
os.rel / "Foo.scala" -> simpleInputsUnformattedContent
5555
)
5656

57+
val simpleInputsWithCustomConfLocation: TestInputs = TestInputs(
58+
Seq(
59+
os.rel / "custom.conf" ->
60+
s"""|version = "3.5.5"
61+
|runner.dialect = scala213
62+
|""".stripMargin,
63+
os.rel / "Foo.scala" -> simpleInputsUnformattedContent
64+
)
65+
)
66+
5767
private def noCrLf(input: String): String =
5868
input.replaceAll("\r\n", "\n")
5969

@@ -139,6 +149,19 @@ class FmtTests extends ScalaCliSuite {
139149
}
140150
}
141151

152+
test("--scalafmt-conf") {
153+
simpleInputsWithCustomConfLocation.fromRoot { root =>
154+
os.proc(TestUtil.cli, "fmt", ".", "--scalafmt-conf", "custom.conf").call(cwd = root)
155+
val confLines = os.read.lines(root / Constants.workspaceDirName / confFileName)
156+
val versionInConf = confLines(0).stripPrefix("version = ").trim
157+
val dialectInConf = confLines(1).stripPrefix("runner.dialect = ").trim
158+
val updatedContent = noCrLf(os.read(root / "Foo.scala"))
159+
expect(versionInConf == "\"3.5.5\"")
160+
expect(dialectInConf == "scala213")
161+
expect(updatedContent == expectedSimpleInputsFormattedContent)
162+
}
163+
}
164+
142165
test("creating workspace conf file") {
143166
simpleInputsWithDialectOnly.fromRoot { root =>
144167
val workspaceConfPath = root / Constants.workspaceDirName / confFileName

website/docs/commands/fmt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ scala-cli fmt . --check --respect-project-filters=false
153153

154154
The Scala CLI `fmt` command runs `scalafmt` under the hood, which *normally* requires `.scalafmt.conf` configuration file with explicitly specified **version** and **dialect** fields. The way it is handled by Scala CLI is as follows:
155155

156-
At the beginning `fmt` looks for existing `.scalafmt.conf` file inside **current workspace** directory and if it doesn't find it - inside **git root** directory. There are 3 possible cases:
156+
At the beginning `fmt` looks for the configuration inside the file specified in the `--scalafmt-conf` option. If the option is not passed or the file doesn't exist, `fmt` looks for the existing configuration file inside **current workspace** directory. If the file is still not found, `fmt` looks for it inside **git root** directory. There are 3 possible cases:
157157

158158
1. Configuration file with the specified version and dialect is found.
159159
2. Configuration file is found, but it doesn't have specified version or dialect.

website/docs/reference/cli-options.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,12 @@ Show help for scalafmt. This is an alias for --scalafmt-arg -help
522522

523523
Aliases: `-F`
524524

525+
#### `--scalafmt-conf`
526+
527+
Aliases: `--scalafmt-config`
528+
529+
Custom path to the scalafmt configuration file.
530+
525531
#### `--scalafmt-dialect`
526532

527533
Aliases: `--dialect`

0 commit comments

Comments
 (0)