0

I share an .emacs file on two machines. About once per month I find that Emacs on one machine or the other fails to load the file. Just today the error was:

File error: https://melpa.org/packages/with-editor-20220412.1340.tar, Not found

I'm not looking for a solution to this particular error, rather, I would like to know **how to make the .emacs file more robust? So that when e.g. Melpa is down, or whatever the cause of this error turns out to be, the rest of the file continues loading.

Here is the current state of my file, what better-practices should I be making a habit out of?

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

; Add the NonGNU ELPA package archive
; https://emacs.amodernist.com/
(add-to-list 'package-archives  '("nongnu" . "https://elpa.nongnu.org/nongnu/"))


;; Git client
; https://emacs.amodernist.com/
(unless (package-installed-p 'magit)
  (package-install 'magit))
; Bind the `magit-status' command to a convenient key.
(global-set-key (kbd "C-c g") #'magit-status)
; Show word-granularity differences within diff hunks
(setq magit-diff-refine-hunk t)


; Indication of local VCS changes
; https://emacs.amodernist.com/
(unless (package-installed-p 'diff-hl)
  (package-install 'diff-hl))
; Update the highlighting without saving
(diff-hl-flydiff-mode t)


; JSON Support
; https://emacs.amodernist.com/
(unless (package-installed-p 'json-mode)
  (package-install 'json-mode))


; Markdown support
; https://emacs.amodernist.com/
(unless (package-installed-p 'markdown-mode)
  (package-install 'markdown-mode))


; Put backup files in a specific directory
; Backup files are of the form filename~
; https://stackoverflow.com/questions/151945/how-do-i-control-how-emacs-makes-backup-files
(setq backup-directory-alist `(("." . "~/.emacs-saves/")))
(setq backup-by-copying t)


; Put autosave files in a specific directory
; Autosave files are of the form #filename#
; https://www.gnu.org/software/emacs/manual/html_node/emacs/Auto-Save-Files.html
; https://github.com/emacscollective/no-littering
(setq auto-save-file-name-transforms `((".*", "~/.emacs-saves/" t)))


; Enable recent files
; Does seem to slow down startup times!
; https://stackoverflow.com/questions/3527150/open-recent-in-emacs
(require 'recentf)
(recentf-mode t)


; Open only a single window.
; https://stackoverflow.com/questions/29915133/how-can-i-open-the-files-only-in-a-specific-window-in-emacs
(setq inhibit-splash-screen t)


; Start maximized
(add-to-list 'default-frame-alist '(fullscreen . maximized))


; Vim Emulation
; https://emacs.amodernist.com/
(unless (package-installed-p 'evil)
  (package-install 'evil))


; Proper Tab-key behaviour in org-mode
; Must be set before enabling evil
; https://stackoverflow.com/questions/22878668/emacs-org-mode-evil-mode-tab-key-not-working
(setq evil-want-C-i-jump nil)


; Enable Evil
(require 'evil)
(evil-mode 1)


; Enable org-evil
; https://github.com/GuiltyDolphin/org-evil
(require 'org-evil)


; esc quits pretty much anything (like pending prompts in the minibuffer)
; https://modulitos.com/blog/lightning-intro-to-emacs-using-evil-mode-and-org-mode/
(define-key evil-normal-state-map [escape] 'keyboard-quit)
(define-key evil-visual-state-map [escape] 'keyboard-quit)
(define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)


; Ctrl-C W Toggle word wrap
; https://emacs.stackexchange.com/questions/30171/how-do-i-toggle-soft-wrapped-lines-in-org-mode
(global-set-key (kbd "C-c w") 'toggle-truncate-lines)


; Run these options only in org-mode
; https://modulitos.com/blog/lightning-intro-to-emacs-using-evil-mode-and-org-mode/
(add-hook 'org-mode-hook (lambda()


    ; Get Firefox link with Ctrl-C F
    ; https://stackoverflow.com/questions/8397319/how-to-bind-a-key-to-run-a-shell-command-in-dired-emacs
    (defun ff-link-org ()
        "Get Firefox link in Org mode format"
        (interactive)
        (shell-command "xdotool search 'Navigator' windowactivate --sync key --clearmodifiers Escape y o ; xdotool keydown alt key Tab ; xdotool keyup alt")
    )
    (global-set-key (kbd "C-c f") 'ff-link-org)


    ; Reenable <sTAB
    ; https://github.com/syl20bnr/spacemacs/issues/11798
    (require 'org-tempo)


    ; Indent org-mode files nicely
    ; https://modulitos.com/blog/lightning-intro-to-emacs-using-evil-mode-and-org-mode/
    (local-set-key (kbd "C-c C-c") 'org-table-align)
    (local-set-key (kbd "C-c C-f") 'org-table-calc-current-TBLFM)
    (org-indent-mode t)


    ; Proper RTL in org-mode
    ; https://emacs.stackexchange.com/questions/71371/rtl-text-with-left-alignment-and-reversed-line-wrapping-in-org-mode
    ;(setq bidi-paragraph-direction 'right-to-left)
    (setq bidi-paragraph-direction nil)


    ; Proper wrapping!
    (visual-line-mode 1)


) )


(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(ansi-color-faces-vector
   [default default default italic underline success warning error])
 '(ansi-color-names-vector
   ["#242424" "#e5786d" "#95e454" "#cae682" "#8ac6f2" "#333366" "#ccaa8f" "#f6f3e8"])
 '(blink-cursor-mode nil)
 '(custom-enabled-themes '(wheatgrass))
 '(org-agenda-files '("~/beer.org"))
 '(package-selected-packages '(csv-mode org-evil dash)))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "Source Code Pro" :foundry "ADBO" :slant normal :weight normal :height 143 :width normal)))))
3
  • 1
    Your dot emacs should not be failing at all. This is atypical behavior. I will look at your dot emacs and see if I can find anything.
    – Edman
    May 5, 2022 at 19:50
  • The question is too broad. And it mixes in specific info without asking anything specific about that info. Please try to pose a specific question that calls for specific answers.
    – Drew
    May 6, 2022 at 15:01
  • Generally (IMHO) its not a good idea to put package-install calls in your init. This implies that you could get some install (melpa) error at the time (a) you add a new package to your mix; plus (b) you're on a different machine. After that it should run stably (until next package choice)
    – Rusi
    May 6, 2022 at 15:04

6 Answers 6

3

The specific issue you are having is that you are calling package-install without ensuring that the package archive cache is up to date. One way to avoid this issue would be something like this:

(unless (package-installed-p 'evil)
  (package-refresh-contents)
  (package-install 'evil))

An alternative is to install the very wonderful use-package package after which you could do

(use-package evil
  :ensure t)
5

I'm not looking for a solution to this particular error, rather, I would like to know how to make the .emacs file more robust? So that when e.g. Melpa is down, or whatever the cause of this error turns out to be, the rest of the file continues loading.

It doesn't really work like that.

Emacs isn't like programs with limited pre-defined collections of user settings which tend to read their config files reliably (unless you've put some kind of completely invalid syntax into the file, perhaps).

You configure Emacs by writing a program in the Emacs Lisp programming language. This immediately makes your question akin to asking (of programming in general): "How can I write a program so that it still works even when there are errors?" -- but a program with errors isn't really working.

Emacs Lisp does have error-handing facilities of course, but wrapping these around entire programs in a blanket fashion is almost certainly ill-advised.

Ultimately, you ought to deal with errors in the programs you write either by writing better code, or handling specific errors in specific cases.

Therefore...

I'm not looking for a solution to this particular error

I suggest that you are, on this occasion, looking for a solution to this particular error, as you should handle errors on a case-by-case basis.

My question to you here is: "Why is your config trying to install a package at all?" If the package is supposed to be part of your config, I recommend that you include it in your config as standard, rather than trying to install it at some arbitrary time in the future.

If you keep your config in a known working state, it's dramatically less likely to fail on you out of the blue.

2

This approach works for preventing startup disaster if any package has trouble. Sometimes you pull down a 3rd party package and it does not play nice which what you currently have. It produces an error message if anything goes wrong with the load.

The example is for rainbow-delimiters; I use this for all the packages loaded in the .emacs.

A symbol at the top of the .emacs is used to control whether a package is loaded or not; in this example its called 'load-rainbow-delimiters'.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; rainbow-delimiters
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(message "reached before rainbow delimiters")
(when  load-rainbow-delimiters;
    (unless
      (ignore-errors ;if an error occurs return nil
        (add-to-list 'load-path "~/.emacs.d/rainbow-delimiters/")
        (add-hook 'emacs-lisp-mode-hook #'rainbow-delimiters-mode)
        (add-hook 'verilog-mode-hook #'rainbow-delimiters-mode)
        (add-hook 'vhdl-mode-hook #'rainbow-delimiters-mode)
        (add-hook 'ruby-mode-hook #'rainbow-delimiters-mode)
        (add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
        (require 'rainbow-delimiters)
        t)
      (message "--Error in load-rainbow-delimiters")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1

I have a system that lets me have one ~/.emacs.d/ source tree, maintained under version control, that works on all the hosts, operating systems and architectures I use: Gnu/Linux, darwin (Mac OS), and Cygwin for when I am forced to use Windows. I used to include Solaris, and it would be easy enough to adapt to, say, A/IX.

From my init.el I load in turn files called host.el and os.el. These files are not under version control; instead, on each host, they are symbolic links resolving to host- and OS-specific files which are maintained under version control. Those files contain any quirks and customizations specific to a single host or platform.

;; Do main/common/standard init stuff
;; ...
(load "os.el")
(load "host.el")

On host host5, running a Gnu/Linux distro, in a shell, with working directory ~/.emacs.d/:

$ ls -l
...
host.el -> host5.el
os.el -> os.gnu_linux.el
...

(I actually use something a little more sophisticated, which also transparently selects among available candidates based on Emacs' major version, but that is beyond the scope of this question.)

1

In addition to using ignore-errors, you could use condition-case to handle specific errors better, or to simply print a message when there is one:

(condition-case err
    (package-install 'foo)
  (error (message "%s" (error-message-string err))
         nil))
1

The problem could be some broken package is downloaded because your network is not reliable.

Here is solution.

Once you've installed all packages, create a local package repository (say "~/myelpa/") from installed packages using https://github.com/redguardtoo/elpa-mirror

This thing need only be done once.

Use (add-to-list 'package-archives '("myelpa" . "~/myelpa/") t) to replace (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)

Then your two machines can use local repository from now on. You can switch to any remote repository any time when you have reliable network.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.