-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fsdocs init
command
#875
base: main
Are you sure you want to change the base?
fsdocs init
command
#875
Conversation
9820686
to
3b00528
Compare
Allright @nojaf @nhirschey i think this is ready for a first review. I took #875 as an opportunity to get a little familiar with the repo and how the cli tool works, so if anything is not in the correct place please correct me. currently, the new
i think the Also, i included just a simple markdown and literate script file to have something there when you run As the init command must copy-paste some of the files that are also searched in the build command, i refactored that as the Happy for any feedback |
Note that this can also be easily used to init fsdocs with a custom template by also adding a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this isn't a bad start but I wasn't able to see it in action yet.
I also wonder if we shouldn't prompt the user a bit more about some questions.
We could use Spectr for this.
I thinking about a flow like:
> We notice that you don't have a Build.Directory.props file, do you want to create one (y/n)?
y
> Who are the authors of this project?
Barry & Dave
We could adjust a lot of the often missing substitutions this way.
Of course, we then need a --yes
flag to also provide users a way to scaffold everything with all the defaults.
src/fsdocs-tool/InitCommand.fs
Outdated
member this.Execute() = | ||
|
||
let outputPath = Path.GetFullPath(this.output) | ||
let repoRoot = Path.GetFullPath(Path.Combine(outputPath, "..")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit of an assumption you are making here. If the user is running dotnet fsdocs init
in a nested subfolder, this won't be accurate.
Maybe we can run git rev-parse --show-toplevel
first and use Path.GetFullPath(Path.Combine(outputPath, ".."))
as fallback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if i didn't miss anything, the build/watch commands seem to just take user input as given. Should i adjust the init command to the same behavior?
FSharp.Formatting/src/fsdocs-tool/BuildCommand.fs
Lines 1443 to 1447 in 7707ea0
let rootOutputFolderAsGiven = | |
if this.output = "" then | |
if watch then "tmp/watch" else "output" | |
else | |
this.output |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think repoRoot
and rootOutputFolderAsGiven
are a little different.
I don't think these need to align.
src/fsdocs-tool/InitCommand.fs
Outdated
(inRepoLocations.index_md_template, Path.GetFullPath(Path.Combine(initLocations.docs, "index.md"))) | ||
(inRepoLocations.literate_sample_template, | ||
Path.GetFullPath(Path.Combine(initLocations.docs, "literate_sample.fsx"))) ] | ||
|> List.iter (fun (src, dst) -> File.Copy(src, dst, true)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm not sure if we should overwrite existing files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about a --force
flag to opt-in to overwriting files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah maybe. Do you think this would often be used? Running init
twice?
printfn "check it out by running 'dotnet fsdocs watch' !" | ||
|
||
0 | ||
with _ as exn -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with _ as exn -> | |
with exn -> |
src/fsdocs-tool/Options.fs
Outdated
/// | ||
/// Note that the path of these files will always be combined with the given `assemblyPath` because the cli tool will query it's own path on runtime via reflection. | ||
/// </summary> | ||
type InPackageLocations(relAssemblyPath) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use InNugetPackageLocations
maybe? I'm struggling to wrap my head around this.
printfn "Error: %s" exn.Message | ||
1 | ||
else | ||
printfn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/fsdocs-tool/Options.fs
Outdated
member _.RelAssemblyPath = relAssemblyPath | ||
|
||
// default folder locations relative to the assembly path | ||
member this.docs = Path.Combine(this.RelAssemblyPath, "docs") |> Path.GetFullPath |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I'm not sure how I feel about the lowercase member names.
I get why you went with them. Maybe be we should use ticks and go for something like
member this.``docs/templates`` = ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was my initial approach actually, but i find auto-suggestions in my IDE lacking for these members. A small issue though, i'll adjust this accordingly.
src/fsdocs-tool/Options.fs
Outdated
member this.docs_templates_init = Path.Combine(this.docs_templates, "init") |> Path.GetFullPath | ||
member this.docs_img = Path.Combine(this.docs, "img") |> Path.GetFullPath | ||
member this.docs_content = Path.Combine(this.docs, "content") |> Path.GetFullPath | ||
member this.docs_content_img = Path.Combine(this.docs_content, "img") |> Path.GetFullPath |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also a nit but I like a custom operator when using Path.Combine
extensively.
Something like let (</>) a b = Path.Combine(a, b)
, so we can do this.docs_content </> "img"
src/fsdocs-tool/Options.fs
Outdated
/// | ||
/// Note that the path of these files will always be combined with the given `assemblyPath` because the cli tool will query it's own path on runtime via reflection. | ||
/// </summary> | ||
type InPackageLocations(relAssemblyPath) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we even need two classes like this? They look so similar, if they only differ by the starting folder, we perhaps should extract that logic and reuse this type for both cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My exact thoughts initially, but the project does pack the files slightly different into the nuget package than the actual paths in the repo, see here for example:
FSharp.Formatting/src/fsdocs-tool/fsdocs-tool.fsproj
Lines 30 to 32 in 7707ea0
<Content Include="..\..\docs\_template.html" PackagePath="templates" /> | |
<Content Include="..\..\docs\_template.tex" PackagePath="templates" /> | |
<Content Include="..\..\docs\_template.ipynb" PackagePath="templates" /> |
a "templates" folder does not exist in the repo, but will contain the template files in the nuget package. I guess the reason here is that in the repo, we need an intact docs
folder. It just felt wrong putting this on the same class when it could contain paths that do not exist.
src/fsdocs-tool/InitCommand.fs
Outdated
ensureOutputDirs () | ||
|
||
try | ||
[ (inPackageLocations.template_html, initLocations.template_html) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm very opposed that we copy the _template.html
file by default.
This should only be done when users are interested in creating their custom theme.
Which, in a sense we want to avoid. 90% of our user base should be able to use or customize the modern theme instead of writing one from scratch.
So, I would not include _template.html
by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I think i do not really get the difference - when the user does not put a _template.html
file into their docs folder, isn't the file i am copying here the exact one that will be used by the tool per default anyways?
My rationale would be that you will need a template file once you want to make even slight changes to the layout, but want to keep most of the default file. Where would i get that file other than looking up the file in the FSharp.Formatting repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, this could be circumvented by putting a good descriptive interactive text on the setup, so users that will need to make adjustments just opt-in to copy the template file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh i think i get the issue. If we update the file for a new version of the tool, the repos that use the copied template file will have an outdated version. So i agree this should be opt-in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, indeed. If the user doesn't have a _template.html
, the one from NuGet is used.
Which will stay updated if they bump the version.
printfn "check it out by running 'dotnet fsdocs watch' !" | ||
|
||
0 | ||
with _ as exn -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with _ as exn -> | |
with exn -> |
Allright a quick summary of how i would proceed:
sounds good @nojaf ? |
I would like it more if there would be a way to unify |
Yup! |
and comment init command code a little
- more descriptive class names - member names now reflect paths exactly - add badge svg file paths - add location descriptions
2f9de2c
to
e28ee79
Compare
Hey @nojaf, where should I put tests that check whether the location classes construct correct paths? None of the test projects seem to match the scope of testing 'Common' functions used across commands in the tool. |
Hmm, this does seem like a rather new area when it comes to the existing test projects. |
This is what i feared, because all the existing test projects look really arcane to me - i usually just use expecto, here it seems to be FsUnit + NUnit - i can roll with that, but every test i looked at also makes heavy use of compiler directives and i have absolutely no clue on what to use from that.
A really simple case would be verifying that all default paths created from a base directory are correct |
Well, the whole solution is rather arcane, isn't it? You could also consider using https://github.com/TestableIO/System.IO.Abstractions in your implementation. That could make writing such tests easier. |
oh wow, that will come in handy in other projects as well, thanks! I'll copy stuff together until i have working tests i guess ;) |
This PR intends to implement a basic version of #872
additionally, i tried to refactor the way default files and folders are accessed from the build command, because the init command needs essentially the same code to copy the relevant files.