From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Philip Kaludercic Newsgroups: gmane.emacs.devel Subject: Re: [ELPA] New package: activities Date: Mon, 29 Jan 2024 13:03:14 +0000 Message-ID: <87zfwo2sx9.fsf@posteo.net> References: <86frykbksh.fsf@gnu.org> <8634ukb7hv.fsf@gnu.org> <3c51c1aa-ebe5-4dd3-b7cd-a12c972cee12@alphapapa.net> <86cytn9rta.fsf@gnu.org> <87mssq25ge.fsf@ucl.ac.uk> <87ede2n47p.fsf@osv.gnss.ru> <87ede11yzp.fsf@ucl.ac.uk> <878r48770w.fsf@osv.gnss.ru> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="28486"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Eric S Fraga , emacs-devel@gnu.org To: Sergey Organov Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Jan 29 14:04:40 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rURJX-00074o-RE for ged-emacs-devel@m.gmane-mx.org; Mon, 29 Jan 2024 14:04:40 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rURIO-00066D-8L; Mon, 29 Jan 2024 08:03:28 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rURIK-00065n-0B for emacs-devel@gnu.org; Mon, 29 Jan 2024 08:03:24 -0500 Original-Received: from mout01.posteo.de ([185.67.36.65]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rURIH-0007hx-AY for emacs-devel@gnu.org; Mon, 29 Jan 2024 08:03:23 -0500 Original-Received: from submission (posteo.de [185.67.36.169]) by mout01.posteo.de (Postfix) with ESMTPS id A3D7A24002B for ; Mon, 29 Jan 2024 14:03:16 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1706533396; bh=dmqSUB4avQv+hCQlBVnmQbKfg9JsqXwOyA0gyKUy3hI=; h=From:To:Cc:Subject:Autocrypt:OpenPGP:Date:Message-ID:MIME-Version: Content-Type:From; b=rXD1riH/gLB6jPGXubazHbL4tEozued5Wld8I/KnAiEMo9MMWqbqAh3ufkKOPEKHo YryIZnmzi8CecK0V6q9Gguk/EhfoLzBSW7OYnpF57Io/w1lk1m9CfotSDZ+t7Z6apf WKd6Dis+0h22gv48pMV0gKMzAXdaQba30G4hspc+BN8+aB1Qq1fpDeSKopoJNFKym6 T4L/ff6jgqoNPt9wziGq6W288jN0t4pECTT1tgPoYtraWm6mncpMUsl0iMyNb4Kr6v 7i26n2FgwSZn2+T9VEUlbpjGjXhI2gLSJnHEt8ve7J7U8rUWp3SFFKnzlmPKHpzVIl I46Dzu9OHI2pA== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4TNpPv2PHKz6twQ; Mon, 29 Jan 2024 14:03:15 +0100 (CET) In-Reply-To: <878r48770w.fsf@osv.gnss.ru> (Sergey Organov's message of "Mon, 29 Jan 2024 13:45:03 +0300") Autocrypt: addr=philipk@posteo.net; keydata= mDMEZBBQQhYJKwYBBAHaRw8BAQdAHJuofBrfqFh12uQu0Yi7mrl525F28eTmwUDflFNmdui0QlBo aWxpcCBLYWx1ZGVyY2ljIChnZW5lcmF0ZWQgYnkgYXV0b2NyeXB0LmVsKSA8cGhpbGlwa0Bwb3N0 ZW8ubmV0PoiWBBMWCAA+FiEEDg7HY17ghYlni8XN8xYDWXahwukFAmQQUEICGwMFCQHhM4AFCwkI BwIGFQoJCAsCBBYCAwECHgECF4AACgkQ8xYDWXahwulikAEA77hloUiSrXgFkUVJhlKBpLCHUjA0 mWZ9j9w5d08+jVwBAK6c4iGP7j+/PhbkxaEKa4V3MzIl7zJkcNNjHCXmvFcEuDgEZBBQQhIKKwYB BAGXVQEFAQEHQI5NLiLRjZy3OfSt1dhCmFyn+fN/QKELUYQetiaoe+MMAwEIB4h+BBgWCAAmFiEE Dg7HY17ghYlni8XN8xYDWXahwukFAmQQUEICGwwFCQHhM4AACgkQ8xYDWXahwukm+wEA8cml4JpK NeAu65rg+auKrPOP6TP/4YWRCTIvuYDm0joBALw98AMz7/qMHvSCeU/hw9PL6u6R2EScxtpKnWof z4oM OpenPGP: id=7126E1DE2F0CE35C770BED01F2C3CC513DB89F66; url="https://keys.openpgp.org/vks/v1/by-fingerprint/7126E1DE2F0CE35C770BED01F2C3CC513DB89F66"; preference=signencrypt Received-SPF: pass client-ip=185.67.36.65; envelope-from=philipk@posteo.net; helo=mout01.posteo.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:315587 Archived-At: --=-=-= Content-Type: text/plain Sergey Organov writes: > Eric S Fraga writes: > >> On Saturday, 27 Jan 2024 at 19:14, Sergey Organov wrote: >>> That's how I use Emacs as well, yet I've built a package based on >>> deskstop.el and session.el a long time ago that I've called desksess.el, >>> and I'm still using it. >> >> Interesting. Are you able to share? > > Sure, > > https://drive.google.com/file/d/1U3TKybt8f7eiOGpyeoW_gFE8dDkFtASf/view?usp=sharing I hope you don't mind me reposting the code here, because I know that many here won't be able or willing to follow that link: --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=desksess.el Content-Transfer-Encoding: quoted-printable ;;; desksess.el -- manage (save/load/etc.) named desktop sessions. ;; ;; Copyright 2005 Sergey Organov ;; ;; Author: Sergey Organov ;; Version: 2.1 ;; Keywords: desktop, session, tools ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;;; Commentary: ;; This package is a wrapper above desktop.el and session.el and depends on ;; them. Unfortunately each of these two nice packages lacks essential ;; features available in another: ;; ;; session.el: ;; - no capability to save non-list globals ;; - no way to save/restore desktop state (to visit files on startup that ;; have been visited before exit) ;; ;; desktop.el: ;; - desktop files scattered over file-system ;; - no recent files menu capability ;; - no capability to save/restore point and other locals when previously ;; visited file is closed and re-opened later ;; ;; The desksess.el tries to use the above two packages to provide more ;; comprehensive and convenient desktop save/restore/switch capabilities. ;; ;; Unlike desktop.el, we store all desktops in a single directory and ;; refer to them by their names, either through menu or commands, so ;; one has single list of all the available desktops. Though loading ;; of arbitrary desktop files is also supported, it's not the primary ;; workflow mode. ;; ;; The package has been extensively tested on Emacs 23.x an 24.4.1. ;;; Installation: ;; 0. Make a backup copy of your ~/.emacs.desktop file if one exists. ;;=20 ;; 1. Copy this file (desksess.el) into a directory where Emacs will ;; find it. Optionally byte-compile the file. ;;=20 ;; 2. Add following lines into your init file (usually ~/.emacs.d/init.el): ;;=20 ;; (require 'desksess) ;; (desksess-initialize) ;; ;; 3. If you wish your session to be saved periodically, add something like ;; this: ;; ;; (add-timeout 300 'desksess-save-current nil 300) ;; ;; 4. Exit then run Emacs again. ;;; Customization: ;; You can still use `customize' to change desktop.el and session.el ;; parameters though some of them are overwritten by this package anyway. ;; Currently there is no `customize' support for the desksess.el itself, but ;; you have the source ;) ;;; Usage: ;; After installation, on the first start desksess will create desktop call= ed ;; "default". If you have used "desktop.el" package before and have ;; ~/.emacs.desktop file in your directory, the file will be read so that ;; "default" desktop looks like your previous one. All your desktops will=20 ;; now be stored in the ~/.desksess directory. ;; ;; To create new fresh desktop and switch to it, use `desksess-new' (the ;; current desktop will be saved automatically before switching). ;; ;; To save the current desktop, use `desksess-save'. ;; ;; To switch between existing desktops, use `desksess-load' (the current ;; desktop will be saved automatically before loading of another one). ;; ;; To clear current desktop (close all the buffers) use `desksess-clear'. ;; ;; Key-bindings: ;; ;; C-c d n desksess-new ;; C-c d l desksess-load ;; C-c d s desksess-save ;; C-c d a desksess-save-as ;; C-c d c desksess-clear ;; C-c d d desksess-show-current ;; C-c d f desksess-forget ;; C-c d e desksess-erase ;; ;; In addition, all the operations are available through menu "Desktop" that ;; should appear on the menu bar. ;; ;; Comments, suggestions, bug-fixes are welcome. ;; ;;; Code: (require 'desktop) (require 'session) (require 'cl) (provide 'desksess) ;; ;; Variables ;; (defvar desksess-history '()) ;; Note: "*Messages*" and "*scratch*" are superfluous in recent ;; Emacsen (since 23.1?) as desktop package already keeps them. (defvar desksess-keep-buffer-names '("*Group*" "*Messages*" "*scratch*" ".n= ewsrc-dribble")) (defvar desksess-menu-max-size 10 "Maximum number of menu items in the sub-menus containing desktops.") (defvar desksess-dir "~/.desksess/" "Name of directory that holds desktop files.") (defvar desksess-sess-subdir ".sess/" "Name of subdirectory inside `desksess-dir' that holds session files.") (defvar desksess-file-env "DESKSESS_FILE" "Environment variable to re-define 'desksess-state-file'") (defvar desksess-state-file "~/.desksess.state" "Name of the file holding desksess state.") (defvar desksess-def-file "default" "Name of the file holding desktop/session by default") ;; ;; Functions ;; ;; Unlike XEmacs, Emacs doesn't provide `enqueue-eval-event', so ;; we define a replacement. (or (functionp 'enqueue-eval-event) (defun enqueue-eval-event (function &rest args) (apply 'run-with-timer 0 nil function args))) (defun desksess-kill-invisible-buffer (buf) "Kill buffer BUF if it's invisible and not in `desksess-keep-buffer-names= '. Return nil." (cond ((member (buffer-name buf) desksess-keep-buffer-names) nil) ((get-buffer-window buf 'visible) nil) (t (kill-buffer buf) nil))) (defun desksess-kill-buffer (buf) "Kill buffer BUF if it's not in `desksess-keep-buffer-names'. Return nil." (cond ((member (buffer-name buf) desksess-keep-buffer-names) nil) (t (kill-buffer buf) nil))) ;; Our original version, kept for reference. Dunno if killing invisible buf= fers ;; actually speeds-up anything in recent Emacsen. (defun desksess-do-clear0 (&optional ignored) "Clear current desktop." ;; For speed-up kill invisible buffers first (mapc 'desksess-kill-invisible-buffer (buffer-list)) (mapc 'desksess-kill-buffer (buffer-list)) (delete-other-windows) (setq kill-ring nil kill-ring-yank-pointer nil search-ring nil search-ring-yank-pointer nil regexp-search-ring nil regexp-search-ring-yank-pointer nil)) (defun desksess-do-clear (&optional ignored) "Clear current desktop." (interactive) (let ((desktop-restore-frames nil) (desktop-clear-preserve-buffers (delete-dups (append desktop-clear-preserve-buffers (mapcar 'regexp-quote desksess-keep-buffer-names))))) (desktop-clear))) (defun desksess-clear () "Prompt for confirmation then clear current desktop." (interactive) (when (yes-or-no-p (format "Clear current desktop (%s): " desktop-base-file-name)) (enqueue-eval-event 'desksess-do-clear nil) (top-level))) (defun desksess-desktop-name-for-menu () (format "`%s'" desktop-base-file-name)) (defun desksess-general-menu-filter (menu-items function) "Build menu from `desksess-history'." (let ((menu nil) (files (mapcar 'abbreviate-file-name desksess-history)) (num-items 0) elem name) (while (and files (<=3D num-items desksess-menu-max-size)) (setq elem (car files) files (cdr files) name (if (string-match (file-name-directory elem) (desksess-dir)) (file-name-nondirectory elem) elem)) (when (not (string-equal elem (desksess-desk-save-file))) (setq num-items (1+ num-items)) (push (vector name (list function elem) t) menu))) (or (> num-items 0) (push [ "none" nil nil ] menu)) (append menu-items (nreverse menu)))) (defun desksess-select-menu-filter (menu-items) "Build \"Desktop|Select\" menu from `desksess-history'." (desksess-general-menu-filter menu-items 'desksess-load)) (defun desksess-forget-menu-filter (menu-items) "Build \"Desktop|Forget\" menu from `desksess-history'." (desksess-general-menu-filter menu-items 'desksess-forget)) (defun desksess-erase-menu-filter (menu-items) "Build \"Desktop|Erase\" menu from `desksess-history'." (desksess-general-menu-filter menu-items 'desksess-erase)) (defun desksess-read-file-name (prompt) (let* ((dir (desksess-initial-desktop-dir)) (file (desksess-initial-desktop-file)) (default-directory dir) (file-name-history desksess-history)) (let ((file-name (read-file-name prompt dir nil t file))) (setq desksess-history (mapcar 'abbreviate-file-name file-name-histor= y)) (abbreviate-file-name file-name)))) (defun desksess-read-file-name-1 (prompt) (let* ((dir (desksess-initial-desktop-dir)) (default-directory dir) (file-name-history desksess-history)) (let ((file-name (read-file-name prompt dir nil nil))) (setq desksess-history (mapcar 'abbreviate-file-name file-name-histor= y)) (abbreviate-file-name file-name)))) (defun desksess-forget (file-name) "Remove `file-name' from `desksess-history'." (interactive (list (desksess-read-file-name "Desktop file to forget: "))) (setq desksess-history (delete file-name desksess-history))) (defun desksess-erase (file-name) "Remove `file-name' from `desksess-history'." (interactive (list (desksess-read-file-name "Desktop file to erase: "))) (when (and (yes-or-no-p (format "Erase desktop `%s'? " file-name)) (or (not (string-equal file-name (desksess-desk-save-file))) (yes-or-no-p (format "Desktop `%s' is current. Erase anywa= y? " file-name)))) (let* ((dir (file-name-directory file-name)) (desktop-base-file-name (file-name-nondirectory file-name)) (desksess-dir dir)) (unwind-protect (delete-file file-name) (unwind-protect (delete-file (desksess-sess-save-file)) (setq desksess-history (delete file-name desksess-history))))))) (defun desksess-dir () "Return the name of directory that holds desktop files." (file-name-as-directory desksess-dir)) (defun desksess-sess-dir () "Return the name of directory that holds session files." (file-name-as-directory (concat (desksess-dir) desksess-sess-subdir))) (defun desksess-desk-save-file () "Return full name of the file holding current desktop." (concat (desksess-dir) (file-name-nondirectory desktop-base-file-name))) (defun desksess-sess-save-file () "Return full name of the file holding current session." (concat (desksess-sess-dir) (file-name-nondirectory desktop-base-file-name))) (defun desksess-show-current () "Show current desktop name in the echo area." (interactive) (message "Current desktop is: %s" (desksess-desk-save-file))) (defun desksess-sess-load () (when (file-readable-p session-save-file) (load session-save-file t nil t))) (defun desksess-ensure-dirs-created () (or (file-directory-p desksess-dir) (make-directory desksess-dir t)) (or (file-directory-p (desksess-sess-dir)) (make-directory (desksess-sess-dir) t))) (defun desksess-save (&optional file-name) "Save current desktop to `file-name'. If `file-name' is not specified, save to the current desktop file." (interactive) (or file-name (setq file-name (desksess-desk-save-file))) (let ((dir (file-name-directory file-name))) (setq file-name (file-name-nondirectory file-name)) (let* ((default-directory dir) (desktop-base-file-name file-name) ;; Even though session.el suggests we set `desktop-globals-to-sa= ve' ;; to '(desktop-missing-file-warning), we don't do that as we do= n't ;; want this variable to be desktop-local. (desktop-globals-to-save '(compile-command)) (desktop-restore-eager nil) (desksess-dir dir) (session-save-file (desksess-sess-save-file))) (desksess-ensure-dirs-created) ;; Kludge to fix a bug in the `session-save-session'. The latter sets ;; current buffer to the last in the buffer list before creating ;; temporary buffer, thus temporary buffer inherits `default-director= y' ;; from the last buffer in the list. At some conditions resulting ;; `default-directory' becomes nil, `file-exists-p' signals error, ;; temporary buffer doesn't get killed. As result not only current ;; evaluation but also all subsequent evaluations of ;; `session-save-session' fail. To fix this we create our own tempora= ry ;; buffer with the same name `session-save-session' would create, so ;; that it gets our buffer with non-nil default directory. (save-excursion (let ((tmp-buf (set-buffer (get-buffer-create " session "))) (default-directory dir)) (unwind-protect (session-save-session) (kill-buffer tmp-buf)))) (desktop-save dir)) (setq session-save-file (desksess-sess-save-file)) (setq desktop-base-file-name file-name) (setq desksess-dir dir)) (desksess-state-save) (message "Desktop `%s' saved." desktop-base-file-name)) (defun desksess-kill () (ignore-errors (desksess-save)) ;; If we own it, we don't anymore. (when (eq (emacs-pid) (desktop-owner)) (desktop-release-lock))) (defun desksess-save-as (file-name) "Save current desktop to the `file-name'. Make `file-name' the default desktop." (interactive (list (desksess-read-file-name-1 "Desktop file: "))) (when (and (stringp file-name) (setq file-name (session-abbrev-file-name file-name)) (or (not (file-exists-p file-name)) (yes-or-no-p (format "File `%s' exists; overwrite? " file-name)))) (desksess-save file-name))) (defun desksess-save-current (&optional ignored) "Save current desktop. This function is intended to be used as argument to `add-timeout'. Argument is ignored." (desksess-save) (message nil)) (defun desksess-read (file-name) "Read desktop from `file-name'." (save-some-buffers) (let ((dir (file-name-directory file-name))) (setq file-name (file-name-nondirectory file-name)) (desksess-do-clear) (let* ((default-directory dir) (desktop-base-file-name file-name) (desktop-missing-file-warning nil) (desktop-load-locked-desktop t) (desktop-restore-frames nil) (desktop-restore-eager nil) (desksess-dir dir) (session-save-file (desksess-sess-save-file))) ;; Originally, we first called 'desksess-sess-load' then 'desktop-rea= d'. ;; However, 'desktop-read' breaks 'file-name-history' because 'sessio= n' ;; package installs 'session-set-file-name-history' into 'find-file-h= ooks'. ;; To restore saved 'file-name-history' we now call 'desktop-read' fi= rst, ;; then correct 'file-name-history' is loaded by 'desksess-sess-load'. (desktop-read dir)=20 (desksess-sess-load)) (setq session-save-file (desksess-sess-save-file)) (setq desktop-base-file-name file-name) (setq desksess-dir dir)) (desksess-state-save) (desksess-show-current)) (defun desksess-initial-desktop-file () (let ((name (second desksess-history))) (and name (file-name-nondirectory name)))) (defun desksess-initial-desktop-dir () (let ((name (second desksess-history))) (or (and name (file-name-directory name)) (desksess-dir)))) (defun desksess-do-load (file-name) "Save current desktop and load the new one from `file-name'." (let ((old-file-name (desksess-desk-save-file))) (desksess-save) (condition-case err (desksess-read file-name) (error (desksess-read old-file-name) ; restore the old desktop (error "Failure to load desktop `%s': %s" file-name err))) (setq desksess-history (append (list file-name) (delete file-name desksess-history))))) (defun desksess-load (file-name) "Load desktop. Save current desktop and load the new one from `file-name'. When called interactively first ask for desktop to be loaded." (interactive (list (desksess-read-file-name "Desktop file to load: "))) (when (and (stringp file-name) (file-regular-p file-name) (file-readable-p file-name) (setq file-name (session-abbrev-file-name file-name)) (not (string-equal file-name (desksess-desk-save-file)))) (enqueue-eval-event 'desksess-do-load file-name) (top-level))) (defun desksess-do-new (file-name) "Save current desktop, then create and switch to the fresh desktop." (desksess-save) (let ((dir (file-name-directory file-name))) (setq file-name (file-name-nondirectory file-name)) (let* ((default-directory dir) (desktop-base-file-name file-name) (desksess-dir dir) (session-save-file (desksess-sess-save-file))) (desksess-do-clear) (desksess-sess-load)) (setq session-save-file (desksess-sess-save-file)) (setq desktop-base-file-name file-name) (setq desksess-dir dir)) (desksess-state-save) (desksess-show-current)) (defun desksess-new (file-name) "Create new empty desktop. Save current desktop, then create and switch to the fresh desktop. When called interactively, first ask for desktop to be created." (interactive (list (desksess-read-file-name-1 "New desktop file: "))) (when (and (stringp file-name) (setq file-name (session-abbrev-file-name file-name)) (or (not (file-exists-p file-name)) (yes-or-no-p (format "File `%s' exists; overwrite? " file-name)))) (enqueue-eval-event 'desksess-do-new file-name) (top-level))) (defun desksess-add-submenu () (add-submenu nil '("Desktop" ("Select" :included (second desksess-history) :filter desksess-select-menu-filter) [ "New..." desksess-new t ] [ "Load..." desksess-load t ] "-" [ "Save" desksess-save :suffix (desksess-desktop-name-for-menu) t nil ] [ "Save As..." desksess-save-as t ] "-" [ "Clear" desksess-clear :suffix (desksess-desktop-name-for-menu) t nil ] ( "Forget" :included (second desksess-history) :filter desksess-forget-menu-filter) ( "Erase" :included (second desksess-history) :filter desksess-erase-menu-filter) )) (and (featurep 'xemacs) (set-menubar-dirty-flag))) (defun desksess-bind-keys () (interactive) (global-set-key [(control c) ?d ?n] 'desksess-new) (global-set-key [(control c) ?d ?l] 'desksess-load) (global-set-key [(control c) ?d ?s] 'desksess-save) (global-set-key [(control c) ?d ?a] 'desksess-save-as) (global-set-key [(control c) ?d ?c] 'desksess-clear) (global-set-key [(control c) ?d ?d] 'desksess-show-current) (global-set-key [(control c) ?d ?f] 'desksess-forget) (global-set-key [(control c) ?d ?e] 'desksess-erase) ) (defun desksess-state-save () (save-excursion (let ((buffer (get-buffer-create " *desksess* "))) (unwind-protect (progn (set-buffer buffer) (erase-buffer) (insert ";;; Autogenerated by `desksess.el' on " (current-time-string) "\n" (format "(setq-default %S %S)\n" 'desktop-base-file-name desktop-base-file-name) (format "(setq-default %S %S)\n" 'desksess-dir desksess-dir) (format "(setq-default %S '%S)\n" 'desksess-history (mapcar 'abbreviate-file-name deskse= ss-history))) (write-region (point-min) (point-max) desksess-state-file nil 0= )) (kill-buffer buffer))))) (defun desksess-state-load () (setq desktop-base-file-name desksess-def-file) (load desksess-state-file t t t) (desksess-ensure-dirs-created)) (defun desksess-fix-session-menu () (when (and (featurep 'xemacs) (car (find-menu-item current-menubar '("Edit" "Yank...recently killed")))) (add-submenu '("Edit") '("Yank...recently killed" :included kill-ring :filter session-yank-menu-filter) "Undo"))) (defun desksess-find-file-hook () (unless (or (and (boundp 'revert-buffer-in-progress-p) revert-buffer-in-progress= -p) (and (boundp 'after-find-file-from-revert-buffer) after-find-file-fr= om-revert-buffer) (session-find-file-hook)))) ;; Replacement for desktop's obsolete desktop-load-default (defun my-desktop-load-default () "Load the `default' start-up library manually. Also inhibit further loading of it." (unless inhibit-default-init ; safety check (load "default" t t) (setq inhibit-default-init t))) (defun desksess-after-emacs-init () "Function to be evaluated after emacs reads `.emacs'." (interactive) ;; Proceed with initialization (let ((name (getenv desksess-file-env))) (if name (setq desksess-state-file name))) (my-desktop-load-default) (desksess-state-load) (desksess-bind-keys) (desksess-add-submenu) (add-to-list 'session-globals-exclude 'desksess-history) (setq session-successful-p t) (desksess-fix-session-menu) (let ((def-name "~/.emacs.desktop") (file-name (desksess-desk-save-file))) (if (or (file-readable-p file-name) (not (file-readable-p def-name))) (progn (setq inhibit-startup-message t) (desksess-read file-name)) (desksess-read def-name) (desksess-save-as file-name))) (remove-hook 'kill-emacs-hook 'session-save-session) (remove-hook 'kill-emacs-hook 'desktop-kill) (add-hook 'kill-emacs-hook 'desksess-kill) (remove-hook 'find-file-hook 'session-find-file-hook) (add-hook 'find-file-hook 'desksess-find-file-hook t) ) (defun desksess-initialize () "Initialize `desksess'. Add (desksess-initialize) to your `.emacs' to initialize `desksess' at startup." ;(if (boundp 'recentf-initialize-file-name-history) ; (setq recentf-initialize-file-name-history nil)) (session-initialize) ;; Put our hook late in the chain so that we can tweak a few things ;; that session.el does in its after-init-hook. (add-hook 'after-init-hook 'desksess-after-emacs-init t) (add-timeout 300 'desksess-save-current nil 300) ) ;;(defun desksess-initialize ()) ;;(desksess-after-emacs-init) ;;(load "~/.emacs.d/init.el") ;;(run-hooks 'after-init-hook) ;; (defun desktop-clear () ;; "Empty the Desktop. ;; This kills all buffers except for internal ones and those with names mat= ched by ;; a regular expression in the list `desktop-clear-preserve-buffers'. ;; Furthermore, it clears the variables listed in `desktop-globals-to-clear= '. ;; When called interactively and `desktop-restore-frames' is non-nil, it al= so ;; deletes all frames except the selected one (and its minibuffer frame, ;; if different)." ;; (interactive) ;; (desktop-lazy-abort) ;; (setq desktop-io-file-version nil) ;; (dolist (var desktop-globals-to-clear) ;; (if (symbolp var) ;; (set-default var nil) ;; (set-default var (eval (cdr var))))) ;; (let ((preserve-regexp (concat "^\\(" ;; (mapconcat (lambda (regexp) ;; (concat "\\(" regexp "\\)"= )) ;; desktop-clear-preserve-buffe= rs ;; "\\|") ;; "\\)$"))) ;; (dolist (buffer (buffer-list)) ;; (let ((bufname (buffer-name buffer))) ;; (if bufname (message "OK : %s" buffer) (message "NUL?: %S" buff= er)) ;; (unless (or (null bufname) ;; (eq (aref bufname 0) ?\s) ;; Don't kill internal buf= fers ;; (string-match-p preserve-regexp bufname)) ;; (kill-buffer buffer))))) ;; (delete-other-windows) ;; (when (and desktop-restore-frames ;; ;; Non-interactive calls to desktop-clear happen before desktop-re= ad ;; ;; which already takes care of frame restoration and deletion. ;; (called-interactively-p 'any)) ;; (let* ((this (selected-frame)) ;; (mini (window-frame (minibuffer-window this)))) ; in case they differ ;; (dolist (frame (sort (frame-list) #'frameset-minibufferless-first-= p)) ;; (condition-case err ;; (unless (or (eq frame this) ;; (eq frame mini) ;; ;; Don't delete daemon's initial frame, or ;; ;; we'll never be able to close the last ;; ;; client's frame (Bug#26912). ;; (if (daemonp) (not (frame-parameter frame 'clien= t))) ;; (frame-parameter frame 'desktop-dont-clear)) ;; (delete-frame frame)) ;; (error ;; (delay-warning 'desktop (error-message-string err)))))))) (defun osv-buffer-list () (interactive) (dolist (buffer (buffer-list)) (let ((bufname (buffer-name buffer))) (if bufname (message "OK : %S" buffer) (message "NUL?: %S" buffer)))= )) --=-=-=--