Sort issues by created date like github web ui
ParetoOptimalDev opened this issue · comments
Is your feature request related to a problem? Please describe.
The issues listed are different than what they would be in the web ui. Maybe in the future I wouldn't consider this an issue, but it seems like I'll have less issues if issues are ordered the same way for me using an emacs client as coworkers using the github web ui.
Describe the solution you'd like
Sorting to be done by created date like the github web ui.
Additional context
I already use the following advice to achieve this:
(defun my/consult-gh--search-issues (search &optional repo)
"Search for repos with \"gh search repos\" and return a list of items each formatted with properties to pass to consult."
(let* ((maxnum (format "%s" consult-gh-issue-maxnum))
(state consult-gh-issues-state-to-show)
(repo (or repo ""))
(sort "created")
(issuelist (if (equal state "all")
(or (string-join `(,(consult-gh--command-to-string "search" "issues" search "--repo" repo "--limit" maxnum "--sort" sort "--state" "open") ,(consult-gh--command-to-string "search" "issues" search "--repo" repo "--limit" maxnum "--sort" sort "--state" "closed")) "\n") "")
(or (consult-gh--command-to-string "search" "issues" search "--repo" repo "--limit" maxnum "--sort" sort "--state" state) "")))
(issues (mapcar (lambda (s) (string-split s "\t")) (remove "" (split-string issuelist "\n")))))
(remove ":" (remove "" (mapcar (lambda (src) (propertize (concat (cadr src) ":" (cadr (cdr (cdr src)))) ':issue (string-trim (cadr src) "#") ':repo (car src) ':status (cadr (cdr src)) ':description (cadr (cdr (cdr src))) ':tags (cadr (cdr (cdr (cdr src)))) ':date (cadr (cdr (cdr (cdr (cdr src))))))) issues))
)
))
(defun my/consult-gh-search-issues (&optional repos search)
"Runs the interactive command in the minibuffer that queries the user for name of repos in the format `OWNER/REPO` e.g. armindarvish/consult-gh as well as a string as search term and returns the list of searhc matches for the string in issues of thae repos for further actions such as viewing in emacs or the browser.
The user can provide multiple repos by using the `consult-gh-crm-separator' similar to how `crm-separator' works in `completing-read-multiple'. Under the hood this command is using `consult' and particularly `consult--multi', which in turn runs macros of `completing-read' and passes the results to the GitHub command-line tool `gh` (e.g. by runing `gh search issues string --repo name-of-the-repo`) to search the issues for particular repositories and shows them back to the user.
It uses `consult-gh--make-source-from-search-issues' to create the list of items for consult and saves the history in `consult-gh--issues-history'. It also keep tracks of previously selected repos by the user in `consult-gh--known-repos-list' and offers them as possible entries in future runs of `consult-gh-search-issues'."
(interactive)
(setq consult-gh--issues-history (mapcar (lambda (item) (consult-gh--output-cleanup (format "%s" item))) consult-gh--issues-history))
(let* ((crm-separator consult-gh-crm-separator)
(repos (or repos (consult-gh--read-repo-name)))
(search (or search (read-string "Search Term: ")))
(candidates (consult--slow-operation "Collecting Issues ..." (mapcar (lambda (repo) (consult-gh--make-source-from-search-issues search repo)) repos))))
(if (not (seq-empty-p (remove nil (mapcar (lambda (cand) (plist-get cand :items)) candidates))))
(progn
(setq consult-gh--known-repos-list (append consult-gh--known-repos-list repos))
(consult--multi candidates
:prompt "Select Issue(s): "
:require-match t
:sort nil
:group #'consult-gh--issue-group
:history 'consult-gh--issues-history
:category 'consult-gh-issues
:preview-key consult-gh-preview-key
)
)
(message (concat "consult-gh: " (propertize "no issues matched your search!" 'face 'warning))))
))
(advice-add 'consult-gh--search-issues :override 'my/consult-gh--search-issues)
(advice-add 'consult-gh-search-issues :override 'my/consult-gh-search-issues)
@ParetoOptimalDev Sorting is a personal preference, and therefore I did not think it would be a good idea to hard-code it, especially because when there is a limit to number of results shown, forcing a particular sorting might not be a good idea. Of course, each user can choose to use advice like you did to get their desired behavior.
That said, I am working on a major upgrade, which will use consult-async and would allow sorting issues on the fly using command-line arguments. My early prototypes are ready and if everything goes as planned, it would be ready in a few weeks. That will then address this issue and add much more capabilities to consult-gh.
In the meanwhile, I suggest you use the advice you have.
By the way, your advice for consult-gh-search-issues
is unnecessary because you are not changing that function and if you are defining a new function with "my/" prefix, then why bother making advices? Also, if I were you I would change my advice function and make it more dynamic, so I could pass other sorting options to it (or if you want to access to options other than sorting you can even use a &rest args
). Then you can make wrapper functions for them and bind them to keybindings.
Here is a quick and dirty implementation, and you then you run M-x my/consult-gh-search-issues-sort-created
(defun my/consult-gh--search-issues (search &optional repo &rest args)
"Search for repos with \"gh search repos\" and return a list of items each formatted with properties to pass to consult."
(print (apply #'append args))
(let* ((maxnum (format "%s" consult-gh-issue-maxnum))
(state consult-gh-issues-state-to-show)
(repo (or repo ""))
(sort "created")
(cmd (append (list "search" "issues" search "--repo" repo "--limit" maxnum "--state" "open") (apply #'append args)))
(issuelist (if (equal state "all")
(or (string-join `(,(apply #'consult-gh--command-to-string cmd) ,(apply #'consult-gh--command-to-string cmd)) "\n") "")
(or (apply #'consult-gh--command-to-string cmd args) "")))
(issues (mapcar (lambda (s) (string-split s "\t")) (remove "" (split-string issuelist "\n")))))
(remove ":" (remove "" (mapcar (lambda (src) (propertize (concat (cadr src) ":" (cadr (cdr (cdr src)))) ':issue (string-trim (cadr src) "#") ':repo (car src) ':status (cadr (cdr src)) ':description (cadr (cdr (cdr src))) ':tags (cadr (cdr (cdr (cdr src)))) ':date (cadr (cdr (cdr (cdr (cdr src))))))) issues))
)
))
(defun my/consult-gh--make-source-from-search-issues (search &optional repo &rest args)
"Create a source for consult from the issues retrieved by fetching all the issues of the `repo` from GitHub by using `consult-gh--issue-list' which in turn uses `gh search issues --repo name-of-the-repo`. This is used by the interactive command `consult-gh-issue-list'.
For more info on consult dources see `consult''s manual for example documentaion on `consult--multi' and `consult-buffer-sources'."
(let ((repo (or repo "")))
`(:category 'consult-gh-issues
:items ,(my/consult-gh--search-issues search repo args)
:face 'consult-gh-default-face
:action ,(funcall consult-gh-issue-action)
:annotate ,(consult-gh--issue-annotate)
:state ,(and consult-gh-show-preview #'consult-gh--issue-preview)
:default t
:history t
:sort t
)))
(defun my/consult-gh-search-issues-sort-created (&optional repos search)
"Runs the interactive command in the minibuffer that queries the user for name of repos in the format `OWNER/REPO` e.g. armindarvish/consult-gh as well as a string as search term and returns the list of searhc matches for the string in issues of thae repos for further actions such as viewing in emacs or the browser.
The user can provide multiple repos by using the `consult-gh-crm-separator' similar to how `crm-separator' works in `completing-read-multiple'. Under the hood this command is using `consult' and particularly `consult--multi', which in turn runs macros of `completing-read' and passes the results to the GitHub command-line tool `gh` (e.g. by runing `gh search issues string --repo name-of-the-repo`) to search the issues for particular repositories and shows them back to the user.
It uses `consult-gh--make-source-from-search-issues' to create the list of items for consult and saves the history in `consult-gh--issues-history'. It also keep tracks of previously selected repos by the user in `consult-gh--known-repos-list' and offers them as possible entries in future runs of `consult-gh-search-issues'."
(interactive)
(setq consult-gh--issues-history (mapcar (lambda (item) (consult-gh--output-cleanup (format "%s" item))) consult-gh--issues-history))
(let* ((crm-separator consult-gh-crm-separator)
(repos (or repos (consult-gh--read-repo-name)))
(search (or search (read-string "Search Term: ")))
(candidates (consult--slow-operation "Collecting Issues ..." (mapcar (lambda (repo) (my/consult-gh--make-source-from-search-issues search repo)) repos))))
(if (not (seq-empty-p (remove nil (mapcar (lambda (cand) (plist-get cand :items)) candidates))))
(progn
(setq consult-gh--known-repos-list (append consult-gh--known-repos-list repos))
(consult--multi candidates
:prompt "Select Issue(s): "
:require-match t
:sort nil
:group #'consult-gh--issue-group
:history 'consult-gh--issues-history
:category 'consult-gh-issues
:preview-key consult-gh-preview-key
)
)
(message (concat "consult-gh: " (propertize "no issues matched your search!" 'face 'warning))))
))
@ParetoOptimalDev I just pushed all the new changes to main, so now with the new version, you can dynamically add command line arguments. Give it a try and Have fun!
Closing this issue now.
Yes, I'm now able to do:
Then this:
M-x consult-gh-search-prs
haskell -- --repo nixos/nixpkgs --sort created --order desc --state open
RET
Returns:
NixOS/nixpkgs
260138:haskell.compiler.ghc98: init at 9.8.1 OPEN 2023-10-10 6.topic: haskell, 8.has: package (new... NixOS/nixpkgs
260079:haskell.packages.ghc96.tls: fix missing LLVM tools on aarch64 OPEN 2023-10-09 6.topic: haskell, 10.rebuild-darwin: ... NixOS/nixpkgs
259655:haskellPackages.hledger-iadd: unmark broken OPEN 2023-10-08 6.topic: haskell, 8.has: package (new... NixOS/nixpkgs
259075:Enhance nano syntax highlighting OPEN 2023-10-04 6.topic: nixos, 8.has: module (update... NixOS/nixpkgs
259060:haskellPackages: update stackage and hackage OPEN 2023-10-10 6.topic: haskell, 8.has: package (new... NixOS/nixpkgs
Which is equivalent to the same search on github.
It should be possible to write a simpler version of my/consult-gh-search-issues-sort-created
above using consult-gh-search-prs
or it's underlying function.
I suppose I need a modified builder that supplies those default postfix parameters.
Okay I figured it out, perhaps not the best way but it works:
(defun add-args-to-builder (builder args)
(let* ((builder-result (funcall builder "foo"))
(my-args args))
(cons (append (car builder-result) my-args) (cdr builder-result))))
(defun my/consult-gh-list-issues/nixos/nixpkgs ()
(interactive)
(let ((args '("--sort" "created" "--repo" "nixos/nixpkgs" "--state" "open")))
(consult-gh--async-search-issues "Search Issues: "
(lambda (input)
(add-args-to-builder 'consult-gh--search-issues-builder args)))))
@ParetoOptimalDev Yes indeed there are better wys to implement that.
1- The simplest way is to use the initial arg of consult-gh-search-issues
. like this:
(defun my:consult-gh-list-issues/nixos/nixpkgs ()
(interactive)
(consult-gh-search-issues "nixos/nixpkgs -- --sort created --state open"))
This way you can further edit the arguments.
2- If don't want to see the extra args when you run that function, then you can try this:
(defun my:consult-gh-list-issues/nixos/nixpkgs ()
(interactive)
(let ((consult-gh-args (append consult-gh-args '("--sort" "created" "--state" "open"))))
(consult-gh-search-issues "nixos/nixpkgs")))