14

Typically I start emacs with the GUI, and start a server right away with (server-start). Now I can easily open documents into my existing emacs session from terminal via emacsclient -n <file>, or from the File Browser.

From time to time, however, I want to run emacs inside my terminal using emacsclient -t. This happens most often when writing git commit logs or performing other very small tasks. In those instances, the fact that my init file was loaded in a GUI instance of emacs means that I don't get any of my customizations that are specific to TTY emacs.

I know that I can run

emacs -nw -q -l "some-custom-init-file.el"

but that will reload all of the packages every time. Can I have the best of both worlds? Is there a way to set up a "TTY daemon" so that I can use separate customizations for running inside the terminal versus visiting the file in an existing emacs window?

nispio
  • 8,175
  • 2
  • 35
  • 73
  • 1
    Can you point to an example of your customisations that are different between TTY and GUI mode? – stsquad Sep 23 '14 at 22:41
  • 1
    @stsquad One really simple one is that I use a left fringe in GUI mode, but since the fringe does not exist in the TTY mode, there is no space between the line numbers and the text. This can be fixed with `(setq linum-format "%d ")` in the TTY customization file. Also, my color theme always looks strange in TTY mode, so I will definitely choose a different theme for the TTY. I actually don't have that many differences at the moment, but now that I know that I can have different servers, the list may grow. – nispio Sep 23 '14 at 22:59
  • @nispio: I suggest you `M-x report-emacs-bug` and request new features such as the ability to have different face themes in TTY and in GUI frames (actually, a theme can specify completely different colors for those different kinds of frames, so you could also adjust your theme). Using several daemons for those separate cases is just a workaround for a lack of corresponding functionality in Emacs. – Stefan Jun 17 '17 at 17:01

3 Answers3

14

Use emacs --daemon=your-server-name -l "custom-init-file" to start a new server and emacsclient -nw -s your-server-name to connect to it from the terminal itself. The section on Using Emacs as a server in the manual has more initialization options.

Vamsi
  • 3,916
  • 22
  • 35
  • This works! Is there a good way to kill a server started this way besides hunting for and deleting the server file? – nispio Sep 23 '14 at 23:01
  • (I had to add a `-q` switch to keep my default `init.el` from running before the custom init file.) – nispio Sep 23 '14 at 23:05
  • 2
    Does `emacsclient -s your-server-name -e "(kill-emacs)"` do what you want ? The above just calls emacsclient and evals `(kill-emacs)`. You could replace `(kill-emacs)` with `(save-buffers-kill-emacs)` as well. – Vamsi Sep 23 '14 at 23:25
  • I used to have a common init.el for both terminal and gui emacs and loaded seperate custom files for individual customizations. Hence I missed the `-q` – Vamsi Sep 23 '14 at 23:28
  • 1
    This solutions also fixed an issue I had when using 'emacsclient -t' with mutt and, in a separate workspace, 'emacsclient -c'. Simply put: daemon was crashing when 'emacsclient -c' was fired up before 'emacsclient -t'. Thank you, Vamsi – Boccaperta-IT Sep 24 '14 at 15:54
7

In addition to @Vamsi's answer, you can get many of the same benefits while running only a single server by attaching advice to make-frame-command.

For example, while running in the terminal I want the background color to be black (which maps to #202020) but I want to use #202020 in a graphical mode. I implemented this with:

(defadvice make-frame-command (after make-frame-change-background-color last activate)
  "Adjusts the background color for different frame types. 
Graphical (X) frames should have the theme color, while terminal frames should match the terminal color (which matches the theme color...but terminal frames can't directly render this color)"
    (if (display-graphic-p)
        (set-background-color "#202020")
      (set-background-color "black")))

You can get a lot of mileage out of this using make-variable-frame-local (set-background-color in the above is already frame-local).

I don't know if this is the best pattern, but if you have relatively few differences between TTY-mode and X-mode Emacs it can make configuration management easier.

The above code was pulled from my .emacs.d.

vfclists
  • 1,347
  • 1
  • 11
  • 28
J David Smith
  • 2,635
  • 1
  • 16
  • 27
  • I had been wondering if there was some way to "detect" which mode I am in on a per-frame basis. – nispio Sep 24 '14 at 01:03
  • 1
    This'll do it. `(display-graphic-p)` gives `t` if the *current frame* is graphical, `nil` otherwise. Because frames cant be moved between graphical and not (afaik), attaching advice to frame creation insures that the desired state is reached for the given frame. – J David Smith Sep 24 '14 at 01:15
  • This is definitely the most convenient answer. – Malabarba Sep 24 '14 at 06:22
3

You don't need an advice to change settings of different frames running in the same emacs daemon. Just use the hook after-make-frame-functions like so

(defvar my/ttheme 'tango-dark)
(defvar my/gtheme 'tango)
(defun my/frame-configuration (frame)
  "configure the current frame depending on the frame type"
  (with-selected-frame frame
    (if (display-graphic-p)
        (progn
          (message "after-make-frame-functions hook: window system")
          (set-frame-size frame 115 60)
          ;; other settings for a graphical frame
          (load-theme my/gtheme t))
      (message "after-make-frame-functions hook: text console")
      (load-theme my/ttheme t)
      (set-frame-parameter frame 'menu-bar-lines 0))))

(add-hook 'after-make-frame-functions 'my/frame-configuration)

;; normal start without daemon
(if (not (daemonp))
  (my/frame-configuration (selected-frame)))

Defining it this way has the added bonus, that it set's the desired frame-configuration even if you don't start in daemon mode.

Unfortunately load-theme is not frame local and so the other frames get coloured too if you really use different themes for text and graphical frames.

Bonus information: configure your terminals with at least 256 colors to get the real feel of your selected theme. Use a setting like this in one of your shell startup files:

TERM=xterm-256color
export TERM
vfclists
  • 1,347
  • 1
  • 11
  • 28
Uwe Koloska
  • 968
  • 9
  • 13
  • Not all terminals support 256 colours, e.g. xfce4-terminal is still just 8 (I switched to sakura for the pretty colours). – unhammer Aug 22 '15 at 07:31