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 +yaeHQKN2l8lPAAA0tVLHw (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 mp0 with LMTPS id WBZQGQKN2l98HgAA1q6Kng (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 020C6940429 for ; Wed, 16 Dec 2020 22:41:06 +0000 (UTC) Received: from localhost ([::1]:46408 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kpfTk-00051P-Ug for larch@yhetil.org; Wed, 16 Dec 2020 17:41:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:53284) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kpchy-0003WC-Ui for guix-devel@gnu.org; Wed, 16 Dec 2020 14:43:34 -0500 Received: from mail-ej1-x633.google.com ([2a00:1450:4864:20::633]:40322) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kpchx-0003VZ-6E for guix-devel@gnu.org; Wed, 16 Dec 2020 14:43:34 -0500 Received: by mail-ej1-x633.google.com with SMTP id x16so34475372ejj.7 for ; Wed, 16 Dec 2020 11:43:32 -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=fWvBMKFf5jsSC9y3RSRMo4+84/KTSmI0BZWM4jwe5/Pr8Lv45Q1bxLxECSwbvvpzm2 L0MOCJBZPlSiFFKwKtDbpW7dCtr5pMyzUZ8UK9zkAOeOSdkrJnOvgfbuqKiDW7siG7Vo d+WHWrFRA3bVTmz5HPiR0VYNIZiEae0cB2hIyP0GyWVr2IgJ2tZmX3G+TKKzqBV409tm EXU6I2EFGG31rjavTbMeu1AEnPja9SAifnv44aK0Fy3SJu3N2ocvMRxApBVGCUaAi4yq 1vCehxUzxNZvf+eJlIFqxmcJKQG7vOOTWCMwik0RrdqdBL0a7XNtxtB7zwrjclbDZJJ6 FNAw== 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=CX0mpA+ly6eh96laqfFrZOEufN0+xJ9RwYqjLVRDAZI8lhtRokqhEzXLC3USjLrdSf 5x5umqCFSbBAOeweuQtx8qyVJ4qTTuM+RcEiYEBuZzXZcJZ0Kw4v/OO7lk8RMV+vtsrn SJxDATQX4Ui7h3Y+4QMQ9FCAlmPMMiPUrruKITroB/PqwZ6Yw8rAiH0XTRP4WUkvsBXx FvpBbg3ngDFLSSmwrVA2ud+mf1Wvepjk25lyMQycMwlJkCfEktWu9CJsFswSmbQNyiPD sRH7S0vaz6LgcYJ2ghFA4T2rXt1eJIhrcJZSi0+vcJefV7aR1OvYsCgnxLhLrjmtim1q qgrQ== X-Gm-Message-State: AOAM532UiYEf8V9iArv3FdKxn9SSH7Qb9l7L2zjqT3nQjPP+X4RDMoCy eoDKRGNdx8erRQojRYbpZOKAvjM2Ho3irA== X-Google-Smtp-Source: ABdhPJwjK1jVMXVUeCQErXUpl0DQXG2CgrHfwDt3R5XSJj/P2r5YEHDtCZnYcSGL6MODyQE30ArTzA== X-Received: by 2002:a17:906:15ca:: with SMTP id l10mr14501079ejd.402.1608147811048; Wed, 16 Dec 2020 11:43:31 -0800 (PST) Received: from localhost (145-130-182-109.fixed.kpn.net. [145.130.182.109]) by smtp.gmail.com with ESMTPSA id i26sm2047742eja.23.2020.12.16.11.43.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Dec 2020 11:43:30 -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: <87lfdxzgda.fsf@gmail.com> Date: Wed, 16 Dec 2020 20:43:29 +0100 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::633; envelope-from=pinoaffe@gmail.com; helo=mail-ej1-x633.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=fWvBMKFf; 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: 020C6940429 X-Spam-Score: -3.01 X-Migadu-Scanner: scn0.migadu.com X-TUID: 4whab9ZZy9pG --=-=-= 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) --=-=-=--