Skip to content
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

Using an expression to generate command #156

Closed
Compro-Prasad opened this issue Feb 15, 2023 · 7 comments
Closed

Using an expression to generate command #156

Compro-Prasad opened this issue Feb 15, 2023 · 7 comments

Comments

@Compro-Prasad
Copy link

Compro-Prasad commented Feb 15, 2023

When I do

(setf (alist-get 'black apheleia-formatters) '("/path/to/venv/bin/black" "-"))

it works. But I have different projects where I don't want to run black if its not installed in the virtualenv. So, I want to use a function to get the command dynamically per file and disable it where not available:

(defun get-command ()
  (when black-was-found-in-venv
    '("/path/to/venv/bin/black" "-")))

(setf (alist-get 'black apheleia-formatters) 'get-command)

Here, get-command function will return the command based on virtualenv and nil when executable wasn't found there. What is the best way to accomplish this?

@raxod502
Copy link
Member

raxod502 commented Feb 16, 2023

I think you would use something like this:

(setf (alist-get 'black apheleia-formatters) '((get-command)))

If the value is a symbol then Apheleia assumes it is a function that defines an Elisp-based formatter. You instead want a list to use a regular command formatter. If an element of the list is not a string then it is evaluated to get a string or list of strings. In this case the sole list element is the form (get-command). This wasn't documented before; I added documentation in 1bd5f2b.

You could also put the logic in an external shell script and add that to $PATH. Then you can invoke it normally from Apheleia.

@Compro-Prasad
Copy link
Author

Compro-Prasad commented Feb 16, 2023

I get the following error when I do it:

error in process sentinel: apheleia--format-command: Command cannot start with (compro/black)
error in process sentinel: Command cannot start with (compro/black)

Code I am using:

(defun compro/black ()
  (when-let* ((root (pet-virtualenv-root))
              (executable (concat root "/bin/black"))
              (exists (file-exists-p executable)))
    executable))
(setf (alist-get 'black apheleia-formatters) '((compro/black)))

@raxod502
Copy link
Member

Odd, I don't know why that error is even in there, although I added it. Fixed in the linked commit.

@Compro-Prasad
Copy link
Author

Compro-Prasad commented Feb 16, 2023

Thanks, that worked. I am currently using:

(defun compro/black ()
  (when-let* ((root (pet-virtualenv-root))
              (executable (concat root "/bin/black"))
              (exists (file-exists-p executable)))
    `(,executable "-")))
(setf (alist-get 'black apheleia-formatters) '((compro/black)))

I am going to close this issue but I will ask for another small feature as its not fixed completely yet. I get the following error when black is not installed in the virtualenv:

error in process sentinel: Wrong type argument: stringp, nil

Instead of showing an error, either fail silently or show a message stating that black was enabled but function returned nil.

@raxod502
Copy link
Member

Hmmm. I'm not necessarily sure it would be correct to handle the function returning nil. After all, the interface here is that you have (compro/black) as one of the arguments in the command line - thus it should return a string. What about returning "cat" when there is no formatting to be done? Then it would leave the file as is.

@Compro-Prasad
Copy link
Author

Compro-Prasad commented Feb 19, 2023

What about returning "cat" when there is no formatting to be done?

Thanks! That does solve the problem.

But don't you think using cat is kind of a hack?

If this is okay then documenting it as an option would be a plus.

@raxod502
Copy link
Member

I think it's reasonable to request a way that a dynamically generated formatter command could signal that no command is to be run. One reasonable way to implement that might be to have a special symbol noop that, if present in the command string, would cause the command invocation to be skipped.

Let's track that feature, if desired, in a separate issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants