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 d5NhN1rl2l/kbQAA0tVLHw (envelope-from ) for ; Thu, 17 Dec 2020 04:58:02 +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 WFbTMlrl2l87KQAA1q6Kng (envelope-from ) for ; Thu, 17 Dec 2020 04:58:02 +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 99F24940142 for ; Thu, 17 Dec 2020 04:58:02 +0000 (UTC) Received: from localhost ([::1]:37664 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kplMX-00042k-HS for larch@yhetil.org; Wed, 16 Dec 2020 23:58:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:37914) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kplML-00042c-9I for guix-devel@gnu.org; Wed, 16 Dec 2020 23:57:49 -0500 Received: from mail-ej1-x62a.google.com ([2a00:1450:4864:20::62a]:42635) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kplMH-0004gH-ES for guix-devel@gnu.org; Wed, 16 Dec 2020 23:57:49 -0500 Received: by mail-ej1-x62a.google.com with SMTP id d17so36012279ejy.9 for ; Wed, 16 Dec 2020 20:57:45 -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=VCgR78WZbZijNbiHy6PHWzXQ9/9n/nfhMnBL8JKn++/ENSmf9SN5AW1FoSBFve1X3A Yt6Z1fsXw5pCp1nhi8EcPdtJmKPqtQfc9NI8eMhLKZNg5zOU06SYZi3uh+jLgz0rg3wQ mIwWrD0rpM9sJYhtUpqIGQscz4Qjh+x2N1iRzPG/hEX33fJHP1o3z4ISl/8OM5opjUx7 dK+JX0e4K8peIn0PnItfF4T4Q0XSknab8+bG+kXoMyANkl5cDcGCO8gxP85WTtEsu3Cr +q6WFAx4VPjIbKLP8goJu5eniWXVHc+HEANOMYAjCQQnNicSwvxQJcDFOOt5vmPOqf9k wXOA== 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=sS7ps19OCA6FaIOHLjtHgC3ZhZ6p8s7xOI0aWg6FKJVzPIDGIVMFjNmzHTN9GTgWlf 876PsbI98SS/OIZdqAMif0rPFu58QoWmrZc4pzKgcUdG18OMjPLRmnKMGden1x8f5MWy o0q9wQ+HZIas1XAl8+YpnqOcnFvFs9VNAvrwSOseHZislW9FF/xX3tDwhsfrwUbYaV6V gGon0n4uzJK5iltaneDqLivMnyChXTeY0Kq9gSuatv0l5xh7DIYT/Flwvk/yqy1hEoOe r5BfB0BaeeC+vaPIfaJwEbxChdU00FJySmGqB2hnndBVsOYxm/qhCQNEb48osVkdfHmK 8atA== X-Gm-Message-State: AOAM531h6QLnvesTkpIljOC58cWmIrI2hh7RO8bpMmttlqxHWIlFUIpw jk3hb0uED67cJrPyBuMlAGSS1hWSkZZqcw== X-Google-Smtp-Source: ABdhPJznY8xao0Fi9HkcEgs+VVLZTb1x6eH19ETCl9nqwwD6g1OCvfh7NYki4OWqHODwV0yDOB83vQ== X-Received: by 2002:a17:906:4756:: with SMTP id j22mr34524976ejs.353.1608181063842; Wed, 16 Dec 2020 20:57:43 -0800 (PST) Received: from localhost (145-130-182-109.fixed.kpn.net. [145.130.182.109]) by smtp.gmail.com with ESMTPSA id v18sm2849887ejw.18.2020.12.16.20.57.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Dec 2020 20:57:43 -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: <87czz9yqpl.fsf@gmail.com> Date: Thu, 17 Dec 2020 05:57:42 +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-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=VCgR78WZ; 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: 99F24940142 X-Spam-Score: -3.01 X-Migadu-Scanner: scn0.migadu.com X-TUID: /xhrxmhFS2dw --=-=-= 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) --=-=-=--