1

I often have to work with multiple related projects and switching between them can become hard. I use counsel-projectile and it really makes everything easier. To be clear, I am not talking about counsel-projectile-switch-to-buffer or counsel-projectile-switch-to-project. I already use those functions and they are really useful.

What I would want is a function or a package that could display all opened projectile projects with ivy or helm and let me choose a candidate. When the candidate would be selected, the last buffer opened in that project would be opened. It would be basically a counsel-switch-buffer but with projects. If possible the last visited project would display first.

An example of this would be this package: persp-projectile, but unfortunately it does not work for me most of the times.

What I currently use is centaur-tabs and it has the function centaur-tabs-counsel-switch-group with centaur-tabs-group-by-projectile-project which is the closest thing of what I want. It only misses to place the last project on top of the candidates. But the real problem is that I don't even use the tab functionality and it makes Emacs have some small bugs sometimes (eg. hiding helm candidates on emacsclient).

So if there was a simple custom function with ivy and projectile I would really appreciate it.

[Edit]

projectile-switch-open-project does almost what I want but it triggers find-file. I would want it to just go to the last opened buffer on the project.

2
  • Maybe you can add this request as a feature enhancement to counsel-projectile as well? Aug 19, 2020 at 6:54
  • 1
    There is projectile-switch-open-project which you can use to switch between open project. You could write your own extra function to open the last open file. I'm a helm user and with helm-projectile it shows the open projects in a list.
    – Swedgin
    Aug 19, 2020 at 7:27

3 Answers 3

3

What I would want is a function or a package that could display all opened projectile projects with ivy or helm and let me choose a candidate. When the candidate would be selected, the last buffer opened in that project would be opened. It would be basically a counsel-switch-buffer but with projects. If possible the last visited project would display first.

Emacs has had rudimentary project support built-in since v25 via project.el, but it's recently seen a lot of interest and new features in v28, including project switching. The good news is you don't have to wait until v28 is released to avail of them; you can install project.el on Emacs 26 or later from GNU ELPA: http://elpa.gnu.org/packages/project.html.

Its project-switching interface revolves around the command project-switch-project (bound to C-xpp by default). Quoth its entry in the Emacs manual at (info "(emacs) Switching Projects"):

28.2.3 Switching Projects
-------------------------

‘C-x p p’
     Run an Emacs command for another project
     (‘project-switch-project’).

   Commands that operate on project files (see Project File
Commands) will conveniently prompt you for a project directory when no
project is current.  When you are inside some project, but you want to
operate on a different project, use the ‘C-x p p’ command
(‘project-switch-project’).  This command prompts you to choose a
directory among known project roots, and then displays the menu of
available commands to operate on the project you choose.  The variable
‘project-switch-commands’ controls which commands are available in the
menu, and which key invokes each command.

   The variable ‘project-list-file’ names the file in which Emacs
records the list of known projects.  It defaults to the file ‘projects’
in ‘user-emacs-directory’ (see Find Init).

This command first prompts for a project with most-recently-used-first completion. Here it is in action with Ivy:

Project directory completion

[As usual, you can of course customise this display using either built-in or Ivy-specific options.]

After selecting a project, the command dispatches on project-related commands found in the variable project-switch-commands. Here's the default set:

Default project command dispatch

For buffer switching, you can modify project-switch-commands to include the commmand project-switch-to-buffer:

(with-eval-after-load 'project
  (push '(?b "Switch buffer" project-switch-to-buffer)
        project-switch-commands))

The prompt is now:

Customised project command dispatch

Finally, project-switch-to-buffer prompts for a buffer in the selected project. Here it is in action with Ivy:

Project buffer completion

Please send any feature requests or bug reports to the Emacs developers using M-xreport-emacs-bugRET.

2

As @Swedgin said in comments projectile-switch-open-project will work without doing nothing more.

Given that you want to switch to an open project buffer, you should also customize projectile-switch-project-action accordingly with your needs, in this case I'd say it's either:

  • projectile-switch-to-buffer
  • counsel-projectile-switch-to-buffer
  • a custom function that will switch buffer to the car of projectile-project-buffer-files, which should be the last project opened buffer, corresponding to a file.

Also you can modify counsel-projectile to read open projects lists.

projectile-open-projects and projectile-relevant-open-projects returns the list of currently open projects, so ultimately it's a matter of using them as ivy-read candidates list.

Check counsel-projectile-switch-project implementation.

At first look I'd say that changing

(if counsel-projectile-remove-current-project
    (projectile-relevant-known-projects)
  projectile-known-projects)

to

(if counsel-projectile-remove-current-project
    (projectile-relevant-open-projects)
  (projectile-open-projects))

Will do the core of it, but cannot test it right now, neither giving it the finishing touches to make it play well without losing the original behavior.

I - or someone else - will extend the response later.

2
  • This does almost what I want but it triggers find-file instead of focusing the last opened buffer in the project that is the only problem. Is there a way to modify the function so it does that?
    – sigan
    Aug 19, 2020 at 13:46
  • I've added to response addressing that. Sorry to not providing code for the custom function, available time is very scarce lately. Hope someone else can fill the gap quicker than me.
    – Muihlinn
    Aug 20, 2020 at 9:00
1

Try this.

(defun smart-switch-project ()                                                                                                                                                                                     
  "Open latest edited buffer when switched the  exist project, find files when switched to a new project."                                                                                                         
  (if  (null (projectile-project-buffer-files ))                                                                                                                                                                   
    (projectile-find-file)                                                                                                                                                                                         
    (switch-to-buffer (get-buffer (car (projectile-project-buffer-files)))))                                                                                                                                       
)                                                                                                                                                                                                                  
(setq projectile-switch-project-action 'smart-switch-project)  

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.