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 tG5lIBwY21/VCwAA0tVLHw (envelope-from ) for ; Thu, 17 Dec 2020 08:34:36 +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 YG+rGxwY218YeAAAB5/wlQ (envelope-from ) for ; Thu, 17 Dec 2020 08:34:36 +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 1DE71940503 for ; Thu, 17 Dec 2020 08:34:36 +0000 (UTC) Received: from localhost ([::1]:41768 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kpok7-00007b-1e for larch@yhetil.org; Thu, 17 Dec 2020 03:34:35 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:33044) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kpof5-00060C-JD for guix-devel@gnu.org; Thu, 17 Dec 2020 03:29:23 -0500 Received: from mail-ed1-x534.google.com ([2a00:1450:4864:20::534]:41477) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kpoez-00081u-Sy for guix-devel@gnu.org; Thu, 17 Dec 2020 03:29:22 -0500 Received: by mail-ed1-x534.google.com with SMTP id i24so27675242edj.8 for ; Thu, 17 Dec 2020 00:29:17 -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=pS2n/lmcgCGyCdsZb//Ti9aTKP2ojGAU+un21Bk4Q7MKAEqdAfJbrW5Q43t5btY1jz WbwfxMFgfToybEZstEC5jIJM3bBJ7NMj8Emz7dFRPE8LT03vx6Sle63e/EiuEBOaA5s0 /WrvPQ63RhHqzxU4JpKfa1Oa64dbAVYwaFvFsBnAp6BJMHbshJaRSjbg1MgPK2CfQ/VD jllq+5qGWZFYYaoIY5mI7R22jmRlG8NQakeDQW9j22zJhgRE213LaHFg1F4GRaQ8gQ84 ShYZZ03BxIKv7p9NF3PMHZdXP4pjoCX3JM/k+V3cBEwgehIFWUjWltb1QK6qUQgqk81l srtw== 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=N2q+yT1Nmp1xPWPOtwczLEBC/xZ0H+IghIPw0n8uz6RvtD5D5RIf/UqdEXc2uQz5um wgM9YcSNIiDn8z9UtQfjSxcmTP5WLQadUTW8KvNjoxfxAkgyv8puwyPWQ4JDYOslEbOw gJhkhh0Dc+GySt5calBUTZASfn3yfTxevLiIwlqPxzOCAb4EF9mFe+YryPIbe3r5ZZIH sUOELPXU1fMagSjS/wu5QiQLJY/F7L/XDhaSwe1M1miSWppG6DyWfeN8KJoIMCUFmMVy jnKnyBMN9V7yMq89tEwUxcAVxT9gpxuG+4Pu+RrfUGGxlK7qZzqxDWQGckM0vJTFyCJB Opvw== X-Gm-Message-State: AOAM532ZuQKn0dCj/1iR4YI53V5CGZuWhtttybWjk3bVQZHHnxWu2J3O emwLrDw6D08B4plVzEzI5/21oCn16mU4cQ== X-Google-Smtp-Source: ABdhPJzvrQQlXbfCBXQzctaWr/umzqOJRsLL/ogIJYy6ZXn2G0xsKwjHvMsxsRZSWI3fZa+lW/B7xw== X-Received: by 2002:aa7:cac2:: with SMTP id l2mr37518275edt.141.1608193756333; Thu, 17 Dec 2020 00:29:16 -0800 (PST) Received: from localhost (145-130-182-109.fixed.kpn.net. [145.130.182.109]) by smtp.gmail.com with ESMTPSA id x16sm3222578ejb.38.2020.12.17.00.29.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Dec 2020 00:29:15 -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: <874kklyqmt.fsf@gmail.com> Date: Thu, 17 Dec 2020 09:29:14 +0100 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::534; envelope-from=pinoaffe@gmail.com; helo=mail-ed1-x534.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: -1.51 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20161025 header.b=pS2n/lmc; 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: 1DE71940503 X-Spam-Score: -1.51 X-Migadu-Scanner: scn0.migadu.com X-TUID: duXM9wejbaEf --=-=-= 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) --=-=-=--