reddit / emacs

How to open a file given by enviroment variable

Kr1ot · 2022-10-11 12:56
Hi, I binded a function [open-file-at-cursor](http://xahlee.info/emacs/emacs/emacs_open_file_path_fast.html). This allows me to open the file directly from a file (given I've written down the correct path). Now, I want to use something like this where I can give the file paths as environment variable. I've been struggling but couldn't find anything related to this. Please help! Edit: Noting down the use case for this Let's assume we have a file in path - /home/user/dir1/dir2/file.txt I've set some env variable $TEST=/home/user/dir1 In some other file (let's name it file2.f under dir2), I've mentioned following two lines: ../file.txt $TEST/dir2/file.txt With the "open-file-at-cursor" bind, I'm able to directly open a file.txt when my cursor is on 1st line. However, the same bind breaks down for line 2. I'm expecting both lines to open the same file. ffap does not solve my issue as it opens the final directory that holds my file(this will increase my keystrokes). Thanks
deaddyfreddy · 2022-10-11 14:16
`substitute-in-file-name` > I binded a function open-file-at-cursor what's wrong with `ffap`, btw? seems like it already uses the function I mentioned
howardthegeek · 2022-10-11 14:19
Can you give us more details of what you're looking for? For instance did you want to have the environment variable with a list of paths, and have it searched in each one? Do you want to modify the original code, or use it as is? Most file operations in Emacs read from the variable, default-directory, so you could use let to change that variable temporarily to the value from a call to getenv, and then call Xah's original function.
Bu156 · 2022-10-11 14:21
If you want to open a file directly by environment variables, for example the variable `$MY_FILE` that should be pretty simple, something like this should do the trick: (defun open-file-from-env (env-var) (interactive `(,(read-string "Enter variable name: "))) (find-file (getenv env-var))) Then just type `MY_FILE` and it should be opened. Hope this helps!
Kr1ot · 2022-10-11 17:03
Just curious, substitute-in-file-name asks me for the file name under the directory, just like ffap, right? The reason I went with this bind is because it allows me to directly open a file specified without prompt. And incase the file does not exist in that path I can create if required. It has been pretty helpful for me (the keystrokes have reduced). However, this bind does not work with env variables :(
Kr1ot · 2022-10-11 17:11
I'll note a simple use case: Let's assume we have a file in path - /home/user/dir1/dir2/file.txt I've set some env variable $TEST=/home/user/dir1 In some other file (let's name it file2.f under dir2), I've mentioned following two lines: ../file.txt $TEST/dir2/file.txt With the "open-file-at-cursor" bind, I'm able to directly open a file.txt when my cursor is on 1st line. However, the same bind breaks down for line 2. I'm expecting both lines open the same file. ffap does not solve my issue as it opens the final directory that holds my file(this will increase my keystrokes). ​ >Most file operations in Emacs read from the variable, default-directory, so you could use let to change that variable temporarily to the value from a call to getenv, and then call Xah's original function. I'm really sorry, I do not know how to do this.
Kr1ot · 2022-10-11 17:20
I guess this function will then ask me to manually input the environment variable. Is there a way emacs can automatically identify the environment variable name?
Bu156 · 2022-10-11 17:22
I might be able to write some code for it later but the gist would be the same as open-file-at-cursor, but identifying the parts which contain `$` and running `(getenv)` on them
Kr1ot · 2022-10-11 17:24
Thanks for the help! I'm really weak in emacs coding, however I'll try to implement the case you explained.
deaddyfreddy · 2022-10-11 17:36
`M-x describe-function RET ffap RET` (actually, it works for all functions, also in addition to docs it has hyperlinks to the source code). > the keystrokes have reduced related https://xkcd.com/1205/
00-11 · 2022-10-11 17:40
Doesn't regular `find-file` do that - expand env vars? It does for me, with `emacs -Q`. E.g., `C-x C-f $HOME RET`.
arthurno1 · 2022-10-11 19:04
> Doesn't regular find-file do that - expand env vars? It does. If Op is asking for only the simple case of expanding an environment variable only, or at the beginning or ending of the path, your answer should be the best one in the thread. However, it does not allow for combining envs in the middle of the path. Something like this does not work (for me at least): export REPOS=repos For me, if I try the path /home/arthur/$REPOS/some-project in find-file, it expands to /repos only. The expansion is done after the slash is typed. But /home/arthur/$REPOS works. I don't know if it is possible to suppress the expansion, or if there is some other function that expands paths after the path is typed completely. I guess I could hack find-file, but I am too lazy, I don't think this is something super useful in general case.
howardthegeek · 2022-10-11 19:22
Ah, it doesn't appear that Xah's code parses the `$TEST` aspect of that string to lookup an environment variable to replace it. To get this working, you would need to edit that Lisp code. Assuming that `TEST` was an environment variable set before starting Emacs, or you ran the Lisp code: (setenv "TEST" "/home/user/dir1") As mentioned in the other comments, you could update the `find-file` function calls in Xah's code with a call to `substitute-in-file-name` (or if you want even more interesting features, call `eshell-command`). Both of these are built-in Emacs function that expands `$XXX` variables), so something like: (find-file (substitute-in-file-name $fpath)) Keep in mind that Xah likes to use dollar signs in his variable names, but Lisp doesn't do anything special with a `$` character.
rswgnu · 2022-10-11 22:06
Just install the Hyperbole package, type a path with env variables anywhere in it, press M-RET with point anywhere within the path and Hyperbole will open it, including displaying in external programs based on file type and operating system in use. You may have to use ${VAR} format for the variable. If you want to use that capability elsewhere, {C-h A} at the same point shows you what M-RET runs when pressed there.
Bodertz · 2022-10-11 23:08
Came here to say the same. Hyperbole is a big package that does a bunch of other things, but you can mostly just ignore things that aren't useful for you. >If you want to use that capability elsewhere, {C-h A} at the same point shows you what M-RET runs when pressed there. I hadn't heard of that keybinding. Is there a use for `C-u M-RET` when `C-h A` seems to do almost the same thing?
rswgnu · 2022-10-12 10:43
Although {C-u M-RET}, the Assist Key, often shows help for the context like {C-h A} always does, in some contexts it performs an action complementary to the Action Key, {M-RET} binding. For example, at the end of lines, the Action Key puts the line at point/mouse-point at the top of the window and the Assist Key moves it to the bottom. {C-u C-h A} of course shows what the Assist Key does in a context.
Kr1ot · 2022-10-12 16:18
This definitely works if I was to manually find a file. However, in my case I have a file that contains path of all the files that I would be using. If I ever want to traverse to any of the file, I would just use the bind "open-file-at-cursor". This would directly open the file. But I'm facing issues if the file path is mentioned with environment variable.
Kr1ot · 2022-10-12 16:56
Thanks for the help. I was not able to try this out as the emacs version on my machine is 23.0 and hyperbole requires 27.0. Is there any other method to do the same?
Kr1ot · 2022-10-12 17:26
>you could update the find-file function calls in Xah's code with a call to substitute-in-file-name One question, do I have to replace `find-file` function with `substitute-in-file-name` or write it like `(find-file (substitute-in-file-name $fpath))`? And do I have to perform this operation for all the instances of `find-file`?
Kr1ot · 2022-10-12 19:49
>substitute-in-file-name Tried working with ffap. It somehow works only when I have either environment variable in the path or a relative path. It breaks when I have both env variable and path : for ex - `$TEST/dir2/file.txt`. It then just searches in the root directory.
Bodertz · 2022-10-12 20:03
Thanks.
deaddyfreddy · 2022-10-13 08:01
works for me, does your file exist at all?