selectrum-repeat does not work well with completing-read sessions initiated via project.el's dispatch actions

Created on 27 Oct 2020  路  4Comments  路  Source: raxod502/selectrum

Using a recent-ish version of project.el, when executing project-switch-project and exiting with a project-find-file action, it is not currently possible to retrieve the project-find-file session using selectrum-repeat.

A typical backtrace looks like

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  (substring-no-properties nil)
  (setq candidate (substring-no-properties candidate))
  (prescient-remember nil)
  (selectrum-prescient--remember nil)
  (run-hook-with-args selectrum-prescient--remember nil)
  (selectrum--exit-with nil)
  (selectrum-select-current-candidate nil)
  (funcall-interactively selectrum-select-current-candidate nil)
  (selectrum-repeat)
  (funcall-interactively selectrum-repeat)
  (command-execute selectrum-repeat)

A similar problem exists when attempting to use selectrum-repeat to retrieve a projectile-find-file session initiated with projectile-commander.

All 4 comments

I can reproduce this issue when using Projectile to projectile-switch-project followed by finding a file, as you mentioned. This requires projectile-switch-project-action to be set to projectile-commander. Backtrace is just about the same, I think:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  substring-no-properties(nil)
  prescient-remember(nil)
  selectrum-prescient--remember(nil)
  run-hook-with-args(selectrum-prescient--remember nil)
  apply(run-hook-with-args selectrum-prescient--remember nil nil)
  selectrum--exit-with(nil)
  selectrum-select-current-candidate(nil)
  funcall-interactively(selectrum-select-current-candidate nil)
  call-interactively(selectrum-select-current-candidate)
  selectrum-repeat()
  funcall-interactively(selectrum-repeat)
  call-interactively(selectrum-repeat nil nil)
  command-execute(selectrum-repeat)

I can take a look at this. The problem is this-command is selectrum-select-current-candidate when selecting the project from the list of projects, and then the user gets prompted by projectile-commander. Typing a key at that prompt counts as running a command interactively, which resets the saved last command to selectrum-select-current-candidate. Presumably, some tweak is needed in the area of the code that decides whether to save the last command. I suspect we won't be able to restore a nested Projectile session like this, but at the least we should be able to restore the selection from the project list.

I spent an hour or two looking at this, and determined that it is very hard to make this work as you would expect in any nontrivial cases. The issue is that selectrum-repeat looks at the saved value of this-command to determine what command to run, and it's extremely difficult to know when it is appropriate to update this-command. For example:

  • running a top-level command: yes, update this-command
  • activating a Selectrum command such as selecting a candidate: no, don't update this-command
  • activating any other command in the minibuffer related to motion or editing: no, don't update this-command
  • running a command from the minibuffer that invokes Selectrum: yes, update this-command (but reset it to the previous value on exiting the nested Selectrum session)
  • if a command calls into Selectrum twice, the first time should update this-command, but the second one shouldn't
  • if a command calls into a non-Selectrum minibuffer session followed by Selectrum, the value of this-command has already been lost before Selectrum can get to it, necessitating the use of some kind of pre-command-hook magic

I was unable to determine any reasonable compromise that would improve the correctness of how any of these cases are handled. In the beginning, selectrum-repeat was not guaranteed to work in all cases, due to the fragility of this-command, and I think we may have to live with that (although, if anybody has ideas, please feel free to contribute). I made a somewhat unrelated change so that you at least get a better error message in the situation that you posted, but I don't have any other ideas.

Thanks for looking into this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ashton314 picture ashton314  路  12Comments

tinglycraniumplacidly picture tinglycraniumplacidly  路  13Comments

thy6 picture thy6  路  8Comments

piranha picture piranha  路  3Comments

minad picture minad  路  13Comments