Okay, let me share a bit of the process of arriving at the solution to Question #1 (which should also resolve #2).
I'm going to assume you know Emacs key notation and at least a little about Elisp.
TL;DR
It's hard. :)
Research
First, let's think a bit. helm-projectile-find-file
is definitely calling find-file
or some similar function at some point. You want to substitute elscreen-find-file
for whatever helm-projectile-find-file
is using by default. With this in mind, it's time to determine what helm-projectile-find-file
actually does.
C-h f helm-projectile-find-file
RET
You should be met with the following:
helm-projectile-find-file is an interactive compiled Lisp function in
helm-projectile.el
.
(helm-projectile-find-file &optional ARG)
Use projectile with Helm for finding files in project
With a prefix ARG
invalidates the cache first.
Navigate over to the helm-projectile.el
and press RET
You'll be met with the following message:
Unable to find location in file
This is bad news. This means that the function you're looking for was generated using some form of metaprogramming, and the literal definition of the function is not available.
In this instance, I'd recommend reading the whole file. Yes, I understand you're new to Elisp, and most of it will not make sense (esp. since Helm source is particularly difficult Elisp). But, thankfully, there are provisions to help you understand:
- Docstrings
- Function and variable names
After plugging through the whole file and reading these, you should have a decent idea of what should be doing what. You might even have determined that the variable helm-projectile-file-actions
is what's controlling the actions that helm-projectile-find-file
takes after you select a file.
The definition of helm-projectile-file-actions
is a bit involved, but you can skip right to the important stuff (i.e. the actual value it holds) by doing
C-h v helm-projectile-file-actions
RET:
Value:
(("Find File" . helm-find-file-or-marked)
("Find file in Dired" . helm-point-file-in-dired)
("View file" . view-file)
("Checksum File" . helm-ff-checksum)
...
("Add files to Dired buffer `C-c a'" . helm-projectile-dired-files-add-action))
(Ellipses mine)
This is a list of conses. The first element of each pair is clearly a string. After a few C-h fs you can determine that the second element of each pair is a function. You can probably also guess that the first element of the list is the one that is executed when you press RET during a helm session.
You can check your guess with M-x debug-on-entry
RET helm-find-file-or-marked
RET. Now attempt to open a file with helm-projectile-find-file
, and you'll be greeted by the Emacs debugger (a topic for another time, I'm afraid), signaling that that was indeed the function that was run. q to quit the debugger. To clear the instrumentation, repeat the process with cancel-debug-on-entry
instead of debug-on-entry
.
Alright. C-h f helm-find-file-or-marked
RET and skip straight to the source. You'll be greeted by a long and complicated function. However, you don't necessarily need to read the entire function, you just need to know what you're looking for: something to do with find-file
.
32 lines down the function you'll see this:
(mapc 'find-file-noselect (cdr marked))
(find-file (car marked))
This code is run when you select multiple helm candidates at once, using C-SPC.
44 lines down the function you'll also see this:
(find-file-at-point
<confusing garbage here>)
This code is run when you are acting on only one candidate.
Both find-file
and find-file-at-point
are essentially synonymous in this usage. They both represent the point where helm hands the file path off to Emacs builtins to actually open the file.
Execution
Copy the entire helm-find-file-or-marked
definition into your init file, rename it my/helm-elscreen-find-file-or-marked
and replace both find-file
and file-file-at-point
with elscreen-find-file
. (find-file-noselect
as well, depending on what you're trying to achieve)
Now, you've produced a helm action function that opens the given candidate with elscreen-find-file
. The next step is to climb back up the levels of abstraction, and make a helm command that uses this function.
You're going to need to go back to helm-projectile.el
. Let me just extract the relevant bits here:
(defvar helm-source-projectile-files-list
(helm-build-in-buffer-source "Projectile files"
:data (lambda ()
(condition-case nil
(projectile-current-project-files)
(error nil)))
:fuzzy-match helm-projectile-fuzzy-match
:coerce 'helm-projectile-coerce-file
:keymap helm-projectile-find-file-map
:help-message 'helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action helm-projectile-file-actions
)
"Helm source definition for Projectile files.")
(defvar helm-source-projectile-files-and-dired-list
'(helm-source-projectile-dired-files-list
helm-source-projectile-files-list))
(helm-projectile-command "find-file" helm-source-projectile-files-and-dired-list "Find file: ")
Now what are you going to need to do?
- Create a new source
my/helm-source-projectile-elscreen-files-list
, using our new action
- Create a new
helm-projectile
command with that source
1.
(defvar my/helm-source-projectile-elscreen-files-list
(helm-build-in-buffer-source "Projectile files"
:data (lambda ()
(condition-case nil
(projectile-current-project-files)
(error nil)))
:fuzzy-match helm-projectile-fuzzy-match
:coerce 'helm-projectile-coerce-file
:keymap helm-projectile-find-file-map
:help-message 'helm-ff-help-message
:mode-line helm-read-file-name-mode-line-string
:action (cons my/helm-elscreen-find-file-or-marked
helm-projectile-file-actions))
"Helm source definition for Projectile files.")
2.
(helm-projectile-command "elscreen-find-file" 'my/helm-source-projectile-elscreen-files-list "Find file in projects (elscreen): " t)
I've created a gist will the finished code.
Disclaimer
There are more efficient ways to do this. Namely, instead of copying the definition of helm-find-file-or-marked
, you could instead override the functions programmatically using cl-letf
, like so:
(defun my/helm-elscreen-find-file-or-marked (candidate)
(cl-letf (((symbol-function #'find-file) #'elscreen-find-file)
((symbol-function #'find-file-noselect) #'elscreen-find-file)
((symbol-function #'find-file-at-point) #'elscreen-find-file))
(helm-find-file-or-marked)))
However, this is reasonablely advanced ELisp.
This thing is long, and probably contains errors. But I'm hoping there will be at least a few useful tidbits that will help you understand how I produced my answer, and how you can go about answering some of your questions in the future.
Keep at it and don't give up! :)
helm-projectile-find-file
doesn't return a buffer, not likefind-file-noselect
in the originalelscreen-find-file
, whileelscreen-find-and-goto-by-buffe
needs buffer as its 1st argument, so your version didn't work. About question 2, it seems there is already an action ("Find file other windowC-c o
") for that, maybe you want give it a try. BTW, I don't use elscreen, so I might misunderstand you.