* [PATCH 0/6] emacs: Add interface for package locations.
@ 2016-04-04 19:47 Alex Kost
2016-04-04 19:47 ` [PATCH 1/6] emacs: Add 'guix-packages-by-location' command Alex Kost
` (6 more replies)
0 siblings, 7 replies; 24+ messages in thread
From: Alex Kost @ 2016-04-04 19:47 UTC (permalink / raw)
To: guix-devel
Hello, this patchset adds an Emacs interface for package locations,
which is very similar to the existing interface for licenses
(guix-licenses, guix-packages-by-license and guix-browse-license-url
commands).
The following commands are added:
- "M-x guix-locations": display a list of package locations (see
the left part of the screenshot¹).
- "M-x guix-packages-by-location": display packages from a particular
location.
- "M-x guix-find-location": move to a particular location. It is the
same as you can do with "M-x guix-edit" but instead of selecting a
package name, you choose a location.
Also *Guix Package Info* buffer shows "Packages" buttons that can be
used to display packages by license and by location (see the right part
of the screenshot).
[PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
[PATCH 2/6] emacs: Separate package location code.
[PATCH 3/6] emacs: Make 'guix-find-location' interactive.
[PATCH 4/6] doc: emacs: Add "Locations" section.
[PATCH 5/6] emacs: Add interface for package locations.
[PATCH 6/6] emacs: Add license/location "Packages" buttons to Info.
¹ http://i.imgur.com/PBmuxex.png
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
@ 2016-04-04 19:47 ` Alex Kost
2016-04-05 20:38 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 2/6] emacs: Separate package location code Alex Kost
` (5 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-04 19:47 UTC (permalink / raw)
To: guix-devel
* emacs/guix-main.scm (%package-location-table): New variable.
(package-location-table, package-locations, packages-by-location): New
procedures.
(%patterns-makers): Add 'location' search type.
* emacs/guix-messages.el (guix-message-packages-by-location): New procedure.
(guix-messages): Use it.
* emacs/guix-read.el (guix-package-locations)
(guix-read-package-location): New procedures.
* emacs/guix-ui-package.el (guix-packages-by-location): New command.
* doc/emacs.texi (Emacs Commands): Document it.
---
doc/emacs.texi | 3 +++
emacs/guix-main.scm | 38 ++++++++++++++++++++++++++++++++++++++
emacs/guix-messages.el | 15 +++++++++++++++
emacs/guix-read.el | 10 ++++++++++
emacs/guix-ui-package.el | 12 +++++++++++-
5 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/doc/emacs.texi b/doc/emacs.texi
index c4fdfff..16ff4d5 100644
--- a/doc/emacs.texi
+++ b/doc/emacs.texi
@@ -160,6 +160,9 @@ Display package(s) with the specified name.
@item M-x guix-packages-by-license
Display package(s) with the specified license.
+@item M-x guix-packages-by-location
+Display package(s) placed in the specified location.
+
@item M-x guix-search-by-regexp
Search for packages by a specified regexp. By default ``name'',
``synopsis'' and ``description'' of the packages will be searched. This
diff --git a/emacs/guix-main.scm b/emacs/guix-main.scm
index c620440..9950cad 100644
--- a/emacs/guix-main.scm
+++ b/emacs/guix-main.scm
@@ -39,6 +39,9 @@
;;
;; - `%package-table' - Hash table of
;; "name+version key"/"list of packages" pairs.
+;;
+;; - `%location-table' - Hash table of
+;; "package location"/"list of packages" pairs.
;;; Code:
@@ -684,6 +687,8 @@ ENTRIES is a list of installed manifest entries."
(license-proc (lambda (_ license-name)
(packages-by-license
(lookup-license license-name))))
+ (location-proc (lambda (_ location)
+ (packages-by-location location)))
(all-proc (lambda _ (all-available-packages)))
(newest-proc (lambda _ (newest-available-packages))))
`((package
@@ -693,6 +698,7 @@ ENTRIES is a list of installed manifest entries."
(obsolete . ,(apply-to-first obsolete-package-patterns))
(regexp . ,regexp-proc)
(license . ,license-proc)
+ (location . ,location-proc)
(all-available . ,all-proc)
(newest-available . ,newest-proc))
(output
@@ -702,6 +708,7 @@ ENTRIES is a list of installed manifest entries."
(obsolete . ,(apply-to-first obsolete-output-patterns))
(regexp . ,regexp-proc)
(license . ,license-proc)
+ (location . ,location-proc)
(all-available . ,all-proc)
(newest-available . ,newest-proc)))))
@@ -1097,3 +1104,34 @@ Return #t if the shell command was executed successfully."
(define (license-entries search-type . search-values)
(map license->sexp
(apply find-licenses search-type search-values)))
+
+\f
+;;; Package locations
+
+(define %package-location-table
+ (delay
+ (let ((table (make-hash-table
+ ;; Rough guess about a number of locations: it is
+ ;; about 10 times less than the number of packages.
+ (euclidean/ (vlist-length (package-vhash)) 10))))
+ ;; XXX Actually, 'for-each-package' is needed but there is no such yet.
+ (fold-packages
+ (lambda (package _)
+ (let* ((location (location-file (package-location package)))
+ (packages (or (hash-ref table location) '())))
+ (hash-set! table location (cons package packages))))
+ #f)
+ table)))
+
+(define (package-location-table)
+ "Return hash table of 'location'/'list of packages' pairs."
+ (force %package-location-table))
+
+(define (package-locations)
+ "Return a list of available package locations."
+ (hash-map->list (lambda (location _) location)
+ (package-location-table)))
+
+(define (packages-by-location location)
+ "Return a list of packages placed in LOCATION."
+ (hash-ref (package-location-table) location))
diff --git a/emacs/guix-messages.el b/emacs/guix-messages.el
index de0331f..7ebe7e8 100644
--- a/emacs/guix-messages.el
+++ b/emacs/guix-messages.el
@@ -40,6 +40,10 @@
,(lambda (_ entries licenses)
(apply #'guix-message-packages-by-license
entries 'package licenses)))
+ (location
+ ,(lambda (_ entries locations)
+ (apply #'guix-message-packages-by-location
+ entries 'package locations)))
(regexp
(0 "No packages matching '%s'." val)
(1 "A single package matching '%s'." val)
@@ -72,6 +76,10 @@
,(lambda (_ entries licenses)
(apply #'guix-message-packages-by-license
entries 'output licenses)))
+ (location
+ ,(lambda (_ entries locations)
+ (apply #'guix-message-packages-by-location
+ entries 'output locations)))
(regexp
(0 "No package outputs matching '%s'." val)
(1 "A single package output matching '%s'." val)
@@ -174,6 +182,13 @@ Try \"M-x guix-search-by-name\"."
(str-end (format "with license '%s'" license)))
(message "%s %s." str-beg str-end)))
+(defun guix-message-packages-by-location (entries entry-type location)
+ "Display a message for packages or outputs searched by LOCATION."
+ (let* ((count (length entries))
+ (str-beg (guix-message-string-entries count entry-type))
+ (str-end (format "placed in '%s'" location)))
+ (message "%s %s." str-beg str-end)))
+
(defun guix-message-generations-by-time (profile entries times)
"Display a message for generations searched by TIMES."
(let* ((count (length entries))
diff --git a/emacs/guix-read.el b/emacs/guix-read.el
index a1a6b86..0551af9 100644
--- a/emacs/guix-read.el
+++ b/emacs/guix-read.el
@@ -62,6 +62,11 @@
"Return a list of names of available licenses."
(guix-eval-read (guix-make-guile-expression 'license-names)))
+(guix-memoized-defun guix-package-locations ()
+ "Return a list of available package locations."
+ (sort (guix-eval-read (guix-make-guile-expression 'package-locations))
+ #'string<))
+
\f
;;; Readers
@@ -131,6 +136,11 @@
:single-reader guix-read-license-name
:single-prompt "License: ")
+(guix-define-readers
+ :completions-getter guix-package-locations
+ :single-reader guix-read-package-location
+ :single-prompt "Location: ")
+
(provide 'guix-read)
;;; guix-read.el ends here
diff --git a/emacs/guix-ui-package.el b/emacs/guix-ui-package.el
index df5f8d1..ecabae1 100644
--- a/emacs/guix-ui-package.el
+++ b/emacs/guix-ui-package.el
@@ -1,6 +1,6 @@
;;; guix-ui-package.el --- Interface for displaying packages -*- lexical-binding: t -*-
-;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
+;; Copyright © 2014, 2015, 2016 Alex Kost <alezost@gmail.com>
;; This file is part of GNU Guix.
@@ -970,6 +970,16 @@ Interactively with prefix, prompt for PROFILE."
(guix-package-get-display profile 'license license))
;;;###autoload
+(defun guix-packages-by-location (location &optional profile)
+ "Display Guix packages placed in LOCATION.
+If PROFILE is nil, use `guix-current-profile'.
+Interactively with prefix, prompt for PROFILE."
+ (interactive
+ (list (guix-read-package-location)
+ (guix-ui-read-profile)))
+ (guix-package-get-display profile 'location location))
+
+;;;###autoload
(defun guix-search-by-regexp (regexp &optional params profile)
"Search for Guix packages by REGEXP.
PARAMS are package parameters that should be searched.
--
2.7.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 2/6] emacs: Separate package location code.
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
2016-04-04 19:47 ` [PATCH 1/6] emacs: Add 'guix-packages-by-location' command Alex Kost
@ 2016-04-04 19:47 ` Alex Kost
2016-04-05 20:39 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 3/6] emacs: Make 'guix-find-location' interactive Alex Kost
` (4 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-04 19:47 UTC (permalink / raw)
To: guix-devel
* emacs/guix-base.el (guix-directory, guix-read-directory)
(guix-set-directory, guix-find-location, guix-package-location)
(guix-edit): Move to...
* emacs/guix-location.el: ... here. New file.
* emacs/guix-ui-package.el: Use it.
* emacs.am (ELFILES): Add it.
---
emacs.am | 1 +
emacs/guix-base.el | 62 +-------------------------------
emacs/guix-location.el | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
emacs/guix-ui-package.el | 1 +
4 files changed, 97 insertions(+), 61 deletions(-)
create mode 100644 emacs/guix-location.el
diff --git a/emacs.am b/emacs.am
index 1897e2e..c0d294d 100644
--- a/emacs.am
+++ b/emacs.am
@@ -40,6 +40,7 @@ ELFILES = \
emacs/guix-init.el \
emacs/guix-license.el \
emacs/guix-list.el \
+ emacs/guix-location.el \
emacs/guix-messages.el \
emacs/guix-pcomplete.el \
emacs/guix-popup.el \
diff --git a/emacs/guix-base.el b/emacs/guix-base.el
index 75d19cb..8888364 100644
--- a/emacs/guix-base.el
+++ b/emacs/guix-base.el
@@ -48,53 +48,7 @@
(when output (concat ":" output))))
\f
-;;; Location of packages, profiles and manifests
-
-(defvar guix-directory nil
- "Default Guix directory.
-If it is not set by a user, it is set after starting Guile REPL.
-This directory is used to define location of the packages.")
-
-(defun guix-read-directory ()
- "Return `guix-directory' or prompt for it.
-This function is intended for using in `interactive' forms."
- (if current-prefix-arg
- (read-directory-name "Directory with Guix modules: "
- guix-directory)
- guix-directory))
-
-(defun guix-set-directory ()
- "Set `guix-directory' if needed."
- (or guix-directory
- (setq guix-directory
- (guix-eval-read "%guix-dir"))))
-
-(add-hook 'guix-after-start-repl-hook 'guix-set-directory)
-
-(defun guix-find-location (location &optional directory)
- "Go to LOCATION of a package.
-LOCATION is a string of the form:
-
- \"PATH:LINE:COLUMN\"
-
-If PATH is relative, it is considered to be relative to
-DIRECTORY (`guix-directory' by default)."
- (cl-multiple-value-bind (path line col)
- (split-string location ":")
- (let ((file (expand-file-name path (or directory guix-directory)))
- (line (string-to-number line))
- (col (string-to-number col)))
- (find-file file)
- (goto-char (point-min))
- (forward-line (- line 1))
- (move-to-column col)
- (recenter 1))))
-
-(defun guix-package-location (id-or-name)
- "Return location of a package with ID-OR-NAME.
-For the meaning of location, see `guix-find-location'."
- (guix-eval-read (guix-make-guile-expression
- 'package-location-string id-or-name)))
+;;; Location of profiles and manifests
(defun guix-generation-file (profile generation)
"Return the file name of a PROFILE's GENERATION."
@@ -120,20 +74,6 @@ See `guix-packages-profile'."
(expand-file-name "manifest"
(guix-packages-profile profile generation system?)))
-;;;###autoload
-(defun guix-edit (id-or-name &optional directory)
- "Edit (go to location of) package with ID-OR-NAME.
-See `guix-find-location' for the meaning of package location and
-DIRECTORY.
-Interactively, with prefix argument, prompt for DIRECTORY."
- (interactive
- (list (guix-read-package-name)
- (guix-read-directory)))
- (let ((loc (guix-package-location id-or-name)))
- (if loc
- (guix-find-location loc directory)
- (message "Couldn't find package location."))))
-
\f
;;; Actions on packages and generations
diff --git a/emacs/guix-location.el b/emacs/guix-location.el
new file mode 100644
index 0000000..c6f9b86
--- /dev/null
+++ b/emacs/guix-location.el
@@ -0,0 +1,94 @@
+;;; guix-location.el --- Package locations
+
+;; Copyright © 2016 Alex Kost <alezost@gmail.com>
+
+;; This file is part of GNU Guix.
+
+;; GNU Guix is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public Location as published by
+;; the Free Software Foundation, either version 3 of the Location, or
+;; (at your option) any later version.
+
+;; GNU Guix is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public Location for more details.
+
+;; You should have received a copy of the GNU General Public Location
+;; along with this program. If not, see <http://www.gnu.org/locations/>.
+
+;;; Commentary:
+
+;; This file provides the code to work with locations of Guix packages.
+
+;;; Code:
+
+(require 'guix-backend)
+(require 'guix-read)
+(require 'guix-guile)
+
+(defvar guix-directory nil
+ "Default Guix directory.
+If it is not set by a user, it is set after starting Guile REPL.
+This directory is used to define location of the packages.")
+
+(defun guix-read-directory ()
+ "Return `guix-directory' or prompt for it.
+This function is intended for using in `interactive' forms."
+ (if current-prefix-arg
+ (read-directory-name "Directory with Guix modules: "
+ guix-directory)
+ guix-directory))
+
+;;;###autoload
+(defun guix-set-directory ()
+ "Set `guix-directory' if needed."
+ (or guix-directory
+ (setq guix-directory
+ (guix-eval-read "%guix-dir"))))
+
+;;;###autoload
+(add-hook 'guix-after-start-repl-hook 'guix-set-directory)
+
+(defun guix-package-location (id-or-name)
+ "Return location of a package with ID-OR-NAME.
+For the meaning of location, see `guix-find-location'."
+ (guix-eval-read (guix-make-guile-expression
+ 'package-location-string id-or-name)))
+
+(defun guix-find-location (location &optional directory)
+ "Go to LOCATION of a package.
+LOCATION is a string of the form:
+
+ \"PATH:LINE:COLUMN\"
+
+If PATH is relative, it is considered to be relative to
+DIRECTORY (`guix-directory' by default)."
+ (cl-multiple-value-bind (path line col)
+ (split-string location ":")
+ (let ((file (expand-file-name path (or directory guix-directory)))
+ (line (string-to-number line))
+ (col (string-to-number col)))
+ (find-file file)
+ (goto-char (point-min))
+ (forward-line (- line 1))
+ (move-to-column col)
+ (recenter 1))))
+
+;;;###autoload
+(defun guix-edit (id-or-name &optional directory)
+ "Edit (go to location of) package with ID-OR-NAME.
+See `guix-find-location' for the meaning of package location and
+DIRECTORY.
+Interactively, with prefix argument, prompt for DIRECTORY."
+ (interactive
+ (list (guix-read-package-name)
+ (guix-read-directory)))
+ (let ((loc (guix-package-location id-or-name)))
+ (if loc
+ (guix-find-location loc directory)
+ (message "Couldn't find package location."))))
+
+(provide 'guix-location)
+
+;;; guix-location.el ends here
diff --git a/emacs/guix-ui-package.el b/emacs/guix-ui-package.el
index ecabae1..aba30ab 100644
--- a/emacs/guix-ui-package.el
+++ b/emacs/guix-ui-package.el
@@ -38,6 +38,7 @@
(require 'guix-hydra-build)
(require 'guix-read)
(require 'guix-license)
+(require 'guix-location)
(require 'guix-profiles)
(guix-ui-define-entry-type package)
--
2.7.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 3/6] emacs: Make 'guix-find-location' interactive.
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
2016-04-04 19:47 ` [PATCH 1/6] emacs: Add 'guix-packages-by-location' command Alex Kost
2016-04-04 19:47 ` [PATCH 2/6] emacs: Separate package location code Alex Kost
@ 2016-04-04 19:47 ` Alex Kost
2016-04-05 20:41 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 4/6] doc: emacs: Add "Locations" section Alex Kost
` (3 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-04 19:47 UTC (permalink / raw)
To: guix-devel
* emacs/guix-location.el (guix-find-location): Make interactive. Adjust
to handle "reduced" locations (without line and column numbers).
---
emacs/guix-location.el | 34 ++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/emacs/guix-location.el b/emacs/guix-location.el
index c6f9b86..d28d5ef 100644
--- a/emacs/guix-location.el
+++ b/emacs/guix-location.el
@@ -56,24 +56,34 @@ For the meaning of location, see `guix-find-location'."
(guix-eval-read (guix-make-guile-expression
'package-location-string id-or-name)))
+\f
+;;; Interactive commands
+
+;;;###autoload
(defun guix-find-location (location &optional directory)
"Go to LOCATION of a package.
LOCATION is a string of the form:
- \"PATH:LINE:COLUMN\"
+ \"FILE:LINE:COLUMN\"
+
+If FILE is relative, it is considered to be relative to
+DIRECTORY (`guix-directory' by default).
-If PATH is relative, it is considered to be relative to
-DIRECTORY (`guix-directory' by default)."
- (cl-multiple-value-bind (path line col)
+Interactively, prompt for LOCATION. With prefix argument, prompt
+for DIRECTORY as well."
+ (interactive
+ (list (guix-read-package-location)
+ (guix-read-directory)))
+ (cl-multiple-value-bind (file line column)
(split-string location ":")
- (let ((file (expand-file-name path (or directory guix-directory)))
- (line (string-to-number line))
- (col (string-to-number col)))
- (find-file file)
- (goto-char (point-min))
- (forward-line (- line 1))
- (move-to-column col)
- (recenter 1))))
+ (find-file (expand-file-name file (or directory guix-directory)))
+ (when (and line column)
+ (let ((line (string-to-number line))
+ (column (string-to-number column)))
+ (goto-char (point-min))
+ (forward-line (- line 1))
+ (move-to-column column)
+ (recenter 1)))))
;;;###autoload
(defun guix-edit (id-or-name &optional directory)
--
2.7.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 4/6] doc: emacs: Add "Locations" section.
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
` (2 preceding siblings ...)
2016-04-04 19:47 ` [PATCH 3/6] emacs: Make 'guix-find-location' interactive Alex Kost
@ 2016-04-04 19:47 ` Alex Kost
2016-04-05 20:46 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 5/6] emacs: Add interface for package locations Alex Kost
` (2 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-04 19:47 UTC (permalink / raw)
To: guix-devel
* doc/emacs.texi (Emacs Commands): Move description of 'guix-edit'
command to...
(Emacs Locations): ... here. Document 'guix-find-location'. New
section.
* doc/guix.texi (Top): Add it.
---
doc/emacs.texi | 63 ++++++++++++++++++++++++++++++++++++----------------------
doc/guix.texi | 1 +
2 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/doc/emacs.texi b/doc/emacs.texi
index 16ff4d5..5a5fbc2 100644
--- a/doc/emacs.texi
+++ b/doc/emacs.texi
@@ -10,6 +10,7 @@ Guix convenient and fun.
* Initial Setup: Emacs Initial Setup. Preparing @file{~/.emacs}.
* Package Management: Emacs Package Management. Managing packages and generations.
* Licenses: Emacs Licenses. Interface for licenses of Guix packages.
+* Locations: Emacs Locations. Interface for package locations.
* Popup Interface: Emacs Popup Interface. Magit-like interface for guix commands.
* Prettify Mode: Emacs Prettify. Abbreviating @file{/gnu/store/@dots{}} file names.
* Build Log Mode: Emacs Build Log. Highlighting Guix build logs.
@@ -220,30 +221,6 @@ With @kbd{C-u}, make it verbose.
Once @command{guix pull} has succeeded, the Guix REPL is restared. This
allows you to keep using the Emacs interface with the updated Guix.
-Finally, there is an Emacs variant of @command{guix edit} command
-(@pxref{Invoking guix edit}):
-
-@table @kbd
-@item M-x guix-edit
-As with @kbd{M-x guix-packages-by-name}, you can press @key{TAB} to
-complete a package name.
-@end table
-
-If you are contributing to Guix, you may find it useful for @kbd{M-x
-guix-edit} to open package files from your git directory. This can be
-done by setting @code{guix-directory} variable. For example, after
-this:
-
-@example
-(setq guix-directory "~/src/guix")
-@end example
-
-@kbd{M-x guix-edit guix} opens
-@file{~/src/guix/gnu/packages/package-management.scm} file.
-
-Also you can use @kbd{C-u} prefix argument to specify a directory just
-for the current @kbd{M-x guix-edit} command.
-
@node Emacs General info
@subsection General information
@@ -568,6 +545,44 @@ guix-packages-by-license} would do (@pxref{Emacs Commands}).
@end table
+@node Emacs Locations
+@section Locations
+
+As you know, package definitions are placed in Guile files, also known
+as @dfn{package locations}. The following commands should help you not
+getting lost in these locations:
+
+@table @kbd
+
+@item M-x guix-find-location
+Find package location file (press @key{TAB} to choose a location from a
+completion list).
+
+@item M-x guix-edit
+Find location of a specified package. This is an Emacs analog of
+@command{guix edit} command (@pxref{Invoking guix edit}). As with
+@kbd{M-x guix-packages-by-name}, you can press @key{TAB} to complete a
+package name.
+
+@end table
+
+If you are contributing to Guix, you may find it useful for @kbd{M-x
+guix-find-location} and @kbd{M-x guix-edit} to open locations from your
+git directory. This can be done by setting @code{guix-directory}
+variable. For example, after this:
+
+@example
+(setq guix-directory "~/src/guix")
+@end example
+
+@kbd{M-x guix-edit guix} opens
+@file{~/src/guix/gnu/packages/package-management.scm} file.
+
+Also you can use @kbd{C-u} prefix argument to specify a directory just
+for the current @kbd{M-x guix-find-location} or @kbd{M-x guix-edit}
+command.
+
+
@node Emacs Popup Interface
@section Popup Interface
diff --git a/doc/guix.texi b/doc/guix.texi
index a34d547..710adbd 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -118,6 +118,7 @@ Emacs Interface
* Initial Setup: Emacs Initial Setup. Preparing @file{~/.emacs}.
* Package Management: Emacs Package Management. Managing packages and generations.
* Licenses: Emacs Licenses. Interface for licenses of Guix packages.
+* Locations: Emacs Locations. Interface for package locations.
* Popup Interface: Emacs Popup Interface. Magit-like interface for guix commands.
* Prettify Mode: Emacs Prettify. Abbreviating @file{/gnu/store/@dots{}} file names.
* Build Log Mode: Emacs Build Log. Highlighting Guix build logs.
--
2.7.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 5/6] emacs: Add interface for package locations.
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
` (3 preceding siblings ...)
2016-04-04 19:47 ` [PATCH 4/6] doc: emacs: Add "Locations" section Alex Kost
@ 2016-04-04 19:47 ` Alex Kost
2016-04-05 20:50 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer Alex Kost
2016-04-05 20:25 ` [PATCH 0/6] emacs: Add interface for package locations Ludovic Courtès
6 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-04 19:47 UTC (permalink / raw)
To: guix-devel
* emacs/guix-main.scm (%package-location-param-alist): New variable.
(package-location->sexp, package-location-entries): New procedures.
* emacs/guix-ui-location.el: New file.
* emacs.am (ELFILES): Add it.
* doc/emacs.texi (Emacs Locations): Document 'guix-locations'.
* NEWS: Mention it.
---
NEWS | 6 ++++
doc/emacs.texi | 7 ++++
emacs.am | 1 +
emacs/guix-main.scm | 12 +++++++
emacs/guix-ui-location.el | 83 +++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 109 insertions(+)
create mode 100644 emacs/guix-ui-location.el
diff --git a/NEWS b/NEWS
index 2ab208f..267c197 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,12 @@ Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
Please send Guix bug reports to bug-guix@gnu.org.
+* Changes in 0.11.0 (since 0.10.0)
+
+** Package management
+
+*** New Emacs interface for package locations: M-x guix-locations
+
* Changes in 0.10.0 (since 0.9.0)
** Community
diff --git a/doc/emacs.texi b/doc/emacs.texi
index 5a5fbc2..5348d78 100644
--- a/doc/emacs.texi
+++ b/doc/emacs.texi
@@ -554,6 +554,13 @@ getting lost in these locations:
@table @kbd
+@item M-x guix-locations
+Display a list of package locations. You can press @key{RET} there to
+display packages placed in the current location in the same way as
+@kbd{M-x guix-packages-by-location} would do (@pxref{Emacs Commands}).
+Note that when the point is on a location button, @key{RET} will open
+this location file.
+
@item M-x guix-find-location
Find package location file (press @key{TAB} to choose a location from a
completion list).
diff --git a/emacs.am b/emacs.am
index c0d294d..4d9ffff 100644
--- a/emacs.am
+++ b/emacs.am
@@ -48,6 +48,7 @@ ELFILES = \
emacs/guix-profiles.el \
emacs/guix-read.el \
emacs/guix-ui.el \
+ emacs/guix-ui-location.el \
emacs/guix-ui-package.el \
emacs/guix-ui-generation.el \
emacs/guix-ui-system-generation.el \
diff --git a/emacs/guix-main.scm b/emacs/guix-main.scm
index 9950cad..f2266a8 100644
--- a/emacs/guix-main.scm
+++ b/emacs/guix-main.scm
@@ -1135,3 +1135,15 @@ Return #t if the shell command was executed successfully."
(define (packages-by-location location)
"Return a list of packages placed in LOCATION."
(hash-ref (package-location-table) location))
+
+(define %package-location-param-alist
+ `((id . ,identity)
+ (location . ,identity)
+ (number-of-packages . ,(lambda (location)
+ (length (packages-by-location location))))))
+
+(define package-location->sexp
+ (object-transformer %package-location-param-alist))
+
+(define (package-location-entries)
+ (map package-location->sexp (package-locations)))
diff --git a/emacs/guix-ui-location.el b/emacs/guix-ui-location.el
new file mode 100644
index 0000000..0027c1f
--- /dev/null
+++ b/emacs/guix-ui-location.el
@@ -0,0 +1,83 @@
+;;; guix-ui-location.el --- Interface for displaying package locations
+
+;; Copyright © 2016 Alex Kost <alezost@gmail.com>
+
+;; This file is part of GNU Guix.
+
+;; GNU Guix is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public Location as published by
+;; the Free Software Foundation, either version 3 of the Location, or
+;; (at your option) any later version.
+
+;; GNU Guix is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public Location for more details.
+
+;; You should have received a copy of the GNU General Public Location
+;; along with this program. If not, see <http://www.gnu.org/locations/>.
+
+;;; Commentary:
+
+;; This file provides a 'list' interface for displaying locations of Guix
+;; packages.
+
+;;; Code:
+
+(require 'guix-buffer)
+(require 'guix-list)
+(require 'guix-location)
+(require 'guix-backend)
+
+(guix-define-entry-type location)
+
+(defun guix-location-get-entries ()
+ "Receive 'package location' entries."
+ (guix-eval-read "(package-location-entries)"))
+
+\f
+;;; Location 'list'
+
+(guix-list-define-interface location
+ :buffer-name "*Guix Package Locations*"
+ :get-entries-function 'guix-location-get-entries
+ :format '((location guix-location-list-file-name-specification 50 t)
+ (number-of-packages nil 10 guix-list-sort-numerically-1
+ :right-align t))
+ :sort-key '(location))
+
+(let ((map guix-location-list-mode-map))
+ (define-key map (kbd "RET") 'guix-location-list-show-packages)
+ ;; "Location Info" buffer is not defined (it would be useless), so
+ ;; unbind "i" key (by default, it is used to display Info buffer).
+ (define-key map (kbd "i") nil))
+
+(defun guix-location-list-file-name-specification (location &optional _)
+ "Return LOCATION button specification for `tabulated-list-entries'."
+ (list location
+ 'face 'guix-list-file-name
+ 'action (lambda (btn)
+ (guix-find-location (button-get btn 'location)))
+ 'follow-link t
+ 'help-echo (concat "Find location: " location)
+ 'location location))
+
+(declare-function guix-packages-by-location "guix-ui-package")
+
+(defun guix-location-list-show-packages ()
+ "Display packages placed in the location at point."
+ (interactive)
+ (guix-packages-by-location (guix-list-current-id)))
+
+\f
+;;; Interactive commands
+
+;;;###autoload
+(defun guix-locations ()
+ "Display locations of the Guix packages."
+ (interactive)
+ (guix-list-get-display-entries 'location))
+
+(provide 'guix-ui-location)
+
+;;; guix-ui-location.el ends here
--
2.7.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer.
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
` (4 preceding siblings ...)
2016-04-04 19:47 ` [PATCH 5/6] emacs: Add interface for package locations Alex Kost
@ 2016-04-04 19:47 ` Alex Kost
2016-04-05 20:50 ` Ludovic Courtès
2016-04-05 20:25 ` [PATCH 0/6] emacs: Add interface for package locations Ludovic Courtès
6 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-04 19:47 UTC (permalink / raw)
To: guix-devel
* emacs/guix-ui-package.el (guix-package-info-insert-location)
(guix-package-info-insert-license): New procedures.
(guix-package-info-format): Use them.
(guix-output-info-format): Likewise.
---
emacs/guix-ui-package.el | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/emacs/guix-ui-package.el b/emacs/guix-ui-package.el
index aba30ab..e6f836d 100644
--- a/emacs/guix-ui-package.el
+++ b/emacs/guix-ui-package.el
@@ -223,9 +223,9 @@ ENTRIES is a list of package entries to get info about packages."
ignore
(outputs simple guix-package-info-insert-outputs)
(source simple guix-package-info-insert-source)
- (location format (format guix-package-location))
+ (location simple guix-package-info-insert-location)
+ (license simple guix-package-info-insert-license)
(home-url format (format guix-url))
- (license format (format guix-package-license))
(systems format guix-package-info-insert-systems)
(inputs format (format guix-package-input))
(native-inputs format (format guix-package-native-input))
@@ -383,6 +383,38 @@ formatted with this string, an action button is inserted.")
'guix-package-heading
'spec (guix-package-entry->name-specification entry)))
+(defun guix-package-info-insert-location (location &optional _)
+ "Insert package LOCATION at point."
+ (if (null location)
+ (guix-format-insert nil)
+ (let ((location-file (car (split-string location ":"))))
+ (guix-info-insert-value-indent location 'guix-package-location)
+ (guix-info-insert-indent)
+ (guix-info-insert-action-button
+ "Packages"
+ (lambda (btn)
+ (guix-package-get-display (guix-ui-current-profile)
+ 'location
+ (button-get btn 'location)))
+ (concat "Show packages from location: " location-file)
+ 'location location-file))))
+
+(defun guix-package-info-insert-license (licenses &optional _)
+ "Insert package LICENSES at point."
+ (if (null licenses)
+ (guix-format-insert nil)
+ (dolist (license licenses)
+ (guix-info-insert-value-indent license 'guix-package-license)
+ (guix-info-insert-indent)
+ (guix-info-insert-action-button
+ "Packages"
+ (lambda (btn)
+ (guix-package-get-display (guix-ui-current-profile)
+ 'license
+ (button-get btn 'license)))
+ (concat "Show packages with license: " license)
+ 'license license))))
+
(defun guix-package-info-insert-systems (systems entry)
"Insert supported package SYSTEMS at point."
(guix-info-insert-value-format
@@ -798,9 +830,9 @@ for all ARGS."
(source simple guix-package-info-insert-source)
(path simple (indent guix-file))
(dependencies simple (indent guix-file))
- (location format (format guix-package-location))
+ (location simple guix-package-info-insert-location)
+ (license simple guix-package-info-insert-license)
(home-url format (format guix-url))
- (license format (format guix-package-license))
(systems format guix-package-info-insert-systems)
(inputs format (format guix-package-input))
(native-inputs format (format guix-package-native-input))
--
2.7.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 0/6] emacs: Add interface for package locations.
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
` (5 preceding siblings ...)
2016-04-04 19:47 ` [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer Alex Kost
@ 2016-04-05 20:25 ` Ludovic Courtès
6 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-05 20:25 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> The following commands are added:
>
> - "M-x guix-locations": display a list of package locations (see
> the left part of the screenshot¹).
>
> - "M-x guix-packages-by-location": display packages from a particular
> location.
>
> - "M-x guix-find-location": move to a particular location. It is the
> same as you can do with "M-x guix-edit" but instead of selecting a
> package name, you choose a location.
Good idea, that looks pretty cool!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
2016-04-04 19:47 ` [PATCH 1/6] emacs: Add 'guix-packages-by-location' command Alex Kost
@ 2016-04-05 20:38 ` Ludovic Courtès
2016-04-06 9:20 ` Alex Kost
0 siblings, 1 reply; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-05 20:38 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> * emacs/guix-main.scm (%package-location-table): New variable.
> (package-location-table, package-locations, packages-by-location): New
> procedures.
> (%patterns-makers): Add 'location' search type.
> * emacs/guix-messages.el (guix-message-packages-by-location): New procedure.
> (guix-messages): Use it.
> * emacs/guix-read.el (guix-package-locations)
> (guix-read-package-location): New procedures.
> * emacs/guix-ui-package.el (guix-packages-by-location): New command.
> * doc/emacs.texi (Emacs Commands): Document it.
[...]
> +@item M-x guix-packages-by-location
> +Display package(s) placed in the specified location.
s/location/source file/ IIUC. Also, this must be a relative file name
like “gnu/packages/emacs.scm”, not just “emacs.scm”, right? It would be
nice to clarify this here.
> +(define %package-location-table
> + (delay
> + (let ((table (make-hash-table
> + ;; Rough guess about a number of locations: it is
> + ;; about 10 times less than the number of packages.
> + (euclidean/ (vlist-length (package-vhash)) 10))))
> + ;; XXX Actually, 'for-each-package' is needed but there is no such yet.
> + (fold-packages
> + (lambda (package _)
> + (let* ((location (location-file (package-location package)))
> + (packages (or (hash-ref table location) '())))
> + (hash-set! table location (cons package packages))))
> + #f)
> + table)))
For the record (and maybe for a future patch, because the rest of the
file already uses the idiom above anyway), I find it somewhat “better”
to (1) use vhashes (easier to reason about), and (2) define lookup
procedures instead of exposing the data structure (no need to document
the data structure, can be changed at will, etc.).
That is, I would rather write:
(define packages-in-source-file
(let ((table (delay (fold-packages
(lambda (package table)
(match (and=> (package-location package)
location-file)
(#f table)
(file (vhash-cons file package table))))
vlist-null))))
(lambda (file)
"Return the (possibly empty) list of packages defined in FILE."
(vhash-fold* cons '() file (force table)))))
WDYT?
> +(define (packages-by-location location)
> + "Return a list of packages placed in LOCATION."
> + (hash-ref (package-location-table) location))
Again use “file” here since it’s a file name, not a <location> record,
that’s expected.
Also: “Return _the_ list”.
Otherwise LGTM.
Thanks!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/6] emacs: Separate package location code.
2016-04-04 19:47 ` [PATCH 2/6] emacs: Separate package location code Alex Kost
@ 2016-04-05 20:39 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-05 20:39 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> * emacs/guix-base.el (guix-directory, guix-read-directory)
> (guix-set-directory, guix-find-location, guix-package-location)
> (guix-edit): Move to...
> * emacs/guix-location.el: ... here. New file.
> * emacs/guix-ui-package.el: Use it.
> * emacs.am (ELFILES): Add it.
OK.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 3/6] emacs: Make 'guix-find-location' interactive.
2016-04-04 19:47 ` [PATCH 3/6] emacs: Make 'guix-find-location' interactive Alex Kost
@ 2016-04-05 20:41 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-05 20:41 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> * emacs/guix-location.el (guix-find-location): Make interactive. Adjust
> to handle "reduced" locations (without line and column numbers).
OK.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/6] doc: emacs: Add "Locations" section.
2016-04-04 19:47 ` [PATCH 4/6] doc: emacs: Add "Locations" section Alex Kost
@ 2016-04-05 20:46 ` Ludovic Courtès
2016-04-06 9:24 ` Alex Kost
0 siblings, 1 reply; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-05 20:46 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> * doc/emacs.texi (Emacs Commands): Move description of 'guix-edit'
> command to...
> (Emacs Locations): ... here. Document 'guix-find-location'. New
> section.
> * doc/guix.texi (Top): Add it.
[...]
> +@node Emacs Locations
> +@section Locations
“Source Locations” or “Package Source Locations” or “Source of Package
Definitions”?
> +As you know, package definitions are placed in Guile files, also known
> +as @dfn{package locations}. The following commands should help you not
> +getting lost in these locations:
s/getting/get/
> +@table @kbd
> +
> +@item M-x guix-find-location
> +Find package location file (press @key{TAB} to choose a location from a
> +completion list).
Maybe “Open the given package definition source file“? (I’ve always
found the use of the word ‘find’ in Emacs to be somewhat confusing, but
maybe it’s just me.)
> +If you are contributing to Guix, you may find it useful for @kbd{M-x
> +guix-find-location} and @kbd{M-x guix-edit} to open locations from your
> +git directory. This can be done by setting @code{guix-directory}
s/git directory/Git checkout/
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 5/6] emacs: Add interface for package locations.
2016-04-04 19:47 ` [PATCH 5/6] emacs: Add interface for package locations Alex Kost
@ 2016-04-05 20:50 ` Ludovic Courtès
2016-04-06 9:23 ` Alex Kost
0 siblings, 1 reply; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-05 20:50 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> * emacs/guix-main.scm (%package-location-param-alist): New variable.
> (package-location->sexp, package-location-entries): New procedures.
> * emacs/guix-ui-location.el: New file.
> * emacs.am (ELFILES): Add it.
> * doc/emacs.texi (Emacs Locations): Document 'guix-locations'.
> * NEWS: Mention it.
> ---
> NEWS | 6 ++++
> doc/emacs.texi | 7 ++++
> emacs.am | 1 +
> emacs/guix-main.scm | 12 +++++++
> emacs/guix-ui-location.el | 83 +++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 109 insertions(+)
> create mode 100644 emacs/guix-ui-location.el
That it takes so few lines to implement this is a good sign. :-)
> +*** New Emacs interface for package locations: M-x guix-locations
s/for package locations/to navigate package definitions/ ?
> +@item M-x guix-locations
> +Display a list of package locations. You can press @key{RET} there to
Maybe “Display the list of source files that define packages.”?
Otherwise LGTM, thanks!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer.
2016-04-04 19:47 ` [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer Alex Kost
@ 2016-04-05 20:50 ` Ludovic Courtès
2016-04-08 8:40 ` Alex Kost
0 siblings, 1 reply; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-05 20:50 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> * emacs/guix-ui-package.el (guix-package-info-insert-location)
> (guix-package-info-insert-license): New procedures.
> (guix-package-info-format): Use them.
> (guix-output-info-format): Likewise.
OK!
Thank you!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
2016-04-05 20:38 ` Ludovic Courtès
@ 2016-04-06 9:20 ` Alex Kost
2016-04-15 22:23 ` Ludovic Courtès
0 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-06 9:20 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel
Ludovic Courtès (2016-04-05 23:38 +0300) wrote:
> Alex Kost <alezost@gmail.com> skribis:
>
>> * emacs/guix-main.scm (%package-location-table): New variable.
>> (package-location-table, package-locations, packages-by-location): New
>> procedures.
>> (%patterns-makers): Add 'location' search type.
>> * emacs/guix-messages.el (guix-message-packages-by-location): New procedure.
>> (guix-messages): Use it.
>> * emacs/guix-read.el (guix-package-locations)
>> (guix-read-package-location): New procedures.
>> * emacs/guix-ui-package.el (guix-packages-by-location): New command.
>> * doc/emacs.texi (Emacs Commands): Document it.
>
> [...]
>
>> +@item M-x guix-packages-by-location
>> +Display package(s) placed in the specified location.
>
> s/location/source file/ IIUC.
Actually, I don't like the name "source file" here as it sounds like it
can be an arbitrary file with packages, while it can be one of the files
recognized by 'fold-packages', i.e. "gnu/packages/…scm" or files from
GUIX_PACKAGE_PATH. I think "location" is the right term here, so what
about "location file"?
> Also, this must be a relative file name
> like “gnu/packages/emacs.scm”, not just “emacs.scm”, right? It would be
> nice to clarify this here.
Right, what about the following clarification:
--8<---------------cut here---------------start------------->8---
@item M-x guix-packages-by-location
Display package(s) placed in the specified location file. These files
usually have the following form: @file{gnu/packages/emacs.scm}, but
don't type them manually! Press @key{TAB} to complete the file name.
--8<---------------cut here---------------end--------------->8---
>> +(define %package-location-table
>> + (delay
>> + (let ((table (make-hash-table
>> + ;; Rough guess about a number of locations: it is
>> + ;; about 10 times less than the number of packages.
>> + (euclidean/ (vlist-length (package-vhash)) 10))))
>> + ;; XXX Actually, 'for-each-package' is needed but there is no such yet.
>> + (fold-packages
>> + (lambda (package _)
>> + (let* ((location (location-file (package-location package)))
>> + (packages (or (hash-ref table location) '())))
>> + (hash-set! table location (cons package packages))))
>> + #f)
>> + table)))
>
> For the record (and maybe for a future patch, because the rest of the
> file already uses the idiom above anyway),
It's not a problem, I'd like to fix it now instead of making a future
patch.
> I find it somewhat “better”
> to (1) use vhashes (easier to reason about), and (2) define lookup
> procedures instead of exposing the data structure (no need to document
> the data structure, can be changed at will, etc.).
Heh, I just like hash tables :-) Also I like to expose data structures
for efficiency. The problem (well, not really a problem) is: along with
this procedure (to get packages by location file), I need another one
(to get a list of location files).
With the top-level hash table, I call 'fold-packages' only once and then
I just use this table. With lookup procedures, 'fold-packages' has to
be called for each of them, which looks redundant to me.
I realize that what you suggest is clean and functional, but I prefer
efficiency over purity... But not in this case :-) Since there are only
2 "lookup procedures" for package locations, it's only a bit
inefficient, so I can bear it and I'm going to make the changes that you
propose, thanks!
> That is, I would rather write:
>
> (define packages-in-source-file
And again, I don't like the name 'packages-in-source-file', what about
'packages-by-location-file'? (I prefer "by" over "in" as it is already
used in other procedure names: by-regexp, by-name, by-license, etc.)
> (let ((table (delay (fold-packages
> (lambda (package table)
> (match (and=> (package-location package)
> location-file)
> (#f table)
> (file (vhash-cons file package table))))
> vlist-null))))
> (lambda (file)
> "Return the (possibly empty) list of packages defined in FILE."
> (vhash-fold* cons '() file (force table)))))
>
> WDYT?
This is great, thanks! I always forget about 'vhash-fold*'.
So, as far as I see it, another "lookup procedure" will be:
(define package-location-files
(memoize
(lambda ()
"Return the list of file names of all package locations."
(fold-packages
(lambda (package result)
(let ((file (location-file (package-location package))))
(if (member file result)
result
(cons file result))))
'()))))
OK? Or is there a better way to write it?
>> +(define (packages-by-location location)
>> + "Return a list of packages placed in LOCATION."
>> + (hash-ref (package-location-table) location))
>
> Again use “file” here since it’s a file name, not a <location> record,
> that’s expected.
> Also: “Return _the_ list”.
OK. BTW, I have always used "Return a list" in other places, so it will
break my convention :-)
--
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 5/6] emacs: Add interface for package locations.
2016-04-05 20:50 ` Ludovic Courtès
@ 2016-04-06 9:23 ` Alex Kost
2016-04-15 22:26 ` Ludovic Courtès
0 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-06 9:23 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel
Ludovic Courtès (2016-04-05 23:50 +0300) wrote:
> Alex Kost <alezost@gmail.com> skribis:
>
>> * emacs/guix-main.scm (%package-location-param-alist): New variable.
>> (package-location->sexp, package-location-entries): New procedures.
>> * emacs/guix-ui-location.el: New file.
>> * emacs.am (ELFILES): Add it.
>> * doc/emacs.texi (Emacs Locations): Document 'guix-locations'.
>> * NEWS: Mention it.
>> ---
>> NEWS | 6 ++++
>> doc/emacs.texi | 7 ++++
>> emacs.am | 1 +
>> emacs/guix-main.scm | 12 +++++++
>> emacs/guix-ui-location.el | 83 +++++++++++++++++++++++++++++++++++++++++++++++
>> 5 files changed, 109 insertions(+)
>> create mode 100644 emacs/guix-ui-location.el
>
> That it takes so few lines to implement this is a good sign. :-)
I also think so ;-)
>> +*** New Emacs interface for package locations: M-x guix-locations
>
> s/for package locations/to navigate package definitions/ ?
This is not really for "package definitions" ("M-x guix-edit" is to move
to a particular definition), but for package location files.
Also it is not just "to navigate". Opennig a location file is a smaller
feature. *Guix Package Locations* buffer can also be used to display
packages from a particular location (similar to displaying packages from
a particular generation that you can do from *Guix Generation List*
buffer).
Finally, *Guix Package Locations* buffer is useful by itself! When you
want to look at how many packages are placed in this or that location.
So I would still prefer a more general «interface for package locations».
>> +@item M-x guix-locations
>> +Display a list of package locations. You can press @key{RET} there to
>
> Maybe “Display the list of source files that define packages.”?
I prefer the term "package location" over "source file that define
packages". It looks simple and understandable to me, but if you insist,
I will change it.
--
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/6] doc: emacs: Add "Locations" section.
2016-04-05 20:46 ` Ludovic Courtès
@ 2016-04-06 9:24 ` Alex Kost
0 siblings, 0 replies; 24+ messages in thread
From: Alex Kost @ 2016-04-06 9:24 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel
Ludovic Courtès (2016-04-05 23:46 +0300) wrote:
> Alex Kost <alezost@gmail.com> skribis:
>
>> * doc/emacs.texi (Emacs Commands): Move description of 'guix-edit'
>> command to...
>> (Emacs Locations): ... here. Document 'guix-find-location'. New
>> section.
>> * doc/guix.texi (Top): Add it.
>
> [...]
>
>> +@node Emacs Locations
>> +@section Locations
>
> “Source Locations” or “Package Source Locations” or “Source of Package
> Definitions”?
I prefer "Package Source Locations".
>> +As you know, package definitions are placed in Guile files, also known
>> +as @dfn{package locations}. The following commands should help you not
>> +getting lost in these locations:
>
> s/getting/get/
OK.
>> +@table @kbd
>> +
>> +@item M-x guix-find-location
>> +Find package location file (press @key{TAB} to choose a location from a
>> +completion list).
>
> Maybe “Open the given package definition source file“? (I’ve always
> found the use of the word ‘find’ in Emacs to be somewhat confusing, but
> maybe it’s just me.)
OK. I also didn't like how Emacs uses "find", but I just got used to it.
>> +If you are contributing to Guix, you may find it useful for @kbd{M-x
>> +guix-find-location} and @kbd{M-x guix-edit} to open locations from your
>> +git directory. This can be done by setting @code{guix-directory}
>
> s/git directory/Git checkout/
Fixed, thanks!
--
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer.
2016-04-05 20:50 ` Ludovic Courtès
@ 2016-04-08 8:40 ` Alex Kost
2016-04-09 14:52 ` Ludovic Courtès
0 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-08 8:40 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel
Ludovic Courtès (2016-04-05 23:50 +0300) wrote:
> Alex Kost <alezost@gmail.com> skribis:
>
>> * emacs/guix-ui-package.el (guix-package-info-insert-location)
>> (guix-package-info-insert-license): New procedures.
>> (guix-package-info-format): Use them.
>> (guix-output-info-format): Likewise.
>
> OK!
Ahem, I've changed my mind about this one: now I think it is good to
have "Packages" button only for location. And for license(s), I prefer
to change the license button itself so that instead of browsing the
license URL, it would open *Guix License Info* buffer.
You probably don't understand what I mean. If so, well, trust me, it
will be better :-)
--
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer.
2016-04-08 8:40 ` Alex Kost
@ 2016-04-09 14:52 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-09 14:52 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> Ludovic Courtès (2016-04-05 23:50 +0300) wrote:
>
>> Alex Kost <alezost@gmail.com> skribis:
>>
>>> * emacs/guix-ui-package.el (guix-package-info-insert-location)
>>> (guix-package-info-insert-license): New procedures.
>>> (guix-package-info-format): Use them.
>>> (guix-output-info-format): Likewise.
>>
>> OK!
>
> Ahem, I've changed my mind about this one: now I think it is good to
> have "Packages" button only for location. And for license(s), I prefer
> to change the license button itself so that instead of browsing the
> license URL, it would open *Guix License Info* buffer.
>
> You probably don't understand what I mean. If so, well, trust me, it
> will be better :-)
I think I kinda understand, but yeah, I trust you. :-)
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
2016-04-06 9:20 ` Alex Kost
@ 2016-04-15 22:23 ` Ludovic Courtès
2016-04-17 7:29 ` Alex Kost
0 siblings, 1 reply; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-15 22:23 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> Ludovic Courtès (2016-04-05 23:38 +0300) wrote:
>
>> Alex Kost <alezost@gmail.com> skribis:
>>
>>> * emacs/guix-main.scm (%package-location-table): New variable.
>>> (package-location-table, package-locations, packages-by-location): New
>>> procedures.
>>> (%patterns-makers): Add 'location' search type.
>>> * emacs/guix-messages.el (guix-message-packages-by-location): New procedure.
>>> (guix-messages): Use it.
>>> * emacs/guix-read.el (guix-package-locations)
>>> (guix-read-package-location): New procedures.
>>> * emacs/guix-ui-package.el (guix-packages-by-location): New command.
>>> * doc/emacs.texi (Emacs Commands): Document it.
>>
>> [...]
>>
>>> +@item M-x guix-packages-by-location
>>> +Display package(s) placed in the specified location.
>>
>> s/location/source file/ IIUC.
>
> Actually, I don't like the name "source file" here as it sounds like it
> can be an arbitrary file with packages, while it can be one of the files
> recognized by 'fold-packages', i.e. "gnu/packages/…scm" or files from
> GUIX_PACKAGE_PATH. I think "location" is the right term here, so what
> about "location file"?
I don’t think we need to invent new phrases. :-)
>> Also, this must be a relative file name
>> like “gnu/packages/emacs.scm”, not just “emacs.scm”, right? It would be
>> nice to clarify this here.
>
> Right, what about the following clarification:
>
> @item M-x guix-packages-by-location
> Display package(s) placed in the specified location file. These files
> usually have the following form: @file{gnu/packages/emacs.scm}, but
> don't type them manually! Press @key{TAB} to complete the file name.
OK! I’d just change the first sentence to:
Display the package(s) located in the specified file.
>>> +(define %package-location-table
>>> + (delay
>>> + (let ((table (make-hash-table
>>> + ;; Rough guess about a number of locations: it is
>>> + ;; about 10 times less than the number of packages.
>>> + (euclidean/ (vlist-length (package-vhash)) 10))))
>>> + ;; XXX Actually, 'for-each-package' is needed but there is no such yet.
>>> + (fold-packages
>>> + (lambda (package _)
>>> + (let* ((location (location-file (package-location package)))
>>> + (packages (or (hash-ref table location) '())))
>>> + (hash-set! table location (cons package packages))))
>>> + #f)
>>> + table)))
>>
>> For the record (and maybe for a future patch, because the rest of the
>> file already uses the idiom above anyway),
>
> It's not a problem, I'd like to fix it now instead of making a future
> patch.
>
>> I find it somewhat “better”
>> to (1) use vhashes (easier to reason about), and (2) define lookup
>> procedures instead of exposing the data structure (no need to document
>> the data structure, can be changed at will, etc.).
>
> Heh, I just like hash tables :-) Also I like to expose data structures
> for efficiency.
Exposing data structures does not improve performance in this case.
> The problem (well, not really a problem) is: along with this procedure
> (to get packages by location file), I need another one (to get a list
> of location files).
Right, I had forgotten about that second use.
We could do something to have both lookup procedures close over the same
promise, for instance:
(define-values (lookup1 lookup2)
(let ((table (delay (fold-packages …))))
(values (lambda (x) …)
(lambda (y) …))))
This way there’s still only one ‘fold-packages’ call.
> I realize that what you suggest is clean and functional, but I prefer
> efficiency over purity... But not in this case :-)
:-)
I agree we shouldn’t end up with inefficient solutions just because it
looks nicer to the eye, but in this case I think we’re doing OK. ;-)
>> That is, I would rather write:
>>
>> (define packages-in-source-file
>
> And again, I don't like the name 'packages-in-source-file', what about
> 'packages-by-location-file'? (I prefer "by" over "in" as it is already
> used in other procedure names: by-regexp, by-name, by-license, etc.)
Fine with me, or ‘package-by-source-file’?
> So, as far as I see it, another "lookup procedure" will be:
>
> (define package-location-files
> (memoize
> (lambda ()
> "Return the list of file names of all package locations."
> (fold-packages
> (lambda (package result)
> (let ((file (location-file (package-location package))))
> (if (member file result)
> result
> (cons file result))))
> '()))))
>
> OK? Or is there a better way to write it?
This is fine.
If you choose to take the ‘define-values’ approach above, I think you
can just list they keys already in the vhash:
(define-values (package-by-something-file package-something-files)
(let* ((table (delay …))
(files (delay
(delete-duplicates
(vhash-fold (lambda (file _ result)
(cons file result))
'()
(force table))))))
(values …
(lambda () (force files)))))
>>> +(define (packages-by-location location)
>>> + "Return a list of packages placed in LOCATION."
>>> + (hash-ref (package-location-table) location))
>>
>> Again use “file” here since it’s a file name, not a <location> record,
>> that’s expected.
>> Also: “Return _the_ list”.
>
> OK. BTW, I have always used "Return a list" in other places, so it will
> break my convention :-)
No big deal, but “return a list” is imprecise IMO: it doesn’t just
return any list. But I’m nitpicking like crazy, I should stop! :-)
Thank you for your patience!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 5/6] emacs: Add interface for package locations.
2016-04-06 9:23 ` Alex Kost
@ 2016-04-15 22:26 ` Ludovic Courtès
0 siblings, 0 replies; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-15 22:26 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> Ludovic Courtès (2016-04-05 23:50 +0300) wrote:
>
>> Alex Kost <alezost@gmail.com> skribis:
[...]
>>> +*** New Emacs interface for package locations: M-x guix-locations
>>
>> s/for package locations/to navigate package definitions/ ?
>
> This is not really for "package definitions" ("M-x guix-edit" is to move
> to a particular definition), but for package location files.
>
> Also it is not just "to navigate". Opennig a location file is a smaller
> feature. *Guix Package Locations* buffer can also be used to display
> packages from a particular location (similar to displaying packages from
> a particular generation that you can do from *Guix Generation List*
> buffer).
>
> Finally, *Guix Package Locations* buffer is useful by itself! When you
> want to look at how many packages are placed in this or that location.
>
> So I would still prefer a more general «interface for package locations».
OK, to me “navigate” captures all these features, but what you suggest
is also fine with me! :-)
>>> +@item M-x guix-locations
>>> +Display a list of package locations. You can press @key{RET} there to
>>
>> Maybe “Display the list of source files that define packages.”?
>
> I prefer the term "package location" over "source file that define
> packages". It looks simple and understandable to me, but if you insist,
> I will change it.
No, I think you’re right.
Thanks!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
2016-04-15 22:23 ` Ludovic Courtès
@ 2016-04-17 7:29 ` Alex Kost
2016-04-17 15:40 ` Ludovic Courtès
0 siblings, 1 reply; 24+ messages in thread
From: Alex Kost @ 2016-04-17 7:29 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel
Ludovic Courtès (2016-04-16 01:23 +0300) wrote:
> Alex Kost <alezost@gmail.com> skribis:
[...]
>> The problem (well, not really a problem) is: along with this procedure
>> (to get packages by location file), I need another one (to get a list
>> of location files).
>
> Right, I had forgotten about that second use.
>
> We could do something to have both lookup procedures close over the same
> promise, for instance:
>
> (define-values (lookup1 lookup2)
> (let ((table (delay (fold-packages …))))
> (values (lambda (x) …)
> (lambda (y) …))))
>
> This way there’s still only one ‘fold-packages’ call.
Oh, very interesting; I didn't know about 'define-values' (shame on me),
thanks for pointing!
>>> That is, I would rather write:
>>>
>>> (define packages-in-source-file
>>
>> And again, I don't like the name 'packages-in-source-file', what about
>> 'packages-by-location-file'? (I prefer "by" over "in" as it is already
>> used in other procedure names: by-regexp, by-name, by-license, etc.)
>
> Fine with me, or ‘package-by-source-file’?
Since the package field as named 'location' I prefer
'packages-by-location-file'.
>> So, as far as I see it, another "lookup procedure" will be:
>>
>> (define package-location-files
>> (memoize
>> (lambda ()
>> "Return the list of file names of all package locations."
>> (fold-packages
>> (lambda (package result)
>> (let ((file (location-file (package-location package))))
>> (if (member file result)
>> result
>> (cons file result))))
>> '()))))
>>
>> OK? Or is there a better way to write it?
>
> This is fine.
>
> If you choose to take the ‘define-values’ approach above, I think you
> can just list they keys already in the vhash:
>
> (define-values (package-by-something-file package-something-files)
> (let* ((table (delay …))
> (files (delay
> (delete-duplicates
> (vhash-fold (lambda (file _ result)
> (cons file result))
> '()
> (force table))))))
> (values …
> (lambda () (force files)))))
Great, thanks! I'm going to use this variant. Is there a preference
for 'delete-duplicates' over this?:
(vhash-fold (lambda (file _ result)
(if (member file result)
result
(cons file result)))
'()
(force table))
--
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
2016-04-17 7:29 ` Alex Kost
@ 2016-04-17 15:40 ` Ludovic Courtès
2016-04-18 7:18 ` Alex Kost
0 siblings, 1 reply; 24+ messages in thread
From: Ludovic Courtès @ 2016-04-17 15:40 UTC (permalink / raw)
To: Alex Kost; +Cc: guix-devel
Alex Kost <alezost@gmail.com> skribis:
> Ludovic Courtès (2016-04-16 01:23 +0300) wrote:
[...]
>> If you choose to take the ‘define-values’ approach above, I think you
>> can just list they keys already in the vhash:
>>
>> (define-values (package-by-something-file package-something-files)
>> (let* ((table (delay …))
>> (files (delay
>> (delete-duplicates
>> (vhash-fold (lambda (file _ result)
>> (cons file result))
>> '()
>> (force table))))))
>> (values …
>> (lambda () (force files)))))
>
> Great, thanks! I'm going to use this variant. Is there a preference
> for 'delete-duplicates' over this?:
>
> (vhash-fold (lambda (file _ result)
> (if (member file result)
> result
> (cons file result)))
> '()
> (force table))
Both are O(n²) and have similar readability, so both are fine with me!
Ludo’.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/6] emacs: Add 'guix-packages-by-location' command.
2016-04-17 15:40 ` Ludovic Courtès
@ 2016-04-18 7:18 ` Alex Kost
0 siblings, 0 replies; 24+ messages in thread
From: Alex Kost @ 2016-04-18 7:18 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guix-devel
Ludovic Courtès (2016-04-17 18:40 +0300) wrote:
> Alex Kost <alezost@gmail.com> skribis:
>
>> Ludovic Courtès (2016-04-16 01:23 +0300) wrote:
>
> [...]
>
>>> If you choose to take the ‘define-values’ approach above, I think you
>>> can just list they keys already in the vhash:
>>>
>>> (define-values (package-by-something-file package-something-files)
>>> (let* ((table (delay …))
>>> (files (delay
>>> (delete-duplicates
>>> (vhash-fold (lambda (file _ result)
>>> (cons file result))
>>> '()
>>> (force table))))))
>>> (values …
>>> (lambda () (force files)))))
>>
>> Great, thanks! I'm going to use this variant. Is there a preference
>> for 'delete-duplicates' over this?:
>>
>> (vhash-fold (lambda (file _ result)
>> (if (member file result)
>> result
>> (cons file result)))
>> '()
>> (force table))
>
> Both are O(n²) and have similar readability, so both are fine with me!
Thanks for clarifying, I have pushed this patchset.
--
Alex
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2016-04-18 7:18 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-04-04 19:47 [PATCH 0/6] emacs: Add interface for package locations Alex Kost
2016-04-04 19:47 ` [PATCH 1/6] emacs: Add 'guix-packages-by-location' command Alex Kost
2016-04-05 20:38 ` Ludovic Courtès
2016-04-06 9:20 ` Alex Kost
2016-04-15 22:23 ` Ludovic Courtès
2016-04-17 7:29 ` Alex Kost
2016-04-17 15:40 ` Ludovic Courtès
2016-04-18 7:18 ` Alex Kost
2016-04-04 19:47 ` [PATCH 2/6] emacs: Separate package location code Alex Kost
2016-04-05 20:39 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 3/6] emacs: Make 'guix-find-location' interactive Alex Kost
2016-04-05 20:41 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 4/6] doc: emacs: Add "Locations" section Alex Kost
2016-04-05 20:46 ` Ludovic Courtès
2016-04-06 9:24 ` Alex Kost
2016-04-04 19:47 ` [PATCH 5/6] emacs: Add interface for package locations Alex Kost
2016-04-05 20:50 ` Ludovic Courtès
2016-04-06 9:23 ` Alex Kost
2016-04-15 22:26 ` Ludovic Courtès
2016-04-04 19:47 ` [PATCH 6/6] emacs: Add license/location "Packages" buttons to Info buffer Alex Kost
2016-04-05 20:50 ` Ludovic Courtès
2016-04-08 8:40 ` Alex Kost
2016-04-09 14:52 ` Ludovic Courtès
2016-04-05 20:25 ` [PATCH 0/6] emacs: Add interface for package locations Ludovic Courtès
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).