Comment by ~emlabee on ~technomancy/fennel
Thanks for getting back to me so quickly! I think I understand your reasoning here.
it's unreasonable for other formatting tools to be able to consistently agree with fnlfmt, which severely diminishes the utility of fnlfmt.
Could you expand on this? I'm not sure what formatting tools you would use with
fnlfmt
when it's considered canonical and I want to understand these use-cases better.(LSP does include a command to format an entire file, but this is not sufficient as it erases authorship data for lines that would not otherwise be edited.)
As in Git history, right? Yeah, that's a drag; I wonder if there are tools out there that specifically work with VCS in this way, albeit whether or not someone considers formatting as authorship is a whole other bikeshed. 😅
To demonstrate where I'm coming from, I started by comparing
fnlfmt
with other language formatters likegofmt
andprettier
as a means of applying a consistent formatting standard and that makes conceptual sense to me, assuming these are reasonable comparisons. (I like prettier's take on this in that by using the library, you're opting into a specific aesthetic.)When I do compare these, the only significant and meaningful difference I see between Fennel and Go / JavaScript are macros, which are inherently non-standard outside of Fennel's standard library. (Strings vs. keywords is the only other difference I could think of where context matters, but it's not relevant and is easily mitigated with
;;fnlfmt: skip
.)Given the code-generating nature of macros, I'm wondering if it's okay for a codebase to opt-in to losing the guarantees that a standard format gives you, in exchange for the ability to utilize macros on their own terms. I think this is possible without the slippery slope of allowing configuration to become too personalized, and I'd be curious to see if configuration could actually empower tooling as well. For example, tooling built on top of
fnlfmt
could benefit from access to explicit config over implicit config, e.g. a tool today needs to know aboutfnlfmt
macro heuristicswith-
anddef
, but in the future can read the same ruleset, especially iffnlfmt
provides the function to access the configuration.
If it's helpful to know, I use a neovim plugin called
conform
which runsfnlfmt
on save, and these are the workarounds I have enabled currently, as well as some I have tried before and / or thought about:#1. Customize and recompile
fnlfmt
with my macros in place, and install that globally / per-projectNot ideal, but it works well. This is what I use right now.
#2. Intercept the format function in
conform
and look for naming convention that tells me not to runfnlfmt
In this case with my test spec library, I named the files
file.spec.test
and looked for.spec.test
as an extension. This worked, but not havingfnlfmt
at all was a bummer.#3. Use
;;fnlfmt: skip
on each line.I don't think this is sustainable with nested macros. This could me mitigated by having
fnlfmt
skip all children expressions, but then you lose out on runningfnlfmt
where applicable.#4. Create another tool that runs
fnlfmt
first, then its own custom formatting.I'm wondering if this is what you meant by additional tooling, but this could be a wrapper library that calls
fnlfmt
, then corrects any mistakes fromfnlfmt
. It doesn't benefit from changes infnlfmt
and is more likely to duplicate effort, but this could be mitigated throughfnlfmt
exporting more inner functionality if necessary. This is a bit more verbose than I'd like (and requires me to also implement #2), but it could be an acceptable tradeoff.All that said, I'd love to hear more so I can understand your position and
fnlfmt
values better. At the moment, native configuration for macros infnlfmt
feels like the option with the least negative tradeoffs that the user can specifically opt into, and I also know you and other Fennel folks have far more context than I do about this. 🙂
Ticket created by ~emlabee on ~technomancy/fennel
Hey there!
Using
fnlfmt
, I'd like to be able to specify configurable global body forms. I've got some macros where prefixing withwith-
anddef
doesn't make much sense. In order of preference:
- A
~/.fnlfmtrc
file that looks for the first valid option from the current working directory, using package loaders, etc.- A comment at the top of the file:
;fnlfmt {:extra-body-forms [:if-let :with-logging :partial-right]}
I know
fnlfmt
was designed to not require configuration, but unlessfnlfmt
can dynamically determine macros, having configuration for body forms would allow for formatting more expressive DSLs and remove the need to extrapolatedef
andwith-
, particularly in cases where that's not desired.I can open a PR, but I wanted to get thoughts first. 🙂
Comment by ~emlabee on ~xerool/fennel-ls
Thanks a lot for taking the time! I appreciate you.
I merged your change, then went back through and removed all of the accidental
fnlfmt
changes and renamed some stuff, so I think this is good to go as a starting point!For posterity, I added the git clone util because I saw it used elsewhere, but I didn't refactor any of those spots so this change could be smaller; happy to change that if I need to though.
My email provider doesn't have SMTP access so I'm not quite sure how to do
git send-mail
just yet, so I just pushed it up here:https://git.sr.ht/~emlabee/fennel-ls/tree
I'll try and figure out how to submit a PATCH. If it's helpful to pull anything from that repo directly, then I'm also happy to rebase the history and either squash into one commit, or into smaller logical ones. Let me know if either of you have any feedback or need anything else from me here!
Comment by ~emlabee on ~xerool/fennel-ls
Thanks for getting back to me!
Now that you mention it, the CLI flag is definitely overkill, haha. My hope was to enable folks who download fennel-ls through a package manager a way to run a stateful command that generates the documentation on the fly in a straight-forward way rather than needing to manually build.
So I agree with you on the env approach; it's easier, and you should only have to build the Love documentation each Love update. I'd probably do that by running the script manually outside the package anyway to start. If we wanted to expose that functionality in a more automated / user-friendly way, then it makes sense to think of the abstraction more holistically, e.g. a plugin architecture, rather than how do we get around a license, haha.
I'll wrap this up with this assumption in mind since a patch gives us something concrete, but I'll change whatever should we need a different approach!
Comment by ~emlabee on ~xerool/fennel-ls
Personally I think the best way would be for fennel-ls to be able to be pointed to a checkout of love-api and generate a docset from that
Perfect! Incidentally, that's pretty close to what I did. :)
If we do the latter, perhaps there could be a directory where docsets can be loaded from which could also be used to store docsets from other 3rd-party APIs.
This makes sense to me. A
~/.config/fennel-ls/docsets
path or something?Does that make sense?
It does. Right now, this is what I have written:
- When
tools/get-docs.fnl
runs, clone thelove-api
repo intobuild/
love-api
docs are parsed intosrc/fennel-ls/docs/generated/love2d.fnl
love2d
can be passed as a library in the config and this doc will be added.If I understood you correctly, these are rough next steps:
- Remove this clone step, refactor
tools/get-docs/love2d.fnl
to take the repo directory as an argument, so it can be run manually.- Submit this as a PATCH, with
love2d
only supported if you compilefennel-ls
yourself.(Optional, with a lot of hand-wavy naming and architecture thoughts haha)
- Add a config option for
:docsets-path
, default to~/.config/fennel-ls/docsets
(or whatever)- Add a
--parse-docset
flag to the CLI that takes a repository path, then a parser pattern matches touser/repo-name
(or two separate arguments,path
andparser
), and exports the parsed docset to the configured docset path.- Submit as a PATCH.
Is this in the ballpark for what you were thinking?
EDIT: Also, I forgot to mention that architecture wise, I ignored all of the variations and only picked the first one. You miss out on some of the consolidated function calls, but that's good enough to start I think.
Comment by ~emlabee on ~xerool/fennel-ls
Yeaaaah, lol. I only figured that out once I already did the work here to pull down
love2d-community/love-api
and parse it for fennel-ls. Technically that repository doesn't have a license, but given that GFDL requires the derivative works are licensed using the same one, we have to assume that it carries the same license, right? I wonder if slime would ever change the Wiki license, but for now, is this the best way forward?
- Make a new repo, e.g.
fennel-ls-love-2d
- Pull all of my work into that repo
- Link to it in
fennel-ls
if folks are interestedI'm cool to abandon the work too, but I'm close enough that I thought I'd try. :D
Ticket created by ~emlabee on ~xerool/fennel-ls
Hey there! 👋
I'm working on a patch to add support for LÖVE as a generated doc-set. I wanted to validate my approach, because I'm at a point where the cost to back out gets a bit high if I make the wrong architectural choice. Let me know if this isn't a patch that would be helpful and we can close the issue.
Otherwise, my approach —
- I'm using love2d-community/love-api to grab a table of the documentation, since this seems to commonly used across other editors.
- I'm cloning it down into
build/love-api
as a repo rather than curling each raw file.- I'm building out of a
tools/get-docs/love2d.fnl
file that is called intools/get-docs.fnl
If the above isn't contentious, this is where I'm getting into trouble:
- LÖVE functions support variants, such that there can be multiple arg lists. (Example — love.graphics.polygon)
{:metadata {:fnl/arg-list []}}
only takes a single arg list.I see two approaches:
- Change
metadata-format
insrc/fennel-ls/formatter.fnl
to accept metadata either as an array of variations, or as a single map.- Change
metadata-format
insrc/fennel-ls/formatter.fnl
to take afnl/fn-variations
-ish key, an array of metadata objects that is appended to the high-levelfnl/arguments
andfnl/docstring
as subsequent variations.- Change
metadata-format
insrc/fennel-ls/formatter.fnl
to take afnl/fn-variations
-ish key, a list of variations that includes all variations. Any other key is ignored.- Do custom formatting in the documentation builder for each variant within a single
fnl/docstring
.No. 4 feels the safest but least formatted, but No. 1 - No. 3 feel useful in more contexts than LÖVE, and benefits from first-class formatting as a code-block where appropriate. Personally I have a slight preference for No. 1 or No. 2, but I wanted to check in to see what is preferred. 🙂