nordtheme / emacs

An arctic, north-bluish clean and elegant Emacs theme.
https://www.nordtheme.com/ports/emacs
MIT License
491 stars 63 forks source link

Theme does not load with `emacs --daemon` #59

Open robert-uhl opened 6 years ago

robert-uhl commented 6 years ago

If emacs is started with emacs --daemon, the nord theme will not properly load, but will instead display as grey-on-white; there are many messages like the following:

Unable to load color "brightblack"
Unable to load color "brightcyan"
Unable to load color "brightblack" [5 times]
Unable to load color "brightblack"
Unable to load color "brightcyan"
Unable to load color "brightblack" [2 times]
Unable to load color "brightcyan"
Unable to load color "brightblack" [5 times]
Unable to load color "brightcyan"
Unable to load color "brightblack" [2 times]
Unable to load color "brightcyan" [3 times]
Unable to load color "brightblack"
Unable to load color "brightcyan"
Unable to load color "brightblack"
Unable to load color "brightcyan"
Unable to load color "brightblack" [5 times]

I believe that this is because in daemon mode there is no terminal, and thus nothing to send the colour names to. I think that the fix is to use the color class system as documented in Defining Faces.

ghost commented 6 years ago
(if (daemonp) 
        (add-hook 'after-make-frame-functions 
              (lambda (frame) 
            (with-selected-frame frame (load-theme 'nord t)))) 
      (load-theme 'nord t))

This fixed it for me.

robert-uhl commented 6 years ago

@gutigen, the problem with that is that it reloads Nord with every single new frame.

I got some code together using the class system, but it's horribly ugly code. I think I need to try a new approach.

jaccarmac commented 6 years ago

To avoid the load-on-every-frame problem I whipped up a variant using cl-labels.

(if (daemonp)
    (cl-labels ((load-nord (frame)
                           (with-selected-frame frame
                             (load-theme 'nord t))
                           (remove-hook 'after-make-frame-functions #'load-nord)))
      (add-hook 'after-make-frame-functions #'load-nord))
  (load-theme 'nord t))

Note that this requires lexical-binding: t. Without lexical binding you could wrap the form in cl-block or use cl-letf instead of cl-labels.

Update: daemonp is technically not the best way to check for server status, as I found out. However, it is the correct condition in this case as I also found out. See this tech note attached to my config.

arcticicestudio commented 6 years ago

Sorry again for the delay. There's another issue about the ANSI color definitions so maybe I'll check how to better implement these to avoid the named "bright" colors listed above in the error log.

arcticicestudio commented 5 years ago

Sorry for the long absence, I've been busy again with my job and work on the official Nord Docs with the goal to finally have a single-source-of-truth for all of Nord's port projects. Anyway, I'd like to get some of the long-time queued issues of some port projects done, including this one.

@somesoup emailed me and submitted #68, a fix for this daemon mode problem. @zvbuhl posted some ideas how to solve it using the definition of faces and @jaccarmac also proposed another way how to solve it. @slippycheeze offered help for some problems in https://github.com/arcticicestudio/nord-emacs/issues/66#issuecomment-421123819 and maybe has some ideas and opinions to get this done too. It would be really nice if we can discuss together what's the best solution to fix this. I'm happy about any help! It bothers me a lot that I could not solve some of the open issues in this repository due to the missing experience with Emacs and the fact that even after searching through many documentations and tutorials not able to find a up-to-date or correct solution. There are also not always ways to reproduce some of the problems. In short: OSS lives from contributors and I welcome any help for this very much :smile:

I tried to reproduce the log posted in the initial post, but when I run emacs --daemon it starts without any errors but only a warning:

Warning: due to a long standing Gtk+ bug
http://bugzilla.gnome.org/show_bug.cgi?id=85715
Emacs might crash when run in daemon mode and the X11 connection is unexpectedly lost.
Using an Emacs configured with --with-x-toolkit=lucid does not have this problem.
Loading hl-line...
Loading hl-line...done
Loading linum...
Loading linum...done
Loading paren...
Loading paren...done
Starting Emacs daemon.

It also works fine running Emacs without the GUI (emacs -nw). I use GNU Emacs 26.1 on Arch Linux with Kernel 4.18.7-arch1-1-ARCH. The package build script can be found in the official repositories, maybe there are some differences in the compile options. Can anyone who's still affected by the problem please provide a step-by-step reproduction guide?

Like I said I'm not a Emacs user and I have no experience with Lisp so I rely on community help.

jaccarmac commented 5 years ago

Thanks for circling back! My snippet is working well enough in practice for now, but I've noticed some irregularities and will work on a reproduction guide later this week. That warning is just noise: It has to do with the way Emacs was compiled, not the environment it is running in nor the config.

CrosleyZack commented 5 years ago

I can recreate this issue. I am loading Emacs 26.1 using emacsclient -nc with the daemon being run by systemd on startup using systemctl start --user emacs. My system is running Kernel version 4.19.13-1-MANJARO. I receive the same errors as @zvbuhl regarding colors being unable to load.

slippycheeze commented 5 years ago

The way to solve this "correctly" is to define the faces with all the options, and let Emacs select the appropriate color given the properties of the current frame. That'll work correctly with daemon mode, as well as a mixture of graphical and tty instances.

TL;DR is instead of defining variables like this:

(nord0 (if (or (daemonp) (display-graphic-p)) "#2E3440" nil))

You want to define faces like this:

(defface nord0-face 
  '((((type graphic) (min-colors 256)) :background "#2E3440")
   (((min-colors 16)) :background "#whatever")
   ((t :background "#if nothing else matches, I guess?")))

Additionally, check in the document linked below the default spec, which lets you set the baseline, then only define what is different in the rest of the matches.

I'd also consider a match for 24-bit color without the terminal type being set, so people with 24-bit TTY stuff setup will be able to get the full color experience.

Sorry not to have time to address this myself, and only give pointers. Life isn't kind, sometimes.

References:

arcticicestudio commented 5 years ago

@slippycheeze Thanks, this helps a lot and looks like the way to go. Absolute no problem for the delayed response time. Unfortunately, I have the same problem that the day only has 24h and necessary real life tasks absorbing almost all of it :unamused:

Since this is a open source project, everyone is free to go for it and submit a PR if it should be merged into this project. As soon as I'm done with porting all documentation and assets of all Nord's port project to the new official website of Nord there is hopefully more time to work on all the issues and PRs waiting in the queue.

jaccarmac commented 5 years ago

Might look at PR'ing this. Are there guidelines for what the Nord colors are in smaller color spaces or should I just eyeball it for 24-bit and 16-color displays?

rien333 commented 5 years ago

The newest release made this a lot worse. Basically no colors seem to be available and @accarmac init.el addition fails to connect to the daemon completely, with no output. (emacs just briefly flashes and then quits). The daemon is running, but there is no way to connect to it.

Edit: nvm, downgrading does not seem to work. I think I might have manually changed something to nord-theme.el to fix the problem at some point. At the moment however, emacs is completely unusable when using nord.

robert-uhl commented 5 years ago

@rien333 I just upgraded to 0.4.0 (20190616.1757) and it seems to work okay. Still loads as light-blue on white, but I’m able to load the theme manually once I’ve got an X frame open, and then proceed as normal.

rien333 commented 5 years ago

Fixed by using the code from PR #64 (that adds a proper 24-bit check) and the daemon solution provided by the "ghost account". When using the solution provided by @jaccarmac my emacsclient just doesn't connect, and I havent been able to get useful debug info from it. (I've seen emacs complain about cl-labels before, maybe it's something about that). Manually loading the theme also works fine now.

btw, I'm using emacs-26.2.

arcticicestudio commented 5 years ago

@rien333 Thanks for your feedback, this helps to decide which of the already four proposed solutions might work the best for latest and older versions 👍

jaccarmac commented 5 years ago

@rien333 Are you using lexical-binding: t? That's probably the easiest way cl-labels would fail. Perhaps I should whip up a non-lexical solution so it works for more people.

rien333 commented 5 years ago

That variable is nil, according to emacs. I also don't alter it in my init.el, nor does setting it to t have any effect. It's somewhat weird actually if I'm the only one that has problems with your snippet, I probably need to bisect my init.el.

As an aside, I'm using the kitty terminal emulator, with 24-bit support in emacs made available by a .terminfo file tailored to the true color spec kitty uses. (not sure if that's relevant but yeah)

jaccarmac commented 5 years ago

It needs to be set with a file-local variable as in my config (see top), otherwise cl-labels will not work properly in that snippet. Otherwise you'll need to use cl-block or cl-letf; I just set my init file as lexical so can't tell you exactly how to do so.

Further information about lexical-binding: Emacs manual, Chris Wellons's blog

robert-uhl commented 5 years ago

Here’s an attempt not to rely on the setting at daemon-start time. It’s a mechanical translation, and it’s embarrassingly unabstracted, but … maybe it’s a start?

https://github.com/zvbuhl/nord-emacs/tree/theme-tty

rien333 commented 5 years ago

@jaccarmac, the addition on top of the file did the trick, thank you for your assistance and the resources on lexical-binding; I wan't completely familiar with the subject yet.

aiguofer commented 5 years ago

So... I'm having a bit of a different issue than most folks here. I'm running emacs off systemctl --user using emacs --fg-daemon.

The theme works great in either terminal (emacsclient -t) or as a frame in X (emacsclient -c). The problem is that it doesn't work in both... it's one or the other (whichever starts first). This is an issue for me because I don't use emacsclient directly but instead have an "editor" script that will use console if I launch in console or a frame otherwise:

#!/bin/bash

if [ -z "$(pgrep emacs)" ]; then
    systemctl --user restart emacs
    sleep 10
fi

SOCKET=$(lsof -c emacs | grep $USER | grep server | grep STREAM | awk '{print $9}' | sort | uniq)
PARAMS="--socket-name=$SOCKET"

if [[ $TMUX || $SSH_CLIENT ]]
then
    PARAMS+=" -t"
else
    PARAMS+=" -c"
fi

exec  /usr/bin/emacsclient $PARAMS $@

Note: I can "switch" the working one by manually calling load-theme in an emacsclient in either terminal or in X, but it'll break the other.

rien333 commented 5 years ago

It might be that I'm missing something important, but it seems to me as if you start emacs the same way I do. I can use the nord-theme fine in either an X frame or in my terminal, and my systemd unit file shows that I also start emacs with emacs --fg-daemon. Is there something different about your setup? Not sure if it's relevant to you and whether you already tried it, but I remember all my problems going away when I patched with PR #64 and added @jaccarmac solution to my init.el.

aiguofer commented 5 years ago

@rien333 thanks for your input! unfortunately that still didn't solve it for me... if it makes a difference, I'm running tmux inside terminator for the console. I've got the nord-theme set up for terminator and using set -g default-terminal screen-256color in tmux.

rien333 commented 5 years ago

I'm seeing the same behavior as you if I run tmux with set -g default-terminal screen-256color.

However, if I use TERM=kitty-24bit emacsclient -t in tmux---a terminfo file I need to use in order for emacs 24-bit support and my terminal to work together---it works fine. Not sure if I'm telling you stuff you already know, but yeah the TERM variable/terminfo or tmux could be the problem.

aiguofer commented 5 years ago

@rien333 thanks! yeah just figured that out... after a bit of googling I finally got it working following this post, with the difference that I went ahead and put TERM=screen-24bit in my .zshrc.

I should add I didn't need the #64 patch, but I did need @jaccarmac's fix for the daemon.

arcticicestudio commented 4 years ago

I've submitted and merged #88 (superseded #64 due to stale state and merge conflicts) as a first step to fix the problem(s) documented in this issue. A by far better soluttion should be a refactoring of the theme colors to make use of defined faces (also mentioned by @zvbuhl and @slippycheeze) in combination with capability tests for display feature/color support.

Anyway, the next release version will include the changes from #88 and I'd really appreciate feeback if it's a step forwards better compatibility :smile:

rien333 commented 4 years ago

@arcticicestudio this is the first time I upgraded nord-theme without it breaking my colors and me having to manually intervene, so it's definitely a step forward in compatibility for my setup (I do have some other fixes from this thread applied to my init.el, though.). Thanks for your time and your continued support!

jaccarmac commented 4 years ago

Can't speak to the issues folks were having in a TTY, but I still need my delayed-load hack for the theme to load under a daemon properly.

iamriel commented 4 years ago

EMACS version: 28.0.5 nord-theme version: 20200108.833

I encounter this issue and I have this as a fix:

(defvar my:theme 'nord)
(defvar my:theme-window-loaded nil)
(defvar my:theme-terminal-loaded nil)

(if (daemonp)
    (add-hook 'after-make-frame-functions(lambda (frame)
                                          (select-frame frame)
                                          (if (window-system frame)
                                              (unless my:theme-window-loaded
                                                (if my:theme-terminal-loaded
                                                    (enable-theme my:theme)
                                                  (load-theme my:theme t))
                                                (setq my:theme-window-loaded t)
                                                )
                                            (unless my:theme-terminal-loaded
                                              (if my:theme-window-loaded
                                                  (enable-theme my:theme)
                                                (load-theme my:theme t))
                                              (setq my:theme-terminal-loaded t)
                                              )
                                            )))

  (progn
    (load-theme my:theme t)
    (if (display-graphic-p)
        (setq my:theme-window-loaded t)
      (setq my:theme-terminal-loaded t)))
  )

I forgot where I found that snippet but credits to the owner.

It works pretty well when I open it in the GUI with emacsclient -nc, but when I run emacsclient -t in the terminal, the theme is different, and I see the Unable to load color errors.

Weird thing is that when I run emacsclient -t BEFORE opening emacs in a GUI, it loads correctly, but when I run it AFTER running emacsclient -nc (GUI), the terminal colors get messed up. You can check the screenshot attached:

Left side is terminal while right side is the GUI:

2020-04-09_23-53

jaccarmac commented 4 years ago

Interesting. I don't really use terminal Emacs, but decided to see how my fix fared in the same situation. And it turns out that if I start a daemon and then open a terminal client before a graphical client, the graphical client doesn't load the correct colors. If a graphical client is opened before everything plays together nicely.

arcticicestudio commented 4 years ago

@iamriel Thanks for your help 👍

I've also noticed the exact same behavior while trying to reproduce the problem and thought it was my fault and lack of experience/usage with Emacs, but it's "good" to see that this is not scoped to my system. I'll keep this on my list for things that requires manual testing when the faces for theme colors are implemented.

xukai92 commented 3 years ago

Just to mention that the unoffical Nord theme in the Doom themes (https://github.com/hlissner/emacs-doom-themes/blob/master/themes/doom-nord-theme.el) doesn't suffer from this issue but that theme is not as polished as this offical one. I wonder if we could merge these two version; Doom themes seem to well-maintained.

EdwardIII commented 2 years ago

Hey, still seeing this on:

Is https://github.com/arcticicestudio/nord-emacs/issues/59#issuecomment-611610832 still the way to go?