travisbhartwell / nix-emacs Goto Github PK
View Code? Open in Web Editor NEWA set of useful Emacs modes and functions for users of Nix and Nix OS.
A set of useful Emacs modes and functions for users of Nix and Nix OS.
Similar to Help-Mode, maybe having a custom mode for the buffer created has sth to do with this?
Hi,
independently from this repository, I developed a few utility functions for working with nix-shell environments link. I think these functions could be beneficial for this repository and I would like to merge my work with yours.
The functions include:
nix-shell-command
to compose a nix-shell command string that can be passed to the commandlinenix-shell
that directly executes a command in the given sandboxnixos-find-sandbox
searches from the given path upwards until it finds a *.nix
file.nixos-current-sandbox
searches from the current working directroy upwards until it finds a *.nix
filenixos-executable-find
, a replacement for the built-in executable-find
. It searches in the given sandbox for executables.Let me know what you think.
Best,
Sven
What is to be done:
Defined at:
options.Defined at
one should go.Defined at
: it goes to the line it was defined (long shot)A typical problem using nix and emacsclient/server is that the environment from nix-shell isn't inherited. This break lots of functionality - anaconda-mode for python, etc.
The easiest solution is to start a dedicated emacs per nix-shell, but that's annoying.
Since all(?) of the environment is contained in the environment variables it seems like just replacing process-environment
with the environment set up by nix-shell
should work quite well?
It's possible to make process-environment
buffer local so the changes are contained to the relevant
buffers.
A quick and dirty function to this is provided below:
(defun nix-shell-load-env (nix-file)
"Loads the environment defined by NIX-FILE. Runs nix-shell to get the
environment and makes process-environment buffer local"
(interactive "fnix-file")
(let ((environment
(with-temp-buffer
(let* ((nix-file-shell-safe (shell-quote-argument nix-file))
(command (format "nix-shell %s --command 'printenv -0' 2>/dev/null"
nix-file-shell-safe))
(status (call-process-shell-command command nil t)))
(when (> status 0)
(message "'nix-shell %s' failed with %d" nix-file-shell-safe status)
(return nil))
(split-string (buffer-string) "\0")))))
(when environment
(set (make-local-variable 'process-environment)
environment))
))
A possible complication is whether the various modes react to changes in the environment. Anaconda mode seems to pick up the changes.
Another problem is to automate it. With the correct hooks (that hopefully runs before mode hooks) and nix-current-sandbox
it doesn't seem to hard though. Ideally we don't want to call nix-shell
each time a new buffer is opened, and it would be nice to share the process-enviroment
across buffers belonging to the same project. Which start to sound like a projectile feature/plugin.
A related discussion: flycheck/flycheck#610
I can try to clean things up and create a PR, but some early feedback is always a good idea.
After updating a nix channel or garbage collecting the nix store, nix-shell may need to do a lot of setup (which, particularly when Haskell dependencies are involved, might take tens of minutes). When this happens, Emacs becomes completely unresponsive when it blocks on a command wrapped by nix-shell
.
Is there any way we can improve on this situation?
I recently added nixos snippets to yasnippet.
Would it make sense to add yasnippet to nix-emacs and/or the nixos layer of spacemacs?
Yesterday I played around a little with nix-sandbox
and found the following functions make it work (at least partially):
;; haskell with nix
(setq haskell-process-wrapper-function
(lambda (args) apply 'nix-shell-command (nix-current-sandbox) args))
(setq flycheck-command-wrapper-function
(lambda (command) (apply 'nix-shell-command (nix-current-sandbox) command))
flycheck-executable-find
(lambda (cmd) (nix-executable-find (nix-current-sandbox) cmd)))
(defun my-ghc-mod-setup ()
(set (make-local-variable 'my-ghc-mod) (nix-executable-find (nix-current-sandbox) "ghc-mod"))
(message "local ghc-mod is: %S" my-ghc-mod)
(set (make-local-variable 'ghc-module-command) my-ghc-mod)
(set (make-local-variable 'ghc-command) my-ghc-mod))
(add-hook 'haskell-mode-hook 'my-ghc-mod-setup)
The first two are from the docs, the ghc
package needs the variables ghc-module-command
and ghc-command
set to work. I make the buffer local, because they are different for every file, obviously. Maybe there is a better solution than buffer-local? Maybe per folder? On the other hand the nix-build overhead is not that big (I think).
There’s still a bit of duplication, but what’s the general impression?
In the particular setup I'm working on, there is a bash exported function module
which is tripping up the environment setup code
module ()
{
eval `/usr/bin/modulecmd bash $*`
}
declare -fx module
It produces the following environment variable definition under printenv
BASH_FUNC_module()=() { eval `/usr/bin/modulecmd bash $*`
}
Which gets translated into the nix-sandbox-rc-... file command
export BASH_FUNC_module()=\(\)\ \{\ \ eval\ \`/usr/bin/modulecmd\ bash\ \$\*\`'
'\}
Causing the shell to choke with the error message
/tmp/nix-sandbox-rc-26417EZN line 97 syntax error near unexpected token `('
One solution may be to have nix-create-sandbox-rc
just capture and use the output of
declare -x
declare -fx
for the shell script instead of using printenv -0
.
Cheers! -Tyson
I use nix-sandbox.el
at work and encountered an issue. After a few hours of work, my machine told me that my disk space is nearly full. As it turns out, it was the /nix/store
directory, so I did a nix-collect-garbage
and cleaned up ~80Gb disk space. After a few hours more, the issue reappeared. The reason for this massive growth in space are successive calls to nix-shell --run ...
. Each call creates a new derivation, which then takes up some space on disk and doesn't get deleted after nix-shell
exits.
So question is, how do we fix this? I see the following solutions:
nix-shell --run
calls.nix-shell
call overhead.I for my part am in favor of the first solution. I also would do the development effort since I'm in a desperate need for a solution. What is your opinion?
Best,
Sven
I haven't looked into why, but these two are by far the slowest loading pkgs in my spacemacs:
3.4 and 4.0 seconds, with the runners up needing 0.6 and 0.5 seconds.
When I write nix.use
I get completion suggestions.
When I write
nix = { use
I don't get any.
Should I be able to get home-manager options as completions using nixos-options
?
I've added this configuration from README to my .emacs
:
(setq flycheck-command-wrapper-function
(lambda (command) (apply 'nix-shell-command (nix-current-sandbox) command))
flycheck-executable-find
(lambda (cmd) (nix-executable-find (nix-current-sandbox) cmd)))
flycheck-verify-setup
output:
Syntax checkers for buffer API.hs in haskell-mode:
haskell-stack-ghc
- predicate: nil
- executable: Not found
haskell-ghc
- predicate: nil
- executable: Not found
haskell-hlint
- predicate: nil
- executable: Not found
Flycheck Mode is enabled.
my shell.nix
(generated by cabal2nix
):
{ nixpkgs ? import <nixpkgs> {}, compiler ? "default" }:
let
inherit (nixpkgs) pkgs;
f = { mkDerivation, base, blaze-builder, blaze-html, bytestring
, containers, cookie, either, mtl, postgresql-simple, servant
, servant-blaze, servant-server, SHA, stdenv, stm, text, time
, transformers, uuid, wai, warp
}:
mkDerivation {
pname = "xxx";
version = "0.1.0.0";
src = ./.;
isLibrary = false;
isExecutable = true;
executableHaskellDepends = [
base blaze-builder blaze-html bytestring containers cookie either
mtl postgresql-simple servant servant-blaze servant-server SHA stm
text time transformers uuid wai warp
];
license = stdenv.lib.licenses.mit;
};
haskellPackages = if compiler == "default"
then pkgs.haskellPackages
else pkgs.haskell.packages.${compiler};
drv = haskellPackages.callPackage f {};
in
if pkgs.lib.inNixShell then drv.env else drv
README must have instructions on how to use the package (with company and helm) examples.
Once ready we can submit to MELPA
[ ] This is an example for company-anaconda. https://github.com/proofit404/company-anaconda
[ ] Gif Showing Usage of the autocompletion and helm sources.
Right now I have to close emacs, re-run nix-shell, and reopen emacs again to reload my NIX_GHC paths for ghc. It would be awesome if there was some function that ran nix-shell and reloaded the exec-path and environment variables without having to restart emacs.
I'm using nix-mode and would like to also make use of nix-sandbox for Flycheck (and other executables where possible). Unfortunately the example code in the README does not work. When trying to Flycheck a file I get the error:
eval: Wrong number of arguments: (1 . 2), 3
After some digging I found that the bug appears to be that nix-sandbox declares a function called nix-shell
which overlaps with a function defined in the nix-mode
package.
Good day to you Travis.
Thank you for your package.
I have next setup and situation and try to figure it out:
nixos
layer: https://github.com/syl20bnr/spacemacs/tree/develop/layers/+os/nixosemacs --debug-init
passes right.When trying to search with helm-nixos-options
, I on any input string get:
Error running timer: (error "In 'NixOS Options' source: 'nixos-options' must be a list, a symbol bond to a list, or a function returning a list ")
I also saw an error:
Warning: Cannot find nixos option file.
Can you help me out and say what is it.
I've been using nix-sandbox for about a month with haskell-mode and flycheck and it works fine.
I think it's ready to be published to melpa.
/cc @svenkeidel
Two issues here:
The readme suggests this configuration for flycheck wrappers to find nix shells:
(setq flycheck-command-wrapper-function
(lambda (command) (apply 'nix-shell-command (nix-current-sandbox) command))
flycheck-executable-find
(lambda (cmd) (nix-executable-find (nix-current-sandbox) cmd)))
This has been working great for my Haskell development. But when I edit an elisp file (such as ~/.emacs.d/init.el) I get this error:
Suspicious state from syntax checker emacs-lisp-checkdoc: Flycheck checker emacs-lisp-checkdoc returned non-zero exit code 1, but its output contained no errors: /run/current-system/sw/bin/bash: -c: line 0: syntax error near unexpected token `('
The command its running appears to be this:
"bash" "-c" "source /tmp/nix-sandbox-rc-8480dqC; /nix/store/1v2ral91bd58w3rawxb1p4a6dwdmz1fd-emacs-25.3/bin/.emacs-wrapped -Q --batch --eval (progn (setq-default sentence-end-double-space t)) --eval (progn (defvar jka-compr-inhibit) (unwind-protect (let ((jka-compr-inhibit t)) (when (equal (car command-line-args-left) "--") (setq command-line-args-left (cdr command-line-args-left))) (unless (require 'elisp-mode nil 'no-error) (require 'lisp-mode)) (require 'checkdoc) (let ((source (car command-line-args-left)) (process-default-directory default-directory)) (with-temp-buffer (insert-file-contents source 'visit) (setq buffer-file-name source) (setq default-directory process-default-directory) (with-demoted-errors "Error in checkdoc: %S" (delay-mode-hooks (emacs-lisp-mode)) (setq delayed-mode-hooks nil) (checkdoc-current-buffer t) (with-current-buffer checkdoc-diagnostic-buffer (princ (buffer-substring-no-properties (point-min) (point-max))) (kill-buffer)))))) (setq command-line-args-left nil))) -- /tmp/flycheck8480q0I/foo.el"
The problem being that quotes have been added around all the outer strings, but since we're calling bash -c the last string is another bash command, and the arguments inside that command aren't quoted properly.
I think what's going on is that nix-shell-command
is taking a list of shell parameters in command
, and in order to embed them into a bash command that sources the sandbox environment it's pasting them in a string. That works provided all the arguments are "simple" enough, but the emacs-lisp checker wants to invoke emacs with a bunch of lisp code as --eval
arguments; all the parentheses and single quotes in the lisp arguments are being interpreted as bash syntax.
Noticed a message pop up in my Messages buffer today that it couldn't find the options file.
Did some investigating and ran into this:
https://gist.github.com/travisbhartwell/748f5310df321283c274
Not sure when this changed. Need to do some investigation on how to properly fix this. Sounds like at the very least it's an upstream issue.
But, also, I think I'd prefer a command that didn't require the user to have allowUnfree
set to true.
The code suggested in the readme for things like getting flycheck to find executables from a nix shell is this:
(setq flycheck-command-wrapper-function
(lambda (command) (apply 'nix-shell-command (nix-current-sandbox) command))
flycheck-executable-find
(lambda (cmd) (nix-executable-find (nix-current-sandbox) cmd)))
This works fine even for executables that aren't in the shell, but are in your normal PATH. But when you open a file that isn't in a nix shell, nix-current-sandbox
returns nil and nix-shell-command
and nix-find-executable
throw an error on receiving nil, even when the executable that's being asked for could be resolved without a nix shell.
This makes the suggested code unsuitable for putting as global configuration for flycheck; instead it needs to be activated per project.
I could make the flycheck customisation functions more complex and check whether nix-current-sandbox
is returning nil, but it'd be much nicer if these functions could instead be no-ops if passed nil (or if nix-current-sandbox
could indicate that there isn't a current sandbox in some other way). Then the suggested configuration would "just work" more of the time.
The last (and only) release tagged was at the beginning of last year. If and when there's a stable point in development, could another release be made? Regular releases helps MELPA Stable users stay up-to-date.
Thanks!
Hi,
when compiling files in this project, I get the following warning:
In toplevel form:
lib/nix-emacs/nixos-packages.el:28:43:Warning: reference to free variable
‘spacemacs-cache-directory’
lib/nix-emacs/nixos-packages.el:34:7:Warning: assignment to free variable
‘nixos-packages’
lib/nix-emacs/nixos-packages.el:46:1:Warning: value returned from (assoc
"name" (car nixos-packages)) is unused
lib/nix-emacs/nixos-packages.el:46:20:Warning: reference to free variable
‘nixos-packages’
lib/nix-emacs/nixos-packages.el:47:1:Warning: value returned from (assoc
"system" (car nixos-packages)) is unused
lib/nix-emacs/nixos-packages.el:48:1:Warning: value returned from (assoc
"description" (assoc "meta" (car nixos-packages))) is unused
lib/nix-emacs/nixos-packages.el:49:1:Warning: value returned from (assoc
"homepage" (assoc "meta" (car nixos-packages))) is unused
lib/nix-emacs/nixos-packages.el:50:1:Warning: value returned from (assoc
"license" (assoc "meta" (car nixos-packages))) is unused
lib/nix-emacs/nixos-packages.el:51:1:Warning: value returned from (assoc
"longDescription" (assoc "meta" (car nixos-packages))) is unused
lib/nix-emacs/nixos-packages.el:52:1:Warning: value returned from (assoc
"platforms" (assoc "meta" (car nixos-packages))) is unused
lib/nix-emacs/nixos-packages.el:53:1:Warning: value returned from (assoc
"position" (assoc "meta" (car nixos-packages))) is unused
lib/nix-emacs/nixos-packages.el:54:1:Warning: value returned from (assoc
"maintainers" (assoc "meta" (car nixos-packages))) is unused
lib/nix-emacs/nixos-packages.el:55:1:Warning: value returned from (assoc
"maintainers" (assoc "meta" (car nixos-packages))) is unused
In end of data:
lib/nix-emacs/nixos-packages.el:116:1:Warning: the following functions are not
known to be defined: nixos-packages-get-description,
nixos-packages-get-homepage, nixos-packages-get-license,
nixos-packages-get-longDescription, nixos-packages-get-platforms,
nixos-packages-get-maintainers, nixos-packages-get-position,
nixos-packages-get-name, nixos-packages-get-system
Done (Total of 5 files compiled)
I'm new to spacemacs and have only been using it for a couple months, but I work in NixOS and make use of nix-shell alot.
One of the interesting consequences of this, is that many projects have dependencies which are now isolated within a nix-shell.
However various spacemacs layers work on the basis of running external commands, like the sqli layer expects mysql
to be available on the PATH.
What I've done atm is often install the layer requirements in my user profile, and also in the shell.nix. So when I run things from nix-shell, I end up using the shell.nix specified dependencies, while spacemacs ends up using the config.nix specified dependencies. While this hack works, it's not very elegant.
I've read in other places, that people would launch emacs from within the nix-shell, and while this could work, how does one deal with multiple projects each with their own nix-shell, does multiple instances of emacs work nicely together, do copy and paste and switching between buffers work seamlessly? I don't know atm.
Just wanted to know other people's thoughts on this issue, and whether there are ideas for making IDE-centric development workflow work with nix-shell like isolation. I thought that if there was an editor that was made from ground up to allow multiple instances of the editor to run and to have a overall chrome/server that allowed coordination between each instance, sort of like the Chrome browser where each tab is a separate process. Then such an editor would actually work nicely with nix-shell.
Following up on #45 (comment):
I've been added to the nix-community github org, so I think if @travisbhartwell initiates an ownership transfer of this repository to nix-community I'll be able to (a) accept the transfer, and (b) re-add @travisbhartwell as a repository maintainer (if necessary - this part may happen automatically).
Related github docs: https://docs.github.com/en/github/administering-a-repository/transferring-a-repository#transferring-a-repository-owned-by-your-user-account
(defun nix-find-sandbox (path)
"Search for a sandbox starting at PATH traversing upwards the directory tree.
If the directory contains a `shell.nix' file, the path to this
file is returned. Otherwise if the directory contains a
`default.nix' file, the parent directory is returned."
The implementation seems to detect the presence of any file ending in .nix
, not just default.nix
. This is a problem for me, because I have .nix
files in various directories that do not correspond to usable shells for development.
In anticipation of the new release, warnings about deprecated attributes started being thrown, and that breaks nix-options
, like:
/home/mdorman/trace: Warning: using a deprecated attribut$
trace: Warning: using a deprecated attribute 'haskellngPackages'.
trace: Warning: using a deprecated attribute 'opentsdb'.
these derivations will be built:
/nix/store/4g5gd0nh4sy6dv3dnjxgg4vjpi5cqcs7-options-json.drv
building path(s) ‘/nix/store/505nfy9237kvcj88jyjcbwjkfgin94jw-options-json’
/nix/store/505nfy9237kvcj88jyjcbwjkfgin94jw-options-json/share/doc/nixos/options.json
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.