From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id urAxB8nl2l9VAQAA0tVLHw (envelope-from ) for ; Thu, 17 Dec 2020 04:59:53 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id kI5/Asnl2l/TJwAA1q6Kng (envelope-from ) for ; Thu, 17 Dec 2020 04:59:53 +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 96630940142 for ; Thu, 17 Dec 2020 04:59:52 +0000 (UTC) Received: from localhost ([::1]:38784 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kplOJ-0004ZX-JO for larch@yhetil.org; Wed, 16 Dec 2020 23:59:51 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:38484) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kplNp-0004ZK-3z for guix-devel@gnu.org; Wed, 16 Dec 2020 23:59:21 -0500 Received: from mail-ej1-x62d.google.com ([2a00:1450:4864:20::62d]:40123) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kplNj-0005A9-Vn for guix-devel@gnu.org; Wed, 16 Dec 2020 23:59:20 -0500 Received: by mail-ej1-x62d.google.com with SMTP id x16so36003297ejj.7 for ; Wed, 16 Dec 2020 20:59:15 -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=r+zWjVspe1W1uWNft2y69Z/Q5nhfOSbPy8Gw5pUtD7OS8RSdXcr7ISee3uKiLCKhQt ptblNtN0BolmsjIcZjNfWJwhA9lesDnOVcRCItM+mTuLd4TP1mO7bQKbLMya/p6Ty+Aa OeWsguGau5IWou4oxyixuphykVdD60e4VdrfE/g+Hbaf5RUqaB1OONTdoeoS7fm9RycJ k1ip5rDuBaZHCBs7CrtjUiCy9YPBXNN/tLblSpt2DJhmJdvySN3HKuGgBQ+9UT1bsH+u 31WqZViklJY7l0UoYXuDA2mFXdVR9SGdTOfgJjjb53YorIu4pI/6Ebtqk3X0kaCWhd95 yukg== 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=mlgNHwzlQ2ZkTQYLIFgQNmsxGOtYLxjP42enGQwoMXyX2GA97uGLhdapg01XCfAkx1 V3CW2HyKLPiDm1aydYmNE67hjqL1bkJsHv8JMhUs43yzm6qUfDMkjEpM4prpZFyZ6OXt ZDiE4BsKUwzpzt8fEFT1rQNkGb4QBCg/VcwX2I6nfURhjRPOcv7ZvTtHcZUYQdIEGgAp D36uktgvUMW5JS1DudnRta2r0eb1WvbKVIaWMJTVaQ1mX8lGBcIRpSLUGE+oLHRCkp7n Bsk1R/gS+dgcqhNPFVSE2wvabcH4mbwUwpSaVwV/tydRAgShmPeDlimoSY/MHg8n30Ad FKTA== X-Gm-Message-State: AOAM532/cxYKDQ74uxiLxXN3oHs8kPrlPcw4vm4M8m6REKJGg1iU+XJh kxD46bEXUcyXOCNy9nGPf9K8Lpn0qY5t0A== X-Google-Smtp-Source: ABdhPJw09djbxQtan62K9+7or/Rp4+p9oIjkNVEGDd9B0DLbMk8J1nfc0imRIiSISglfgyosPSTgaQ== X-Received: by 2002:a17:906:3813:: with SMTP id v19mr33738228ejc.462.1608181154164; Wed, 16 Dec 2020 20:59:14 -0800 (PST) Received: from localhost (145-130-182-109.fixed.kpn.net. [145.130.182.109]) by smtp.gmail.com with ESMTPSA id l12sm2901161ejk.10.2020.12.16.20.59.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Dec 2020 20:59:13 -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: <877dphyqn2.fsf@gmail.com> Date: Thu, 17 Dec 2020 05:59:13 +0100 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::62d; envelope-from=pinoaffe@gmail.com; helo=mail-ej1-x62d.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-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=r+zWjVsp; 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: 96630940142 X-Spam-Score: -3.01 X-Migadu-Scanner: scn0.migadu.com X-TUID: kzSAYvjazGa/ --=-=-= 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) --=-=-=--