rejeep / prodigy.el

Manage external services from within Emacs
GNU General Public License v3.0
550 stars 39 forks source link

Set via customization #1

Open purcell opened 10 years ago

purcell commented 10 years ago

Hey, this might be possible already, but I wanted to say that this is a prime example of something that I would primarily want to configure using custom vars. I don't check anything personal into my config, but service definitions are very project-specific, and if I could add them to my custom variables that would be better than adding code to define them.

-Steve

rejeep commented 10 years ago

I don't check in custom code either. See https://github.com/rejeep/emacs/blob/master/init.el#L381-L385. I never use custom vars. Could you explain how that would work?

purcell commented 10 years ago

It's similar to some advice I gave lunaryorn about flycheck: prefer data structures over functions where practical. So if instead of

(prodigy-define-service
  :name "Python app"
  :command "python"
  :cwd "/path/to/my/project"
  :args '("-m" "SimpleHTTPServer" "6001")
  :tags '(work))

you have a prodigy-services variable

(setq prodigy-services
    '((:name "Python app"
        :command "python"
        :cwd "/path/to/my/project"
        :args '("-m" "SimpleHTTPServer" "6001")
        :tags '(work))
      ...
     ))

then the package can be configured using data alone, and thus also via the custom interface.

helm, company, auto-complete and others have followed this rule of thumb with great success.

(Re. local non-checked-in config, I do have support for it, but I just prefer not to use it.)

rejeep commented 10 years ago

I already have a prodigy-services variable for internal use. This means I have to work with the data structure specified or duplicate the data, which sucks. I think a big win of functions is that they better document the API and can validate it.

purcell commented 10 years ago

You can still validate the data, just not at the time it's defined. Obviously it's your choice, but I would go so far as to say that controlling behaviour using structured customizable data is the Emacs Way, e.g. auto-mode-alist, font lock keywords etc.

rejeep commented 10 years ago

Agreed, but I don't like that. For example it's impossible to read the custom-set-variables.

I find plist's hopeless to work with, so I'll probably never use that internally. If you can figure out a good way to not duplicate the data and still allow for both ways of defining services, let me know. :)

purcell commented 10 years ago

For example it's impossible to read the custom-set-variables.

custom-set-variables isn't meant to be readable, so that's no surprise. But a defcustom can specify the exact shape of its contents, so it actually gives you some amount of validation for free.

If you can figure out a good way to not duplicate the data and still allow for both ways of defining services, let me know. :)

See ac-define-source, which is really just a fancy defvar. Imagine the contents of prodigy-services being a list of symbols (a la flycheck-checkers) which refer to services which have been defined elsewhere either as named variables or with prodigy-define-service. Seems like a tried and tested solution.

rejeep commented 10 years ago

custom-set-variables isn't meant to be readable, so that's no surprise.

Bad example. Just look at themes. Impossible to understand! And sure, it's not impossible to read defcustom's, but they are impossible to write. But I guess that's not the point either. But I usually want to write/read my config. That's kind of the whole idea for me with Emacs :)

Imagine the contents of prodigy-services being a list of symbols ...

I don't see how that solves the issue? That means that the internal data structures depends on how the API is designed, which does not make any sense.

purcell commented 10 years ago

But I usually want to write/read my config. That's kind of the whole idea for me with Emacs :) [snip] That means that the internal data structures depends on how the API is designed, which does not make any sense

You're assuming users want an API. Many (most?) emacs users don't even want to write a .emacs file, and use M-x customize for everything possible. That's probably the main reason why all the existing popular code works the way it does.

But in any case, my intention isn't to take up our time discussing stuff, just to offer a counter point of view. Happy that you put the package together. :-)

rejeep commented 10 years ago

You're assuming users want an API.

Probably, yes. It's how I want to do it, so I only think about that case.

But in any case, my intention isn't to take up our time discussing stuff, just to offer a counter point of view

Not at all, I'm happy to discuss this!

I just hate the fact that the internals are affected by the (non) API. But if you think (I have no idea) that many users want to configure packages like this, it's definitely something that should work.

purcell commented 10 years ago

I was a user like that myself for a while when I first switched from vim (in 1999!), and I believe it's common: even in these days of fancy starter kits, I expect that many users download a kit and then start tinkering with customize before they work up the courage to write any elisp. Now I think elisp is the whole point of emacs, but it's amazing how far you can adjust emacs without writing any.

rejeep commented 10 years ago

Still, do you think it makes sense to use customize to define services? By time it will get more advanced. For example, you can specify a function to the :init property. How would that even work?

magnars commented 10 years ago

An argument from the side lines: If it was a data structure instead of an API, I would already know how to have separate lists of services based on which project I've currently got open.

rejeep commented 10 years ago

I guess symbols can be used instead of lambdas to solve that issue. @magnars Do you also prefer customize?

magnars commented 10 years ago

No, I don't care about customize one bit. But I still see the benefits of data structures over APIs.

rejeep commented 10 years ago

@purcell I created a branch where I use a plist instead of a hash table https://github.com/rejeep/prodigy.el/tree/customize. The variable prodigy-services is still a variable though. If you have any customize magic up your sleeves, I could sure use it :)

Still the branch allow the setq approach.

purcell commented 10 years ago

Looks good to me.

If I get chance in the next couple of days I'll send a PR converting prodigy-services into a defcustom with a constrained layout.

rejeep commented 10 years ago

If I get chance in the next couple of days I'll send a PR converting prodigy-services into a defcustom with a constrained layout.

That would be awesome, thanks!

joelmccracken commented 10 years ago

This precise issue sounds like something that would pair very well with projectile. Thoughts?