reddit / emacs

Suggestions on remote work with LSP? How do you do it?

XtremePocket · 2022-03-27 15:45
So this is a very open question about emacs workflow with remote work. I’m sharing my thoughts here because I’m stuck and am looking for some useful ideas. It’s more like a very long mumble that you can respond to. There will be no right answers, and please let me know what you think of each of the ideas here! Background: I do a lot of machine learning and data analysis, which means I have to use python and R on remote servers a lot. I’ve been trying to find a good workflow from my laptop in emacs. These servers usually have very different dependencies from my laptop since they have GPUs. For example, pytorch, a machine learning learning library, uses different versions for machines with and without GPU. This makes direct sharing of virtual environments or poetry projects difficult. Here are a few things I’ve been trying/planning to try: 1. Tramp + remote lsp server (pyright-remote) + Anaconda mode Theoretically, this will give the perfect remote development experience. Anaconda mode can connect to the remote conda and use the environments stored in there, which will tell the lsp on remote server to use the correct interpreter, which theoretically is equivalent to developing with ssh on the remote server. However, I’ve encountered multiple issues with this approach. First of all, our remote machine uses a system called slurm which assigns GPUs to you only if you ask. My tramp wasn’t smart enough to do this, and thus doesn’t load the drivers for GPU, and thus language server can’t be started because of the missing dependencies. The second, and most annoying, issue is that I just can get lsp and anaconda to work remotely. There have been many posts in this community trying to get either of them working, and I haven’t been successful on this end either. 2. Poetry/conda + ssh-deploy This is pretty self-explanatory - link the file system and develop on local. Sync the virtual environment so we have the correct packages. But, as I alluded to, the issue with this is that my laptop doesn’t have gpu and thus misses some important dependencies necessary for replicating the environment on remote machine. If you were me, what would you do? I’m totally open to other methods of providing lsp-like services, as long as they have features including definition lookup, (preferably) type hint, completion, doc lookup, (preferably) renaming.
snippins1987 · 2022-03-27 16:48
Maybe creating a bash script on the remote server that ask for gpu and only end start the lsp-server? Then you can change the path where emacs find the remote lsp server. #!/usr/bin/env bash #SBATCH --account=def-someuser #SBATCH --gres=gpu:1 # Number of GPU(s) per node #SBATCH --cpus-per-task=6 # CPU cores/threads #SBATCH --mem=4000M # memory per node #SBATCH --time=0-03:00 # time (DD-HH:MM) export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK exec /path/to/lsp-server-binary "$@"
nnreddit-user · 2022-03-27 16:52
I surrendered after dashing several vessels on this rocky shore. I'll quote the SLURM guide: >the quickest and most efficient is to learn how to use a terminal-based editor such as Vim, Emacs, or Nano... This means making do with whatever the cluster offers after `srun --pty bash`. Attempting anything fancier involves too many moving parts. When it comes to running experiments *en masse* you really want absolutely nothing between your code and the environment it's going to run in.
flagos · 2022-03-27 19:56
I'm launching emacs on the server, in no window mode. You can have it inside a screen/tmux session so that it's persisted even though you disconnect. That's my workflow for the last 5 years, working pretty well.
XtremePocket · 2022-03-27 19:58
Thanks. This is good suggestion. Emacs was installed on our server and works perfectly with no window, I guess my integration-hungry brain just really wanted to ask "what if I can do ALL things from here..."
XtremePocket · 2022-03-27 20:01
This does look helpful. How would you run this? I'm guessing adding to something like .zshrc and so it autoloads after connection? I'm not very familiar with how slurm works under the hook, but will this make sure emacs (or rather tramp) get these same resources?
XtremePocket · 2022-03-27 20:04
True. This is what I usually do as well. I was just hoping for a magical workflow where I can seamlessly transition from remote projects to my org-roam paper noting session. Perhaps I'm too greedy to want all of these plus a perfect editing experience! XD
da-g · 2022-03-27 20:34
Honestly, this is a great question. I've tried many different approaches through the years, and they all have drawbacks. My solution right now isn't perfect, but it's the best I've had so far with emacs + python + org-mode. I use jupyter-emacs to start remote kernels via ssh. I can then either develop stuff locally and associate the local files/project to the remote kernel using jupyter-repl-associate-buffer, or develop remote files. I can even mix and match so it doesn't really matter where the code lives and where I want it executed, jupyter-emacs allows me to coordinate that at will - and it's easy to have multiple frames with different kernels running at different remotes. Integration with org-mode is a free lunch. Drawback is that there is no lsp integration, and I don't see an easy way to get that going either. Jupyter-emacs is also a one person show, and even though the code is readable, it requires fluency in both emacs and jupyter, so its hard to fix bugs without help from the maintainer. With that said, if I would start from scratch today, I'd probably pick up neovim instead of Emacs and run it in headless mode on the remote under tmux and then connect to it over a tcp socket using neovide. Problem is that's vim, and I'm sure there are massive drawbacks there too that I don't even know exist. And there is no real org mode impl, which sucks. Running emacs in terminal mode is a PITA because of conflicting keybindings with terminal emulators.
wargxs · 2022-03-27 21:08
I think you can tell tramp to keep the remote path and also tell it to always start a login shell. This should give you then the same environment as when you login (bash -l …). Eglot works well with tramp, I don’t need anaconda mode. https://www.gnu.org/software/tramp/#Remote-programs
XtremePocket · 2022-03-27 22:21
[Org-lsp](https://emacs-lsp.github.io/lsp-mode/manual-language-docs/lsp-org/) has just got into alpha! With some tweaking maybe you could use python lsp even in org mode? But yeah, I think using remote kernels is a great remedy to the issues I stated above. However, most of my projects involve more structured code and thus Jupyter's script-style doesn't really work for me. Neovide looks interesting though - do you know if it's truly UI, e.g. can it do things like pdf-tools in emacs? I came from vim, disappointed in the lack of its integrations in academic productivity tools like org-roam and such (The other reason is that I find vim to be too easy to install and thus my config files are literally all over the place. Small point but really annoying at times).
MistakeNotDotDotDot · 2022-03-27 22:44
This is part of why I use emacs. I can use 95% of the same stuff on any server, just copy my .emacs.d, wait for straight.el to install everything, and go. (The other 5% is stuff that uses child frames that obviously don't make sense in a TUI.) Was great when I had a job with a "no code leaves your work desktop ever, even on your work laptop if WFH" policy.
justin473 · 2022-03-28 01:53
Use local X server and use X11 remotely. That technically does answer your question about how to do “remote work”.
snippins1987 · 2022-03-28 05:51
As I understand, your problem is that the lsp-server can't be start because you would need to run some slurm commands first to ask for resources. My solution for that is to write a wrapper script on the remote server for the lsp-server binary. Tramp doesn't need to know anything slurm, this is more of a problem about how the lsp server binary is started, it might be the problem of some environment variables is not being set, or in this case it's about hardware access with slurm. For example, if you set some environment variables in the remote machine ~/.bashrc, the lsp server started remotely by your local Emacs won't be able to see them, because the command that used to start the server doesn't source ~/.bashrc at all. In short, you will need to create a new script with the content similar to the above, where you replace the slurm commands that you use before the "exec" line, plus other setup about environment variables and enter the actual lsp-server binary location on the remote server. Don't forget to do "chmod +x" on the script afterward. If you don't know what slurm commands to use, and it is somebody else that set it up for you, you might want to check the content of "~/.bashrc" or "~./profile" on the remote server. At some point in your login process slurm commands must have been ran. Then go to your init.el and change the path of the remote server lsp-server binary to the path of the script you created.
astoff1 · 2022-03-28 09:00
> I use jupyter-emacs to start remote kernels via ssh. I can then either develop stuff locally and associate the local files/project to the remote kernel using jupyter-repl-associate-buffer, or develop remote files. This is a good suggestion. The built-in Python shell also supports this approach, and in Emacs 28 some of the rough edges have been fixed. This means you can `cd` to the remote server, and `M-x run-python` from there. Evaluating regions of code from a local file now does what you expect, namely, the code is sent to the remote machine. > Drawback is that there is no lsp integration, and I don't see an easy way to get that going either. This is very simple, no? Install the LSP server locally, install the dependencies (including, say the CPU-only version of PyTorch), and edit the code locally. Then use rsync before running the code remotely.
da-g · 2022-03-28 16:38
Wow, glad to hear the built-in Python shell supports that now! Thanks for the info! What attracted me to jupyter-emacs was both the ease of use to open remote kernels and the custom shell which supports inline images. I don't think the native shell could handle that back when I last checked. Hopefully it will soon. I'd love for things to just work with Emacs only and no extra packages. That'd be the dream. Also my use case is that my datasets are very large, so I can't really test out code locally, except for a couple of small examples. I also find it hard to deal with file paths when rsyncing, because paths to datasets differ between local and remote, so rsync wouldn't work out of the box. I wonder how other people handle that. Finally, I'm sure I could get some sort of LSP to work, but I never liked lsp-mode because it's always been buggy and slow on my end. I believe it's because of my config, and not lsp-mode itself. Maybe one day I'll look into it again.
da-g · 2022-03-28 16:51
Oh I think the name may be misleading. Jupyter-emacs runs a python kernel on the remote, so you edit python files normally with a repl on the side (which supports inline images). No need for org mode nor notebooks at all! Support for org mode comes through org-babel, in which case the org-blocks would get sent to a remote kernel too, but that is not a requirement. I'm not sure one can read pdfs in neovide. I'd use emacs for that. The interesting point for me is that neovide is just a frontend for whatever is running on the remote. So the remote headless neovim could run behind tmux and I could connect to it from multiple computers, on different days. I wouldn't mind keeping emacs open on the side for the academic stuff. Maybe the way forward is to have emacs be the frontend to a remote neovim managing python kernels and lsp. Why not? Currently, if my network connection goes down, so does my python kernel running on remote, which is extremely annoying if on the move.
astoff1 · 2022-03-28 17:24
> Hopefully it will soon. Yes, it will soon, namely as of Emacs 28: https://github.com/astoff/comint-mime > Also my use case is that my datasets are very large, so I can't really test out code locally, except for a couple of small examples. Similar for me. I rarely execute the code I write locally. One exception are unit tests. > I also find it hard to deal with file paths when rsyncing, because paths to datasets differ between local and remote, so rsync wouldn't work out of the box. I only have the data remotely, and only rsync the code. And I run LSP locally and the Python shell on the remote machine. > I never liked lsp-mode because it's always been buggy and slow on my end. Even when the server is running locally? Maybe you can try Eglot.
da-g · 2022-03-29 04:00
Wow, comint-mime = pretty nice. I just tried it and it works great. Glad it's part of ELPA. I never tried eglot with python, only lua and it worked better than LSP. Maybe one last question, for your remote setup, how do you actually connect to the remote and/or keep it alive? Always through run-python on a remote file?
astoff1 · 2022-03-29 06:57
I have some helper functions to do things remotely. The main one is a command roughly as follows, where mirror directory is a Tramp path that I set dir-locally for each project I'm working on. ``` (defvar mirror-directory nil) (defun mirror-command-execute (command) "Execute COMMAND with remote `default-directory'. Interactively, reads a key sequence, so it acts like a prefix keymap." (interactive (list (lookup-key (current-active-maps) (read-key-sequence "Run remotely: ")))) (unless (commandp command) (error "`%s' is not a valid command" command)) (unless mirror-directory (error "Mirror directory not set")) (setq this-command command) (let ((default-directory mirror-directory)) (command-execute command))) ```
whompyjaw · 2022-08-16 17:13
How do you account for the commands that are different from the GUI? For example, even \`C-/\` doesn't work in no window mode. edit: I suppose I can use \`C-S--\` (or \`C-\_\`)