atlas-engineer / nfiles

User configuration and data file management
BSD 3-Clause "New" or "Revised" License
17 stars 5 forks source link

Symlinking issue #2

Closed ghost closed 2 years ago

ghost commented 2 years ago

First of all, thank you for this library, it has made file management on Nyxt way more coherent. To give a little background, I use Home Configuration to manage my dotfiles, including my Nyxt init, which I have split into many other configuration files.

I recently pulled the latest version of Nyxt master, and I stumbled upon the fact that nyxt-init-file or *init-file* for that matter, didn't point to the correct location, but instead, pointed to /gnu/store/ and the corresponding Nyxt init file in the Guix store respectively, which are the resolved symlinks for the files in the Nyxt configuration directory. This got me wondering why did you opt for :truenamize t in the nfiles:resolve :around auxiliary method of nfiles:file in the first place. I'm currently overriding this method in my configuration without the call to :truenamize t and it does the job, but I was wondering if there's a more apt solution for this.

Ambrevar commented 2 years ago

I'm not sure I understand. Is this symlink resolution a problem in your case? It should point to the right file in any case, doesn't it?

I also use symlinks to store my configuration to a dotfiles repo, and Nyxt works as expected.

The main reason for following symlinks is so that all operations done on the expansion of the path behave as expected on the actual file rather than on the symlink. There might have been another reason behind this design choice, but I can't remember right now :)

Ambrevar commented 2 years ago

P.S.: Thanks for the kind words, glad you like it and even happier that it achieved its objective of making file management easier!

ghost commented 2 years ago

Yes, in my case it is, but I understand it may be a very specific scenario, although I believe it's worth evaluating. The problem lies, in that functions such as nyxt-init-file, which returns the enclosing directory path from the init file, will point to the original's file parent directory instead of the symlink's. This is an issue with Guix home, given as my Nyxt init file is stored, for instance, under the /gnu/store/112zbfdyz48jckcqq96xqk6dhfpvrib1-init.lisp file in the store.

Within my init, I load other Nyxt configuration files that ought to be located under a lisp/ subdirectory relative to the init file, such as style.lisp. Since invoking nyxt-init-file will point to /gnu/store/ instead of ~/.config/nyxt/, when I write something like (nyxt-init-file "/lisp/style.lisp") this will get me in trouble because it will refer to /gnu/store/lisp/style.lisp instead of what would be the appropriate file in the store (e.g. /gnu/store/2y9b8myl0g28kkrp31wbvsxgwzrvbm0y-style.lisp) or alternatively ~/.config/nyxt/lisp/style.lisp.

To provide a more clear explanation, this is my current service configuration for Nyxt via Home Configuration.

(define-module (efimerspan home web-browsers)
  #:use-module (efimerspan home)
  #:use-module (gnu home-services base)
  #:use-module (gnu home services)
  #:use-module (gnu services)
  #:use-module (gnu packages web-browsers)
  #:use-module (gnu packages gstreamer)
  #:use-module (guix gexp)
  #:use-module (ice-9 ftw))

(define-public services
  (list
   (home-generic-service
    'home-nyxt-service
    #:packages (list nyxt gst-libav gstreamer gst-plugins-bad
                     gst-plugins-ugly gst-plugins-good gst-plugins-base)
    #:files
    (append
      `(("config/nyxt/init.lisp"
         ,(local-file (string-append %project-root "/etc/init.lisp")))
        ("local/share/nyxt/auto-mode-rules.lisp"
         ,(local-file (string-append %project-root "/etc/auto-mode-rules.lisp"))))
      (map
       (lambda (file)
         `(,(string-append "config/nyxt/lisp/" file)
           ,(local-file (string-append %project-root "/etc/nyxt/" file))))
       (scandir (string-append %project-root "/etc/nyxt")
                (lambda (file)
                  (string-suffix? ".lisp" file))))))))

Where my non-init Nyxt configuration files are stored in my dotfiles repository under /etc/nyxt/ and the above will basically symlink them into ~/.config/nyxt/lisp/.

And this is the section of my Nyxt configuration which is in charge of loading the additional configuration files.

(defun load-configuration-files ()
  "Loads Nyxt configuration files."
  (loop with lisp-path = (merge-pathnames (uiop:pathname-directory-pathname
                                           (nfiles:expand *init-file*))
                                          "lisp")
        with extension-files = `((:nx-mapper . ,(nyxt-init-file "lisp/style.lisp"))
                                 (:nx-mapper . ,(nyxt-init-file "lisp/url.lisp"))
                                 (:nx-search-engines . ,(nyxt-init-file "lisp/search-engines.lisp")))
        for file in (uiop:directory-files lisp-path)
        unless (find file extension-files :test #'equal :key #'cdr)
          do (load file)
        finally (dolist (extension-file extension-files)
                  (load-after-system (car extension-file) (cdr extension-file)))))

As I pointed out, perhaps this is too specific due to the nature of my configuration, but it certainly is an issue with the way Guix stores the files, and I'm really not sure how would one go about it unless the symlink resolution isn't performed, otherwise the user is required to specify a custom base path for their Nyxt init file.

Ambrevar commented 2 years ago

You are right, I think it's an issue, but then the issue is not really with nfiles but rather with nyxt-init-file, no? We could simply redefine the function to something like (untested):

(defun nyxt-init-file (&optional subpath)
  "Return SUBPATH relative to `*init-file*'.
Return nil if `*init-file*' is nil.

Example:
If for example, we want to load a define-command procedure that lives in ~/path/to/nyxt/config/dir/my-slink.lisp
(load-after-system :slynk (nyxt-init-file \"my-slink.lisp\"))"
  (if subpath
      (nfiles:expand (make-instance 'init-file :base-path subpath))
      (nfiles:expand *init-file*)))
Ambrevar commented 2 years ago

Bonus: it's shorter and clearer! :)

ghost commented 2 years ago

Yup, that works just fine! Will you push a fix for it on Nyxt or do you want me to make a PR?

Ambrevar commented 2 years ago

If you want to take credit for it, please send a PR! :) If you don't have the time, no problem, I'll do it later.

ghost commented 2 years ago

Now you've confirmed you'll address it, I wouldn't want to take credit for your solution, so I'll patiently wait. Thanks ever so much for the help!

Ambrevar commented 2 years ago

No problem, done; https://github.com/atlas-engineer/nyxt/commit/95c859c2ff1c8c84d936ec0868f32a7aa6276c69.