From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id JYK/HAKN2l+KOAAA0tVLHw (envelope-from ) for ; Wed, 16 Dec 2020 22:41:06 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id iC8SGAKN2l/+UQAAB5/wlQ (envelope-from ) for ; Wed, 16 Dec 2020 22:41:06 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id C12F59402D6 for ; Wed, 16 Dec 2020 22:41:05 +0000 (UTC) Received: from localhost ([::1]:46416 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kpfTk-00051Y-Dg for larch@yhetil.org; Wed, 16 Dec 2020 17:41:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:53366) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kpciD-0003ZP-C4 for guix-devel@gnu.org; Wed, 16 Dec 2020 14:43:49 -0500 Received: from mail-ej1-x62a.google.com ([2a00:1450:4864:20::62a]:40317) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kpciB-0003XY-V9 for guix-devel@gnu.org; Wed, 16 Dec 2020 14:43:49 -0500 Received: by mail-ej1-x62a.google.com with SMTP id x16so34476435ejj.7 for ; Wed, 16 Dec 2020 11:43:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=user-agent:from:to:subject:message-id:date:mime-version; bh=1gmsJ5K/nUWx43UYEUvlGcQI5HjNApTfEAgEHerWOHY=; b=phr7h/8/XhCc9CdPNo/HrULZ2kVqlNj8b0w+Bqnrstg9DC886UPoInsteDl1UVWcWu +MgfJMu07RDW3Dp2n+bjBoRB4FTgeq3qUtjRlFY60ohUbCB1vqoLuRWoBqpW4NtmGV9R JMGtlSKRjJIPAR7UlRxvnvzzm1rzU+k6pVXuRdXyVLnkn2XbHw5lbe3IHNTToRz2z2Fo dFjDyQ8V/kw7m2w8EQIvSJDGS4EQ3sypjGOiRAzzRGj2XjqeL448rAHRq7eSZnKBJYf0 U2YTTqyYnBkqyW7oKccAHn0JRwG8LBdBADPOvl/TKST/eZlSSVqG0fZVVm2B9kz0EkdC 1rZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:user-agent:from:to:subject:message-id:date :mime-version; bh=1gmsJ5K/nUWx43UYEUvlGcQI5HjNApTfEAgEHerWOHY=; b=V4HaBSg/3Om8zkCdIGorA80qPUXdcRPG/0uzsvj7a0O8t1UglhEyyqfwnlvFIyb3F7 waKJt3wC0BCTCKOGEtPx1PkwxCSnlUVZVeo5g57c+y43YAhm1WhT0z5rXTwuQqRra6FP uI4RLQ0esV46EMljKNotu27CCHHKsNLEzKuPkH4ZXd74Vja8FmwxCxuzYhf6LGKGAsFj lMcD4sMb0+l3tOsi8oXdGbzTdJBPpK09YCMIg+NM0Mr/rNzi+z1lrzF/WmyGMT6fZHhd TZL7WxmxiDrk38BHqTy2jNYU658LhJ0dhJaQeQ5N5DO5R0D4Slf3LgEYa77wjZOQQSrX kwFw== X-Gm-Message-State: AOAM532IrUo3j6Yuj3cO/2ir5MI1oaA6ZAoe0P/5sAGZkMFJkyxU2riW PgfPOdBnAv2jlTd6evYHNM7U03SrtKldJw== X-Google-Smtp-Source: ABdhPJyuU5rIFk8njXqMG7zZKpxDTKP6d3nStjlV4TxJUou/GrZ5gEKlveO06DScv8CE3oUCBsDn+w== X-Received: by 2002:a17:906:1302:: with SMTP id w2mr33456038ejb.413.1608147826296; Wed, 16 Dec 2020 11:43:46 -0800 (PST) Received: from localhost (145-130-182-109.fixed.kpn.net. [145.130.182.109]) by smtp.gmail.com with ESMTPSA id i4sm2124248eje.90.2020.12.16.11.43.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Dec 2020 11:43:45 -0800 (PST) User-agent: mu4e 1.4.13; emacs 27.1 From: pinoaffe To: guix-devel@gnu.org Subject: Some emacs stuff to activate/deactivate guix profiles Message-ID: <87im91zgcv.fsf@gmail.com> Date: Wed, 16 Dec 2020 20:43:44 +0100 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::62a; envelope-from=pinoaffe@gmail.com; helo=mail-ej1-x62a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 16 Dec 2020 17:40:35 -0500 X-BeenThere: guix-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+larch=yhetil.org@gnu.org Sender: "Guix-devel" X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: -3.01 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20161025 header.b=phr7h/8/; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of guix-devel-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-devel-bounces@gnu.org X-Migadu-Queue-Id: C12F59402D6 X-Spam-Score: -3.01 X-Migadu-Scanner: scn0.migadu.com X-TUID: KbnQ7f3WJc/1 --=-=-= Content-Type: text/plain Hi guix! I wrote some elisp that * maintains a list of available guix profiles * maintains a list of active guix profiles * allows the user to modify both of those lists * provides interactive commands that allow the user to (de)activate profiles * sets env variables and the emacs search path based on active profiles I may add the ability to "update" a profile from a manifest. This allows me to have a profile with, say, reverse engineering tools, and to (de)activate it whenever I do(nt) need those tools. Please not that I'm fairly new to all of this emacs stuff, so it may not be idiomatic or good code. I've attached the reusable stuff in guix-profiles.el, and my personal config in init-profiles.el. Any thoughts? Blessings, pinoaffe --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=guix-profiles.el Content-Transfer-Encoding: quoted-printable (require 'seq) (require 'subr-x) (defgroup guix-profiles nil "Settings for guix profile management") (defcustom guix-home-dir "" "The directory in which to look for the user's guix installation, typical= ly the users homedir." :type '(string) :group 'guix-profiles) (defcustom guix-available-profiles '() "List of all available profiles, each profile is represented by a cons pa= ir of the profile name and a plist containing at least the attribute :profi= le-file which should be a string pointing to the profile location" :type '(repeat (cons string (plist))) :group 'guix-profiles) (defcustom guix-active-profiles '() "The names of the profiles that are currently active." :type '(repeat string) :group 'guix-profiles) (defun guix-profile-or-name->profile (profile-or-name) (if (stringp profile-or-name) (assoc profile-or-name guix-available-profiles) profile-or-name)) (defun guix-profile->profile-file (profile-or-name) (and-let* ((profile (guix-profile-or-name->profile profile-or-name)) (profile-plist (cdr profile)) (profile-file (plist-get profile-plist :profile-file))) profile-file)) (defun guix-profile->manifest-file (profile-or-name) (and-let* ((profile (guix-profile-or-name->profile profile-or-name)) (profile-plist (cdr profile)) (manifest-file (plist-get profile-plist :manifest-file))) manifest-file)) (defun guix-enable-profile (profile) (interactive (list (ido-completing-read "Profile: " (mapcar #'car guix-av= ailable-profiles)))) (setq guix-active-profiles (cons profile guix-active-profiles)) (guix-set-paths guix-active-profiles)) (defun guix-disable-profile (profile) (interactive (list (ido-completing-read "Profile: " guix-active-profiles)= )) (setq guix-active-profiles (remove profile guix-active-profiles)) (guix-set-paths guix-active-profiles)) (defun fold (func acc lst) (if lst (fold func (apply func (car lst) acc '()) (cdr lst)) acc)) (defun cons* (&rest args) (apply #'apply #'list args)) (defun guix-profiles->environment-vars (profiles) (shell-command-to-string (string-join (apply #'list "guix" "package" "--search-paths" (fold (lambda (element accumulator) (cons "-p" (cons element accumulator))) nil (cons* "/run/current-system/profile" (format "%s/.config/guix/current" guix-= home-dir) (format "%s/.guix-profile" guix-home-di= r) (mapcar #'guix-profile->profile-file profiles)))) " "))) (defun guix-path-file->key-value (str) (mapcar (lambda (line) (let* ((lst (split-string line "=3D")) (var (string-remove-prefix "export " (car lst))) (val (string-trim (string-join (cdr lst) "=3D") "\"" "= \""))) (cons var val))) (split-string (string-trim-right str "\n") "\n"))) (defun guix-set-paths (profiles) (interactive (list guix-active-profiles)) (setq exec-path ; TODO: properly handle escaped :'s in $PATH (cons "/run/setuid-programs" (split-string (alist-get "PATH" (guix-path-file->key-value (guix-profiles->enviro= nment-vars profiles)) '() nil #'string=3D) ":"))) (mapcar (lambda (pair) (setenv (car pair) (cdr pair))) (guix-path-file->key-value (guix-profiles->environment-vars profi= les))) (setenv "PATH" (format "/run/setuid-programs/:%s" (getenv "PATH")))) (provide 'guix-profiles) --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=init-profiles.el Content-Transfer-Encoding: quoted-printable (defun read-file-contents (file) (read (with-temp-buffer (insert-file-contents file) (buffer-string)))) (use-package guix-profiles :init (progn (defvar guix-home-dir "/home/pino") (defvar guix-manifest-prefix (format "%s/data/config/manifests" g= uix-home-dir)) (defvar guix-profile-prefix (format "%s/profiles" guix-home-dir))) :config (progn (setq guix-available-profiles (mapcar (lambda (profile-name) (cons profile-name (list :profile-file (format = "%s/%s/%s" = guix-profile-prefix = profile-name = profile-name) :manifest-file (format= "%s/%s.scm" = guix-manifest-prefix = profile-name)))) (append (read-file-contents (format "%s/optional.= scm" guix-manifest-prefix)) (read-file-contents (format "%s/core.scm"= guix-manifest-prefix))))) (setq guix-active-profiles (read-file-contents (format "%s/core= .scm" guix-manifest-prefix))) (guix-set-paths guix-active-profiles))) (provide 'init-profiles) --=-=-=--