Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

usage examples / tutorial #2

Closed
musteresel opened this issue Nov 18, 2016 · 21 comments
Closed

usage examples / tutorial #2

musteresel opened this issue Nov 18, 2016 · 21 comments

Comments

@musteresel
Copy link

A (few) fully fledged examples of what one can achieve with this would be very helpful.

As far as I understand this looks for a dir-locals.nix somewhere in the directory path (to either the default directory or the current buffer's file's directory) and runs nix-build on it to generate a elisp file which is then loaded. Ignoring the safety considerations in above description, of course.

What do you use it for? Do you have examples of useful dir-locals.nix?

@shlevy
Copy link
Owner

shlevy commented Nov 18, 2016

https://github.com/shlevy/service-runner The dir-locals.nix here sets up my coq environment with the right coq version and dependencies.

@idontgetoutmuch
Copy link

I have

let pkgs = import <nixpkgs> {}; in
pkgs.nixBufferBuilders.withPackages [ pkgs.python3 ]

as my dir-locals.nix but when I do M-x nix-buffer and M-x run-python then I still get a buffer with

Python 2.7.10 (default, Jul 15 2017, 17:16:57) 

How should I be using nix-buffer?

@idontgetoutmuch
Copy link

I can see I have

(require 'inherit-local "/nix/store/kbjaqrrdxjm595fzclmyjhr0yn5dhkf5-emacs-inherit-local-1.1.1/share/emacs/site-lisp/elpa/inherit-local-1.1.1/inherit-local.elc")

; Only set up nixpkgs buffer handling when we have some buffers active
(defvar nixpkgs--buffer-count 0)
(when (eq nixpkgs--buffer-count 0)
  (make-variable-buffer-local 'nixpkgs--is-nixpkgs-buffer)
  ; When generating a new temporary buffer (one whose name starts with a space), do inherit-local inheritance and make it a nixpkgs buffer
  (defun nixpkgs--around-generate (orig name)
    (if (and nixpkgs--is-nixpkgs-buffer (eq (aref name 0) ?\s))
        (let ((buf (funcall orig name)))
          (progn
            (inherit-local-inherit-child buf)
            (with-current-buffer buf
              (setq nixpkgs--buffer-count (1+ nixpkgs--buffer-count))
              (add-hook 'kill-buffer-hook 'nixpkgs--decrement-buffer-count nil t)))
          buf)
      (funcall orig name)))
  (advice-add 'generate-new-buffer :around #'nixpkgs--around-generate)
  ; When we have no more nixpkgs buffers, tear down the buffer handling
  (defun nixpkgs--decrement-buffer-count ()
    (setq nixpkgs--buffer-count (1- nixpkgs--buffer-count))
    (when (eq nixpkgs--buffer-count 0)
      (advice-remove 'generate-new-buffer #'nixpkgs--around-generate)
      (fmakunbound 'nixpkgs--around-generate)
      (fmakunbound 'nixpkgs--decrement-buffer-count))))
(setq nixpkgs--buffer-count (1+ nixpkgs--buffer-count))
(add-hook 'kill-buffer-hook 'nixpkgs--decrement-buffer-count nil t)

; Add packages to PATH and exec-path
(make-local-variable 'process-environment)
(put 'process-environment 'permanent-local t)
(inherit-local 'process-environment)
; setenv modifies in place, so copy the environment first
(setq process-environment (copy-tree process-environment))
(setenv "PATH" (concat "/nix/store/z0kd979q0h5b5knm4wng76j73f0708fl-python3-3.6.4/bin:/nix/store/z58l69705j82vvgsa88is55gzrl2r6xr-python3.6-numpy-1.13.3/bin:" (getenv "PATH")))
(inherit-local-permanent exec-path (append '("/nix/store/z0kd979q0h5b5knm4wng76j73f0708fl-python3-3.6.4/bin" "/nix/store/z58l69705j82vvgsa88is55gzrl2r6xr-python3.6-numpy-1.13.3/bin") exec-path))

(setq nixpkgs--is-nixpkgs-buffer t)
(inherit-local 'nixpkgs--is-nixpkgs-buffer)

so my PATH should be set to have the python on /nix/store/z0kd979q0h5b5knm4wng76j73f0708fl-python3-3.6.4/bin first but as I already have said if I do M-x run-python I get the python from /usr/bin/python.

@idontgetoutmuch
Copy link

idontgetoutmuch commented Feb 12, 2018

@shlevy I don't think your example works?

nix-build for nix-buffer for Process.v exited abnormally with code 1 with error output: 
error: attribute ‘fiat_HEAD’ missing, at /Users/dom/Dropbox/Tidy/NumMethHaskell/service-runner/dir-locals.nix:2:50
(use ‘--show-trace’ to show detailed location information)

@shlevy
Copy link
Owner

shlevy commented Feb 12, 2018

@idontgetoutmuch Not sure what revision of nixpkgs you have, but I have fiat_HEAD here... Anyway, is it possible run-python runs python in a separate comint buffer? If so I have a hacky workaround for that for coq support but need a better general solution.

@idontgetoutmuch
Copy link

It does seem like python runs in a separate comint buffer but my elisp isn't good enough to be sure.

(defun run-python (&optional cmd dedicated show)
  "Run an inferior Python process.

Argument CMD defaults to `python-shell-calculate-command' return
value.  When called interactively with `prefix-arg', it allows
the user to edit such value and choose whether the interpreter
should be DEDICATED for the current buffer.  When numeric prefix
arg is other than 0 or 4 do not SHOW.

For a given buffer and same values of DEDICATED, if a process is
already running for it, it will do nothing.  This means that if
the current buffer is using a global process, the user is still
able to switch it to use a dedicated one.

Runs the hook `inferior-python-mode-hook' after
`comint-mode-hook' is run.  (Type \\[describe-mode] in the
process buffer for a list of commands.)"
  (interactive
   (if current-prefix-arg
       (list
        (read-shell-command "Run Python: " (python-shell-calculate-command))
        (y-or-n-p "Make dedicated process? ")
        (= (prefix-numeric-value current-prefix-arg) 4))
     (list (python-shell-calculate-command) nil t)))
  (get-buffer-process
   (python-shell-make-comint
    (or cmd (python-shell-calculate-command))
    (python-shell-get-process-name dedicated) show)))

@shlevy
Copy link
Owner

shlevy commented Feb 12, 2018

OK, thanks. I'll try to find time to generalize and clean up my comint hack, but I can't promise any time soon sadly :( In the mean time you can try to copy what we do for coq: https://github.com/NixOS/nixpkgs/blob/038b893338f78bbb879eb6a7c28d8dcd9f9064d2/pkgs/applications/science/logic/coq/default.nix#L53-L78

@idontgetoutmuch
Copy link

My emacs and nix knowledge are probably insufficient to copy what you did. In the meantime, this very hacky setup seems to work

 '(python-shell-interpreter "/nix/var/nix/profiles/default/bin/nix-shell")
 '(python-shell-interpreter-args
   "-p \"callPackage /Users/dom/Dropbox/Tidy/mrp/dl.nix {}\" -I nixpkgs=/Users/dom/nixpkgs --run python")
 '(python-shell-process-environment
   (quote
    ("NIX_PROFILES=/nix/var/nix/profiles/default /Users/dom/.nix-profile" "NIX_REMOTE=daemon" "NIX_PATH=/nix/var/nix/profiles/per-user/root/channels" "NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "NIX_USER_PROFILE_DIR=/nix/var/nix/profiles/per-user/dom"))))

@eqyiel
Copy link

eqyiel commented Feb 12, 2018

@idontgetoutmuch I do something similar to get a Node REPL, you may be able to work from this: https://github.com/eqyiel/.emacs.d/blob/50ed49a43078e2642da609a0e12970b88a27baaa/config.org#nodejs-repl

@jwiegley
Copy link

@shlevy Shea, if I'm using developPackage, how can I get nix-buffer to create an environment for the buffer there only the dependencies listed for my projects are in scope?

I'm trying to get haskell-ide-engine working on macOS, but it fails compiling anything saying "Argument list too long", because my user environment has too many packages installed. For Haskell development, I'd like there to be multiple haskell-ide-engine processes running, each seeing only what it needs to see to work for each particular project.

@shlevy
Copy link
Owner

shlevy commented May 13, 2018

@jwiegley Take a look at haskell.lib.getHaskellBuildInputs

@jwiegley
Copy link

@shlevy So this?

let pkgs = import <nixpkgs> {};
    package = import ./. {};
in pkgs.nixBufferBuilders.withPackages
     (pkgs.haskell.lib.getHaskellBuildInputs package)

@shlevy
Copy link
Owner

shlevy commented May 14, 2018

I'd first build a GHC environment:

ghcEnv = package.compiler.withPackages (_: pkgs.haskell.lib.getHaskellBuildInputs package)

And then put that into your withPackages list.

@jwiegley
Copy link

@shlevy Do you know a variant of that which creates a Hoogle database for all the local dependencies of the package? :)

@jwiegley
Copy link

jwiegley commented May 15, 2018

@shlevy Here's my attempt:

let pkgs = (import <darwin> {}).pkgs;

    package = import ./. { nixpkgs = pkgs; };

    haskell-ide-engine = import (pkgs.fetchFromGitHub {
      owner  = "domenkozar";
      repo   = "hie-nix";
      rev    = "dbb89939da8997cc6d863705387ce7783d8b6958";
      sha256 = "1bcw59zwf788wg686p3qmcq03fr7bvgbcaa83vq8gvg231bgid4m";
    }) {};

    hoogleExpr = <nixpkgs/pkgs/development/haskell-modules/hoogle.nix>;

    ghcEnv = package.compiler.withPackages
      (p: with p;
        let packages = pkgs.haskell.lib.getHaskellBuildInputs package;
            hoogle = callPackage hoogleExpr { inherit packages; }; in
          [ hdevtools haskell-ide-engine.hie82 hoogle ] ++ packages);

in pkgs.nixBufferBuilders.withPackages [ ghcEnv ]

@jwiegley
Copy link

@shlevy How would I do the same thing as getHaskellBuildInputs, but for Coq?

@jwiegley
Copy link

jwiegley commented May 16, 2018

@shlevy At least for Haskell, I now have a more convenient way of interacting with projects that do and do not have a default.nix (using developPackage).

  1. Create a packageDeps function: https://github.com/jwiegley/nix-config/blob/master/overlays/10-haskell.nix#L91

  2. Create nix-shell-gen, which works even if there's no default.nix, but just a .cabal file or a package.yaml: https://github.com/jwiegley/nix-config/blob/master/bin/nix-shell-gen

  3. Create a dir-locals.nix, using packageDeps:

let pkgs = (import <darwin> {}).pkgs;
in pkgs.nixBufferBuilders.withPackages
     [ (pkgs.packageDeps "hnix" "ghc822" pkgs.haskellPackages_8_2
          (builtins.dirOf __curPos.file)) ]

For more complex projects like hnix, I create a full default.nix file compatible with this workflow: https://github.com/haskell-nix/hnix/blob/pending/default.nix

@shlevy
Copy link
Owner

shlevy commented May 17, 2018

@jwiegley I think there's a ghcWithHoogle, but I don't use it myself yet...

For coq, do we have a general buildCoqPackage or coq.mkDerivation or whatever? If not, we have to either just take all build inputs or manually add passthru to the relevant packages.

@shlevy
Copy link
Owner

shlevy commented May 17, 2018

@jwiegley Nice! For my setup, I have a top-level dir-locals.nix in my home directory that handles haskell projects without their own dir-locals.nix: https://github.com/shlevy/config/blob/72469d4de45f7c6c9fd828f8f4291f1932e3500d/dir-locals.nix

@analyticd
Copy link

Related to this, an alternative solution to nix-shell integration to Emacs that I found works better than other solutions I have tried (especially for Python) was brought to my attention here. I have a fork with some usage examples here. As you'll see from the first link this is a different nix-mode and nix-shell than you see floating around elsewhere. Need to make this wider known.

@shlevy
Copy link
Owner

shlevy commented Sep 23, 2022

Superseded by #20, part of the work to get a flake-based version of nix-buffer

@shlevy shlevy closed this as not planned Won't fix, can't repro, duplicate, stale Sep 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants