ncmpcpp / ncmpcpp

Featureful ncurses based MPD client inspired by ncmpc
GNU General Public License v2.0
2.13k stars 225 forks source link

[BUG] Pywal color not working #449

Open Cyliann opened 3 years ago

Cyliann commented 3 years ago

Describe the bug Dunno if it's a bug, but when I use pywal colors change, but when I open another window it changes back to default.

To Reproduce Open ncmpcpp. Change wallpaper with pywal. Open another window.

Expected behavior Change color palette acording to pywal.

Screenshots/Logs image

Desktop (please complete the following information):

swodig112 commented 3 years ago

Hi I think I'm encountering the same bug. It happens on alacritty, kitty and foot. I use pywal in zsh and the colors are reset once I resize the window. @Cyliann I know awesomeWM is a tiling WM so the window size changes when you open a new window. Maybe the problem is resizing. Would you check that?

OS arch ncmpcpp 0.9.2 WM sway

0xGodspeed commented 3 years ago

Same thing happens in alacritty on dwm as well.

sbruder commented 3 years ago

I have the same problem, in my case the text colour set with dynamic-colors gets reset to the colour from alacritty’s configuration file on window resize, which makes some text unreadable (light text on light background).

I did some digging around in the source code of the related projects (ncmpcpp, ncurses, alacritty) and found out why this happens.

The reset is caused by calling ncurses’ endwin() function, which also resets the terminal, when the main window has to be reloaded: https://github.com/ncmpcpp/ncmpcpp/blob/71970fa73cdcf760499274fc9666611272cd62bf/src/actions.cpp#L201-L205

This is the relevant part of the terminfo definition for alacritty from ncurses 6.2 (misc/terminfo.src, ll. 6940/6941):

alacritty|alacritty terminal emulator,
    rs1=\Ec\E]104\007, use=xterm+256color,

Because the definition of rs1 includes \E]104\007, all colours get reset to their default values (from the configuration file): https://github.com/alacritty/alacritty/blob/c688adc7b514de92afdb9c3c27faeda95f8fa475/alacritty_terminal/src/ansi.rs#L1052-L1059

Just using \Ec also resets the terminal but keeps the colours unchanged, which can be seen by spoofing the TERM environment variable to a different terminal that only uses \Ec for reset (like xterm): TERM=xterm ncmpcpp

However, I do not know how to fix this, because from what I know, every part is doing what it is supposed to do. My guess is that setting the global palette dynamically is not intended since it can be reset at any time (and has to for some operations). Therefore, the two solutions that I see are to either not use dynamic palettes or the somewhat hacky solution to spoof the TERM environment variable for ncmpcpp.

swodig112 commented 3 years ago

Thanks to @sbruder I found a way to get it work with pywal. I'm sure with a bit of tweaking this can be done for dynamic-colors as well.

I used LD_PRELOAD to use my own endwin() function. Copy the code below and save it in endwin.c:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <curses.h>

int endwin(void) {
    int (*original_endwin)(void);
    original_endwin = dlsym(RTLD_NEXT, "endwin");
    int ret = (*original_endwin)();

    char *filename = "/.cache/wal/sequences";
    char *home_dir = getenv("HOME");
    char *filepath = malloc(strlen(home_dir) + strlen(filename) + 1);
    strncpy(filepath, home_dir, strlen(home_dir) + 1);
    strncat(filepath, filename, strlen(filename) + 1);

    FILE *sequences;
    char s;
    sequences = fopen(filepath,"r");
    while((s = fgetc(sequences)) != EOF) {
      printf("%c", s);
    }
    fclose(sequences);

    return ret;
}

Compile it using gcc and set LD_PRELOAD to get it working:

gcc -Wall -fPIC -shared -o endwin.so endwin.c -ldl
LD_PRELOAD=./endwin.so ncmpcpp

Sorry if this is a mess I just copied stuff and used some poor knowledge I had in my brain already. I hope it works for you.

Cyliann commented 3 years ago

I found a solution to that problem. Somewhere on reddit someone posted a script which reloads alacritty colors and I just run it every time I change a wallpaper/pywal colors.

# Alacritty Color Export
# Version 0.1.0
# github.com/egeesin
#
# Exports generated Wal colors to Alacritty config
# WARNING: Don't forget to backup your Alacritty config
# before execute this script!
#
# Dependencies: bash, grep, sed
# Usage: ./script.sh
#        ./script.sh <config yml>

