2

I have customized tramp-remote-path in my .emacs.d/init.el with

(custom-set-variables  '(tramp-remote-path
    (quote
     (tramp-own-remote-path))))

but when tramp is loaded the value of tramp-remote-path is set to the default value. For example after I open a remote file the value of tramp-remote-path is (tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin" ...)

I have verified this behaviour even when the above customization is the only code in init.el with both 24.5 and 25.0.

Why does this happen?

How can I prevent it and make my customization stick?

Since tramp-remote-path is defined using defcustom, it seems like it should be customizable with custom-set-variables

  • Try dropping the (quote ...) around the sexp (tramp-own-remote-path). – Drew Jun 28 '16 at 20:30
  • @Drew That seems to make no difference – Daniel Mahler Jun 28 '16 at 20:45
  • And try removing the parens around tramp-own-remote-path. Better yet, use M-x customize-option to customize the option, instead of trying to roll your own code to customize it. – Drew Jun 28 '16 at 20:46
  • @Drew The code in the question was saved from the customize interface. – Daniel Mahler Jun 28 '16 at 21:17
  • 1
    Please M-x report-emacs-bug. – Stefan Jul 5 '16 at 7:53
4
+50

Short answer: Don't edit custom-set-variables form by hand.

Tramp must be loaded for custom-set-variables to work. Either load tramp before custom-set-variables:

(require 'tramp)
(custom-set-variables  '(tramp-remote-path
    (quote
     (tramp-own-remote-path))))

Or see Michael's answer for a way to tell customize to load tramp first. Note that using M-x customize-variable RET tramp-remote-path RET creates a correct custom-set-variables entry, of the form suggested by Michael.


Longer answer

The root of the problem seems to be in tramp's custom ###;;;tramp-autoload annotation. This tramp-specific mechanism more or less breaks basic custom-set-variables forms.

In normal operation, when you run customize-set-variables, Emacs does one of two things: if the variable already exists in context it sets it, and if it doesn't, it records the value (using (set symbol value)), relying on the customize machinery to use that saved value after the variable is declared (through a defcustom).

Then, when Emacs evaluates the corresponding defcustom (when loading the corresponding package, for example), the customize machinery checks whether the symbol being defcustomed already has a value pending (using (get symbol 'saved-value)), and sets the symbol to that value if so. If there is no such pending value, it uses the value provided by the defcustom form (the default value).

As an exception, however, the defcustom implementation also checks that it isn't overriding an already set value. That is, if the variable has already been declared and given a value, then it's value is preserved. To check whether such a default value exists, customize calls default-toplevel-value. If there already is a default value set, it leaves the variable untouched.

The function that does this is custom-initialize-reset.

Well, in your case, the problem is precisely this exception. If you open emacs/lisp/net/tramp-loaddefs.el, you'll see the following:

(defvar tramp-remote-path '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin" "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin" "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin" "/opt/bin" "/opt/sbin" "/opt/local/bin") "\

This is a way to forward declare tramp-remote-path, but as a side effect it declares and gives a default value to tramp-remote-path. That's fine as far as custom-set-variables is concerned, but not as far as defcustom is concerned. Thus, when the actual defcustom for tramp-remote-path is loaded, the aforementioned exception kicks in, and customize politely preserves the value set by the defvar, thereby ignoring your customization.

You can verify that this is the issue by adding

(defvar tramp-remote-path nil)

to your .emacs, before the actual call to custom-set-variables. That should fix it (because now custom-set-variable will think the variable exists), but I don't know enough about customize to recommend this solution.

2

Fascinating. I can exactly reproduce what you're running in to if I try to use the customization interface. However! I can successfully change the value of tramp-remote-path by skipping the customization interface, either of two different ways.

First, tramp expects tramp-remote-path to be a list, so my inclination is to do this (in my init.el):

(require 'tramp)
(add-to-list 'tramp-remote-path "/home/gastove/")

Or, setting to a single directory:

(require 'tramp)
(setq tramp-remote-path '("/home/gastove"))
  • This solves the main problem, but I would still like to understand why/how tramp resets customizations on load. Currently I am trying to keep configuration in customize when I can. – Daniel Mahler Jul 3 '16 at 1:49
2

tramp.el must be loaded indeed when a Tramp user option shall be set. The proper way to do this is

(custom-set-variables
 '(tramp-remote-path (quote (tramp-own-remote-path)) nil (tramp)))

Maybe this shall be described in the Tramp manual.

  • Michael, I upvoted your answer to get it closer to the top, but isn't that arguably a bug? Also, is there a way to get such a form from the customize interface (with the extra nil (tramp)? Normally custom-set-variables forms are not written by hand. – Clément Apr 6 '17 at 20:34
  • I suppose if you customize the variable in the customize interface, and if you save your settings then, you will get such a custom-set-variables call in your .emacs. I've described it this way, because many people hesitate to use the customize interface. – Michael Albinus Apr 7 '17 at 11:18
  • Oh, you're right! Thanks. I'll update my own answer. – Clément Apr 7 '17 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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