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

Add a simple package manager for lisp/lem libraries #1249

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

Sasanidas
Copy link
Member

This is the initial proposal of a simple package manager, this implementations contains the following features:

  • A simple and declarative way of defining an external package (in this context, "package" is basically an asd system), both using quicklisp and git (with the possibility of using a custom branch and/or commit) as a source:
lem-declarative.mp4
  • Two commands to manage packages (install/remove) from quicklisp and from git:
command-installation.mp4

I chose to use a folder in "~/.lem/packages" to save the packages, the dependencies of the packages will be managed by quicklisp. This approach helps developing external packages while using Lem (I can load packages from git, modify them and push the changes to the package repository).

I'm planning to extend the lem-use-package options in the future to add more useful features.

(The idea of this simple approach is to just have something to manage packages until https://github.com/lem-project/lem-extension-manager is finished)

@Sasanidas Sasanidas requested a review from cxxxr January 11, 2024 22:54
@Sasanidas Sasanidas self-assigned this Jan 11, 2024

(defun packages-list ()
(remove-duplicates
(mapcar #'(lambda (d) (pathname (directory-namestring d)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure #' in front of lambda is old style and not necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I think this was some GNU Emacs flashback 😆

@vindarel
Copy link
Collaborator

and my feedback:

  • use a shorter package name? (or more fun :p )
  • in run-git or the download functions: no need of more error handling? (network error, the repository doesn't exist etc)
  • eval-when: will this be run at compile time? It should be run when the user launches the package manager.
  • I don't undesrtand the names spackage, rsource, pdir, dfsource, rpackage.
  • what about splitting the macro: extract the flet, use a call-with- pattern?
  • write an accompanying user-level documentation, that we would keep in sync with the source and copy-paste to lem-pages?

@Sasanidas
Copy link
Member Author

  • use a shorter package name? (or more fun :p )

Ummm, I think simple-package is good enough, I'm not that creative when it comes to names 😅

  • in run-git or the download functions: no need of more error handling? (network error, the repository doesn't exist etc)

I wanted the error to just rise to the interface (which Lem can handle and show to the user), maybe I can catch some and improve
the messages, but I think they are quite clear most of them.

  • eval-when: will this be run at compile time? It should be run when the user launches the package manager.

Indeed I don't think it's necessary the eval-when, but this should not be updated every time the user launches a command,
it's most like a cache for ql packages for auto-completion.

  • I don't undesrtand the names spackage, rsource, pdir, dfsource, rpackage.

spackage = simple-package
rsource = it's the local source defined
pdir = package directory
dfsource = define-source
rpackage = it's the local name for the package

They are kind of inferred from the context, but indeed this style of naming is not usual.

  • what about splitting the macro: extract the flet, use a call-with- pattern?

Indeed, I'll move the flet to a separate, about the call-with-pattern, I'll add it for the configuration of the downloaded
package (basically the s-expression of the configuration keyword that is not yet available).

  • write an accompanying user-level documentation, that we would keep in sync with the source and copy-paste to lem-pages?

Indeed! I'm planning to document everything, I just wanted the feedback of Sasaki-san first maybe he wish to make some changes or have other requests.

@vindarel
Copy link
Collaborator

eval-when […] it's most like a cache for ql packages for auto-completion.

then a simple variable not instantiated, to check with boundp? (to differentiate with NIL) This seems nicer and simpler… and more correct? 🤔

@Sasanidas
Copy link
Member Author

Sasanidas commented Jan 12, 2024

then a simple variable not instantiated, to check with boundp? (to differentiate with NIL) This seems nicer and simpler… and more correct? 🤔

I'm using it as a constant basically (not really a constant, but is not meant to change), it should get populated when compiling, which given the rate of update of quicklisp should be enough I think. I'll add a command to update the packages list in the future.

@vindarel
Copy link
Collaborator

I'm using it as a constant basically (not really a constant, but is not meant to change), it should get populated when compiling, which given the rate of update of quicklisp should be enough I think. I'll add a command to update the packages list in the future.

so there can be a difference between the compile-time list and the user's Quicklisp dist. It's maybe less an issue than I think, specially with a command to update it.

no more questions and remarks, thanks. Great addition.

@Sasanidas
Copy link
Member Author

There is an interesting problem that I would have to address. When calling the lem-use-package, is there code that uses the packages that it loads, it will trigger a read-time error (as at read time the package itself hasn't been loaded yet).

So, my idea is to do a macro-reader to load the package at read-time , so any reference below can work without problems

@Sasanidas
Copy link
Member Author

Sasanidas commented Jan 13, 2024

So, to not add more complexity, I just added a function to load the initial files (instead of doing it using a custom asd system). This will allow to load the file at read time with the built-in read macro #., so lem-use-package have to be use in a loaded file:

#.(lem/simple-package:lem-use-package
   "lisp-critic"
   :source '(:type :git
             :url "https://github.com/g000001/lisp-critic.git"))

(define-command fer/critic-reference () ()
  (let ((beg nil)
        (end nil)
        (output-string nil))
    (lem:with-point ((p (current-point)))
      (funcall
       (variable-value 'lem/language-mode:beginning-of-defun-function :buffer)
       p 1)
      (setf beg (copy-point p)
            end (lem-vi-mode/commands::vi-forward-matching-paren
                 (current-window) p)
            output-string (with-output-to-string (s)
                            (let ((*standard-output* s))
                              (lisp-critic:critique-definition
                               (read-from-string
                                (format nil "~a)"(points-to-string beg end)))))))
      (fer/describe-thing
       (or (and (not (str:emptyp output-string)) output-string)
           "All is well!")))))

(in this example, the file has to be loaded, otherwise the reader may fail if it load the file from the cache)

@Sasanidas
Copy link
Member Author

I changed the name of the commands to use the prefix sp as I think its more easy to use that way

@Sasanidas
Copy link
Member Author

So I think the functionality of this PR is finish and ready for testing. I'll document everything in the webpage after merge-time :)

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

Successfully merging this pull request may close these issues.

None yet

2 participants