# Get Wal color file
SRC=${HOME}"/.cache/wal/colors"
[[ ! -e $SRC ]] && echo "ERR: Wal colors not found, exiting script. Did you executed Wal before?" && exit 0
[[ -e $SRC ]] && echo "Colors found, source ready."

READLINK=$( command -v greadlink | command -v readlink )

# Get config file
if [[ $1 ]]; then
    # Check path syntax here
    [[ -e $1 ]] && echo "Config found, destination ready."; CFG=$1
    [[ -L $1 ]] && echo "Following symlink to config..." && CFG=$($READLINK -f $1)
    [[ ! -e $1 ]] && echo "ERR: Selected config doesn't exist, exiting script." && exit 0
else
    # Default config path in Mac systems
    [[ -e ${HOME}"/.config/alacritty/alacritty.yml" ]] && echo "Config found, destination ready." && CFG=${HOME}"/.config/alacritty/alacritty.yml"
    [[ -L ${HOME}"/.config/alacritty/alacritty.yml" ]] && echo "Following symlink to config..." && CFG=$($READLINK -f ${HOME}"/.config/alacritty/alacritty.yml")
    [[ ! -e $CFG ]] && echo "ERR: Alacritty config not found, exiting script." && exit 0
fi

# Get and convert hex colors from Wal cache
index=1
for line in $(grep -oE '[0-9a-fA-F]{6}' "$SRC")
do
    regex='[0-9a-fA-F]{6}'
    if [[ $line =~ $regex ]]
    then
        eval "color$index=0x$line"
        index=$((index+1));
    fi
done

# Delete existing color declerations (generated by this script)
if grep -q '^# BEGIN ACE' "$CFG"; then
    echo "Existing 'generated' colors found, replacing new colors...'"
    sed -i '' -e '/^# BEGIN ACE/,/^# END ACE/{/^# BEGIN ACE/!{/^# END ACE/!d;};}' "$CFG"
# ^^^ There's something wrong with this command. If BEGIN ACE comment
# doesn't exist but END ACE, just deletes all config except END ACE line.
# In the mean time, surrounding comments must not touched, until finding
# safer version of this command.
else
    echo "There's no existing 'generated' colors, adding comments...";
    echo -e '# BEGIN ACE\n# END ACE' >> "$CFG";
fi

# vvv This line may give error on different systems.
sed -i '' -e "/^# BEGIN ACE/ r /dev/stdin" "$CFG" <<EOF
colors:
  primary:
    background: '$color1'
    foreground: '$color8'
  cursor:
    text:       '$color1'
    cursor:     '$color8'
  normal:
    black:      '$color1'
    red:        '$color2'
    green:      '$color3'
    yellow:     '$color4'
    blue:       '$color5'
    magenta:    '$color6'
    cyan:       '$color7'
    white:      '$color8'
  bright:
    black:      '$color9'
    red:        '$color10'
    green:      '$color11'
    yellow:     '$color12'
    blue:       '$color13'
    magenta:    '$color14'
    cyan:       '$color15'
    white:      '$color16'

EOF

echo "'${SRC}' exported to '${CFG}'"
thenns commented 2 years ago

I also have the same problem using kitty

AmeerMoustafa commented 1 year ago

Having the same problem with kitty. @swodig112's solution doesn't seem to be working for me unfortunately. Very frustrating.

swodig112 commented 1 year ago

Pywal generates a color config for kitty. It's located in ~/.cache/wal/colors-kitty.conf. To use it, remove color configuration from kitty's configuration in ~/.config/kitty/kitty.conf and add this line: include ~/.cache/wal/colors-kitty.conf

As for alacritty and other terminal emulators such as foot, you can write a template yourself. Here's what I'm using for foot:

[colors]
foreground = {foreground.strip}
background = {background.strip}
regular0 = {color0.strip}
regular1 = {color1.strip}
regular2 = {color2.strip}
regular3 = {color3.strip}
regular4 = {color4.strip}
regular5 = {color5.strip}
regular6 = {color6.strip}
regular7 = {color7.strip}
bright0 = {color8.strip}
bright1 = {color9.strip}
bright2 = {color10.strip}
bright3 = {color11.strip}
bright4 = {color12.strip}
bright5 = {color13.strip}
bright6 = {color14.strip}
bright7 = {color15.strip}

I think this issue should be marked as solved.

AmeerMoustafa commented 1 year ago

Yup. This pretty much fixed it for me. Thank you for the quick response!