inital commit
213
.config/cava/cava_option_config
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
|
||||
## Configuration file for CAVA. Default values are commented out. Use either ';' or '#' for commenting.
|
||||
|
||||
|
||||
[general]
|
||||
|
||||
|
||||
bars = 10
|
||||
framerate = 240
|
||||
|
||||
|
||||
# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0
|
||||
; mode = scientific
|
||||
|
||||
# Accepts only non-negative values.
|
||||
; framerate = 30
|
||||
|
||||
# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = active
|
||||
# new as of 0.6.0 autosens of low values (dynamic range)
|
||||
# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0
|
||||
; autosens = 1
|
||||
; overshoot = 20
|
||||
|
||||
# Manual sensitivity in %. If autosens is enabled, this will only be the initial value.
|
||||
# 200 means double height. Accepts only non-negative values.
|
||||
; sensitivity = 120
|
||||
|
||||
# The number of bars (0-200). 0 sets it to auto (fill up console).
|
||||
# Bars' width and space between bars in number of characters.
|
||||
; bars = 10
|
||||
; bar_width = 1
|
||||
; bar_spacing = 100
|
||||
# bar_height is only used for output in "noritake" format
|
||||
; bar_height = 32
|
||||
|
||||
# For SDL width and space between bars is in pixels, defaults are:
|
||||
; bar_width = 20
|
||||
; bar_spacing = 5
|
||||
|
||||
|
||||
# Lower and higher cutactive frequencies for lowest and highest bars
|
||||
# the bandwidth of the visualizer.
|
||||
# Note: there is a minimum total bandwidth of 43Mhz x number of bars.
|
||||
# Cava will automatically increase the higher cutactive if a too low band is specified.
|
||||
; lower_cutactive_freq = 50
|
||||
; higher_cutactive_freq = 10000
|
||||
|
||||
|
||||
# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and
|
||||
# only check for input once per second. Cava will wake up once input is detected. 0 = disable.
|
||||
sleep_timer = 10
|
||||
|
||||
|
||||
[input]
|
||||
|
||||
# Audio capturing method. Possible methods are: 'pulse', 'alsa', 'fifo', 'sndio' or 'shmem'
|
||||
# Defaults to 'pulse', 'alsa' or 'fifo', in that order, dependent on what support cava was built with.
|
||||
#
|
||||
# All input methods uses the same config variable 'source'
|
||||
# to define where it should get the audio.
|
||||
#
|
||||
# For pulseaudio 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink
|
||||
# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them).
|
||||
#
|
||||
# For alsa 'source' will be the capture device.
|
||||
# For fifo 'source' will be the path to fifo-file.
|
||||
# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address
|
||||
; method = pulse
|
||||
; source = auto
|
||||
|
||||
; method = alsa
|
||||
; source = hw:Loopback,1
|
||||
|
||||
; method = fifo
|
||||
; source = /tmp/mpd.fifo
|
||||
; sample_rate = 44100
|
||||
; sample_bits = 16
|
||||
|
||||
; method = shmem
|
||||
; source = /squeezelite-AA:BB:CC:DD:EE:FF
|
||||
|
||||
; method = portaudio
|
||||
; source = auto
|
||||
|
||||
|
||||
[output]
|
||||
|
||||
# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake' or 'sdl'.
|
||||
# 'noncurses' uses a custom framebuffer technique and prints only changes
|
||||
# from frame to frame in the terminal. 'ncurses' is default if supported.
|
||||
#
|
||||
# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data
|
||||
# stream of the bar heights that can be used to send to other playerlications.
|
||||
# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above.
|
||||
#
|
||||
# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display
|
||||
# in graphic mode. It only support the 3000 series graphical VFDs for now.
|
||||
#
|
||||
# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context.
|
||||
method = raw
|
||||
|
||||
# Visual channels. Can be 'stereo' or 'mono'.
|
||||
# 'stereo' mirrors both channels with low frequencies in center.
|
||||
# 'mono' outputs left to right lowest to highest frequencies.
|
||||
# 'mono_option' set mono to either take input from 'left', 'right' or 'average'.
|
||||
# set 'reverse' to 1 to display frequencies the other way around.
|
||||
; channels = stereo
|
||||
; mono_option = average
|
||||
; reverse = 0
|
||||
|
||||
# Raw output target. A fifo will be created if target does not exist.
|
||||
; raw_target = /dev/stdout
|
||||
|
||||
# Raw data format. Can be 'binary' or 'ascii'.
|
||||
data_format = ascii
|
||||
|
||||
# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530).
|
||||
; bit_format = 16bit
|
||||
|
||||
# Ascii max value. In 'ascii' mode range will run from 0 to value specified here
|
||||
ascii_max_range = 7
|
||||
|
||||
# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters.
|
||||
# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)).
|
||||
; bar_delimiter = 59
|
||||
; frame_delimiter = 10
|
||||
|
||||
# sdl window size and position. -1,-1 is centered.
|
||||
; sdl_width = 1000
|
||||
; sdl_height = 500
|
||||
; sdl_x = -1
|
||||
; sdl_y= -1
|
||||
|
||||
# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none'
|
||||
# 'frequency' displays the lower cut active frequency of the bar above.
|
||||
# Only supported on ncurses and noncurses output.
|
||||
; xaxis = none
|
||||
|
||||
# enable alacritty synchronized updates. 1 = on, 0 = active
|
||||
# removes flickering in alacritty terminal emeulator.
|
||||
# defaults to active since the behaviour in other terminal emulators is unknown
|
||||
; alacritty_sync = 1
|
||||
|
||||
[color]
|
||||
|
||||
# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow.
|
||||
# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires
|
||||
# ncurses output method and a terminal that can change color definitions such as Gnome-terminal or rxvt.
|
||||
# if supported, ncurses mode will be forced on if user defined colors are used.
|
||||
# default is to keep current terminal color
|
||||
; background = default
|
||||
; foreground = default
|
||||
|
||||
# SDL only support hex code colors, these are the default:
|
||||
; background = '#111111'
|
||||
; foreground = '#33cccc'
|
||||
|
||||
|
||||
# Gradient mode, only hex defined colors (and thereby ncurses mode) are supported,
|
||||
# background must also be defined in hex or remain commented out. 1 = on, 0 = active.
|
||||
# You can define as many as 8 different colors. They range from bottom to top of screen
|
||||
; gradient = 0
|
||||
; gradient_count = 8
|
||||
; gradient_color_1 = '#59cc33'
|
||||
; gradient_color_2 = '#80cc33'
|
||||
; gradient_color_3 = '#a6cc33'
|
||||
; gradient_color_4 = '#cccc33'
|
||||
; gradient_color_5 = '#cca633'
|
||||
; gradient_color_6 = '#cc8033'
|
||||
; gradient_color_7 = '#cc5933'
|
||||
; gradient_color_8 = '#cc3333'
|
||||
|
||||
|
||||
|
||||
[smoothing]
|
||||
|
||||
# Percentage value for integral smoothing. Takes values from 0 - 100.
|
||||
# Higher values means smoother, but less precise. 0 to disable.
|
||||
# DEPRECATED as of 0.8.0, use noise_reduction instead
|
||||
; integral = 77
|
||||
|
||||
# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable.
|
||||
; monstercat = 0
|
||||
; waves = 0
|
||||
|
||||
# Set gravity percentage for "drop active". Higher values means bars will drop faster.
|
||||
# Accepts only non-negative values. 50 means half gravity, 200 means double. Set to 0 to disable "drop active".
|
||||
# DEPRECATED as of 0.8.0, use noise_reduction instead
|
||||
; gravity = 100
|
||||
|
||||
|
||||
# In bar height, bars that would have been lower that this will not be drawn.
|
||||
# DEPRECATED as of 0.8.0
|
||||
; ignore = 0
|
||||
|
||||
# Noise reduction, float 0 - 1. default 0.77
|
||||
# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth
|
||||
# 1 will be very slow and smooth, 0 will be fast but noisy.
|
||||
; noise_reduction = 0.77
|
||||
|
||||
|
||||
[eq]
|
||||
|
||||
# This one is tricky. You can have as much keys as you want.
|
||||
# Remember to uncomment more then one key! More keys = more precision.
|
||||
# Look at readme.md on github for further explanations and examples.
|
||||
# DEPRECATED as of 0.8.0 can be brought back by popular request, open issue at:
|
||||
# https://github.com/karlstav/cava
|
||||
; 1 = 1 # bass
|
||||
; 2 = 1
|
||||
; 3 = 1 # midtone
|
||||
; 4 = 1
|
||||
; 5 = 1 # treble
|
||||
321
.config/cava/config
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
## Configuration file for CAVA.
|
||||
# Remove the ; to change parameters.
|
||||
|
||||
|
||||
[general]
|
||||
|
||||
# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0
|
||||
; mode = normal
|
||||
|
||||
# Accepts only non-negative values.
|
||||
; framerate = 60
|
||||
|
||||
# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off
|
||||
# new as of 0.6.0 autosens of low values (dynamic range)
|
||||
# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0
|
||||
; autosens = 1
|
||||
; overshoot = 20
|
||||
|
||||
# Manual sensitivity in %. If autosens is enabled, this will only be the initial value.
|
||||
# 200 means double height. Accepts only non-negative values.
|
||||
; sensitivity = 100
|
||||
|
||||
# The number of bars (0-512). 0 sets it to auto (fill up console).
|
||||
# Bars' width and space between bars in number of characters.
|
||||
; bars = 0
|
||||
; bar_width = 2
|
||||
; bar_spacing = 1
|
||||
# bar_height is only used for output in "noritake" format
|
||||
; bar_height = 32
|
||||
|
||||
# For SDL width and space between bars is in pixels, defaults are:
|
||||
; bar_width = 20
|
||||
; bar_spacing = 5
|
||||
|
||||
# sdl_glsl have these default values, they are only used to calculate max number of bars.
|
||||
; bar_width = 1
|
||||
; bar_spacing = 0
|
||||
|
||||
# ceter bars in terminal, if there is space.
|
||||
; center_align = 1
|
||||
|
||||
# max height of bars in terminal, in percent of terminal height.
|
||||
; max_height = 100
|
||||
|
||||
|
||||
# Lower and higher cutoff frequencies for lowest and highest bars
|
||||
# the bandwidth of the visualizer.
|
||||
# Note: there is a minimum total bandwidth of 43Mhz x number of bars.
|
||||
# Cava will automatically increase the higher cutoff if a too low band is specified.
|
||||
; lower_cutoff_freq = 50
|
||||
; higher_cutoff_freq = 10000
|
||||
|
||||
|
||||
# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and
|
||||
# only check for input once per second. Cava will wake up once input is detected. 0 = disable.
|
||||
; sleep_timer = 0
|
||||
|
||||
|
||||
[input]
|
||||
|
||||
# Audio capturing method. Possible methods are: 'fifo', 'portaudio', 'pipewire', 'alsa', 'pulse', 'sndio', 'oss', 'jack' or 'shmem'
|
||||
# Defaults to 'oss', 'pipewire', 'sndio', 'jack', 'pulse', 'alsa', 'portaudio' or 'fifo', in that order, dependent on what support cava was built with.
|
||||
# On Mac it defaults to 'portaudio' or 'fifo'
|
||||
# On windows this is automatic and no input settings are needed.
|
||||
#
|
||||
# All input methods uses the same config variable 'source'
|
||||
# to define where it should get the audio.
|
||||
#
|
||||
# For pulseaudio and pipewire 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink
|
||||
# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them).
|
||||
#
|
||||
# For pipewire 'source' will be the object name or object.serial of the device to capture from.
|
||||
# Both input and output devices are supported. To capture the monitor source of a sink node, append '.monitor' to the sink's object name.
|
||||
#
|
||||
# For alsa 'source' will be the capture device.
|
||||
# For fifo 'source' will be the path to fifo-file.
|
||||
# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address
|
||||
#
|
||||
# For sndio 'source' will be a raw recording audio descriptor or a monitoring sub-device, e.g. 'rsnd/2' or 'snd/1'. Default: 'default'.
|
||||
# README.md contains further information on how to setup CAVA for sndio.
|
||||
#
|
||||
# For oss 'source' will be the path to a audio device, e.g. '/dev/dsp2'. Default: '/dev/dsp', i.e. the default audio device.
|
||||
# README.md contains further information on how to setup CAVA for OSS on FreeBSD.
|
||||
#
|
||||
# For jack 'source' will be the name of the JACK server to connect to, e.g. 'foobar'. Default: 'default'.
|
||||
# README.md contains further information on how to setup CAVA for JACK.
|
||||
#
|
||||
; method = pulse
|
||||
; source = auto
|
||||
|
||||
; method = pipewire
|
||||
; source = auto
|
||||
|
||||
; method = alsa
|
||||
; source = hw:Loopback,1
|
||||
|
||||
; method = fifo
|
||||
; source = /tmp/mpd.fifo
|
||||
|
||||
; method = shmem
|
||||
; source = /squeezelite-AA:BB:CC:DD:EE:FF
|
||||
|
||||
; method = portaudio
|
||||
; source = auto
|
||||
|
||||
; method = sndio
|
||||
; source = default
|
||||
|
||||
; method = oss
|
||||
; source = /dev/dsp
|
||||
|
||||
; method = jack
|
||||
; source = default
|
||||
|
||||
# The options 'sample_rate', 'sample_bits', 'channels' and 'autoconnect' can be configured for some input methods:
|
||||
# sample_rate: fifo, pipewire, sndio, oss
|
||||
# sample_bits: fifo, pipewire, sndio, oss
|
||||
# channels: sndio, oss, jack
|
||||
# autoconnect: jack
|
||||
# Other methods ignore these settings.
|
||||
# For pipewire, sample_rate will default to 48000, for all other input methods, sample_rate will default to 44100.
|
||||
#
|
||||
# For 'sndio' and 'oss' they are only preferred values, i.e. if the values are not supported
|
||||
# by the chosen audio device, the device will use other supported values instead.
|
||||
# Example: 48000, 32 and 2, but the device only supports 44100, 16 and 1, then it
|
||||
# will use 44100, 16 and 1.
|
||||
#
|
||||
#
|
||||
# The 'pipewire' input method has three options to control linking and mixing:
|
||||
# active: Force the node to always process. Useful for monitoring sources when no other application is active.
|
||||
# remix: Allow pipewire to remix audio channels to match cava's channel count. Useful for surround sound.
|
||||
# virtual: Set the node to virtual, to avoid recording notifications from the DE.
|
||||
#
|
||||
; sample_rate = 44100
|
||||
; sample_bits = 16
|
||||
; channels = 2
|
||||
; autoconnect = 2
|
||||
; active = 0
|
||||
; remix = 1
|
||||
; virtual = 1
|
||||
|
||||
|
||||
[output]
|
||||
|
||||
# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake', 'sdl'
|
||||
# or 'sdl_glsl'.
|
||||
# 'noncurses' (default) uses a buffer and cursor movements to only print
|
||||
# changes from frame to frame in the terminal. Uses less resources and is less
|
||||
# prone to tearing (vsync issues) than 'ncurses'.
|
||||
#
|
||||
# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data
|
||||
# stream of the bar heights that can be used to send to other applications.
|
||||
# 'raw' defaults to 1024 bars stereo (512 bars mono), which can be adjusted in the 'bars' option above.
|
||||
#
|
||||
# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display
|
||||
# in graphic mode. It only support the 3000 series graphical VFDs for now.
|
||||
#
|
||||
# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context.
|
||||
# 'sdl_glsl' uses SDL to create an OpenGL context. Write your own shaders or
|
||||
# use one of the predefined ones.
|
||||
; method = noncurses
|
||||
|
||||
# Orientation of the visualization. Can be 'bottom', 'top', 'left', 'right' or
|
||||
# 'horizontal'. Default is 'bottom'. 'left and 'right' are only supported on sdl
|
||||
# and ncruses output. 'horizontal' (bars go up and down from center) is only supported
|
||||
# on noncurses output.
|
||||
# Note: many fonts have weird or missing glyphs for characters used in orientations
|
||||
# other than 'bottom', which can make output not look right.
|
||||
; orientation = bottom
|
||||
|
||||
# Visual channels. Can be 'stereo' or 'mono'.
|
||||
# 'stereo' mirrors both channels with low frequencies in center.
|
||||
# 'mono' outputs left to right lowest to highest frequencies.
|
||||
# 'mono_option' set mono to either take input from 'left', 'right' or 'average'.
|
||||
# set 'reverse' to 1 to display frequencies the other way around.
|
||||
; channels = stereo
|
||||
; mono_option = average
|
||||
; reverse = 0
|
||||
|
||||
# Raw output target.
|
||||
# On Linux, a fifo will be created if target does not exist.
|
||||
# On Windows, a named pipe will be created if target does not exist.
|
||||
; raw_target = /dev/stdout
|
||||
|
||||
# Raw data format. Can be 'binary' or 'ascii'.
|
||||
; data_format = binary
|
||||
|
||||
# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530).
|
||||
; bit_format = 16bit
|
||||
|
||||
# Ascii max value. In 'ascii' mode range will run from 0 to value specified here
|
||||
; ascii_max_range = 1000
|
||||
|
||||
# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters.
|
||||
# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)).
|
||||
; bar_delimiter = 59
|
||||
; frame_delimiter = 10
|
||||
|
||||
# sdl window size and position. -1,-1 is centered.
|
||||
; sdl_width = 1024
|
||||
; sdl_height = 512
|
||||
; sdl_x = -1
|
||||
; sdl_y= -1
|
||||
; sdl_full_screen = 0
|
||||
|
||||
# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none'
|
||||
# 'frequency' displays the lower cut off frequency of the bar above.
|
||||
# Only supported on ncurses and noncurses output.
|
||||
; xaxis = none
|
||||
|
||||
# enable synchronized sync. 1 = on, 0 = off
|
||||
# removes flickering in alacritty terminal emulator.
|
||||
# defaults to off since the behaviour in other terminal emulators is unknown
|
||||
; synchronized_sync = 0
|
||||
|
||||
# Shaders for sdl_glsl, located in $HOME/.config/cava/shaders
|
||||
; vertex_shader = pass_through.vert
|
||||
; fragment_shader = bar_spectrum.frag
|
||||
|
||||
; for glsl output mode, keep rendering even if no audio
|
||||
; continuous_rendering = 0
|
||||
|
||||
# disable console blank (screen saver) in tty
|
||||
# (Not supported on FreeBSD)
|
||||
; disable_blanking = 0
|
||||
|
||||
# show a flat bar at the bottom of the screen when idle, 1 = on, 0 = off
|
||||
; show_idle_bar_heads = 1
|
||||
|
||||
# show waveform instead of frequency spectrum, 1 = on, 0 = off
|
||||
; waveform = 0
|
||||
|
||||
[color]
|
||||
|
||||
# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow.
|
||||
# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires
|
||||
# a terminal that can change color definitions such as Gnome-terminal or rxvt.
|
||||
# default is to keep current terminal color
|
||||
; background = default
|
||||
; foreground = default
|
||||
|
||||
# SDL and sdl_glsl only support hex code colors, these are the default:
|
||||
; background = '#111111'
|
||||
; foreground = '#33ffff'
|
||||
|
||||
|
||||
# Gradient mode, only hex defined colors are supported,
|
||||
# background must also be defined in hex or remain commented out. 1 = on, 0 = off.
|
||||
# You can define as many as 8 different colors. They range from bottom to top of screen
|
||||
; gradient = 0
|
||||
; gradient_color_1 = '#59cc33'
|
||||
; gradient_color_2 = '#80cc33'
|
||||
; gradient_color_3 = '#a6cc33'
|
||||
; gradient_color_4 = '#cccc33'
|
||||
; gradient_color_5 = '#cca633'
|
||||
; gradient_color_6 = '#cc8033'
|
||||
; gradient_color_7 = '#cc5933'
|
||||
; gradient_color_8 = '#cc3333'
|
||||
|
||||
|
||||
# Horizontal is only supported on noncurses output.
|
||||
# Only one color will be calculated per bar.
|
||||
; horizontal_gradient = 0
|
||||
; horizontal_gradient_color_1 = '#c45161'
|
||||
; horizontal_gradient_color_2 = '#e094a0'
|
||||
; horizontal_gradient_color_3 = '#f2b6c0'
|
||||
; horizontal_gradient_color_4 = '#f2dde1'
|
||||
; horizontal_gradient_color_5 = '#cbc7d8'
|
||||
; horizontal_gradient_color_6 = '#8db7d2'
|
||||
; horizontal_gradient_color_7 = '#5e62a9'
|
||||
; horizontal_gradient_color_8 = '#434279'
|
||||
|
||||
|
||||
# If both vertical and horizontal gradient is enabled, vertical will be blended in this direction.
|
||||
# Can be 'up', 'down', 'left' or 'right'. 'up' means the vertical gradient will be blended in from
|
||||
# bottom to top. I.e. the bottom will be only the horizontal
|
||||
# and top will be only the color of the vertical gradient.
|
||||
; blend_direction = 'up'
|
||||
|
||||
# use theme file instead of defining colors in this file
|
||||
# themes are located in $HOME/.config/cava/themes
|
||||
; theme = 'none'
|
||||
|
||||
|
||||
[smoothing]
|
||||
|
||||
# Percentage value for integral smoothing. Takes values from 0 - 100.
|
||||
# Higher values means smoother, but less precise. 0 to disable.
|
||||
# DEPRECATED as of 0.8.0, use noise_reduction instead
|
||||
; integral = 77
|
||||
|
||||
# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable.
|
||||
; monstercat = 0
|
||||
; waves = 0
|
||||
|
||||
# Set gravity percentage for "drop off". Higher values means bars will drop faster.
|
||||
# Accepts only non-negative values. 50 means half gravity, 200 means double. Set to 0 to disable "drop off".
|
||||
# DEPRECATED as of 0.8.0, use noise_reduction instead
|
||||
; gravity = 100
|
||||
|
||||
|
||||
# In bar height, bars that would have been lower that this will not be drawn.
|
||||
# DEPRECATED as of 0.8.0
|
||||
; ignore = 0
|
||||
|
||||
# Noise reduction, int 0 - 100. default 77
|
||||
# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth
|
||||
# 100 will be very slow and smooth, 0 will be fast but noisy.
|
||||
; noise_reduction = 77
|
||||
|
||||
|
||||
[eq]
|
||||
|
||||
# This one is tricky. You can have as much keys as you want.
|
||||
# Remember to uncomment more than one key! More keys = more precision.
|
||||
# Look at readme.md on github for further explanations and examples.
|
||||
; 1 = 1 # bass
|
||||
; 2 = 1
|
||||
; 3 = 1 # midtone
|
||||
; 4 = 1
|
||||
; 5 = 1 # treble
|
||||
11
.config/cava/config.bak
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[color]
|
||||
gradient = 1
|
||||
|
||||
gradient_color_1 = '#81c8be'
|
||||
gradient_color_2 = '#99d1db'
|
||||
gradient_color_3 = '#85c1dc'
|
||||
gradient_color_4 = '#8caaee'
|
||||
gradient_color_5 = '#ca9ee6'
|
||||
gradient_color_6 = '#f4b8e4'
|
||||
gradient_color_7 = '#ea999c'
|
||||
gradient_color_8 = '#e78284'
|
||||
73
.config/cava/shaders/bar_spectrum.frag
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#version 330
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
// bar values. defaults to left channels first (low to high), then right (high to low).
|
||||
uniform float bars[512];
|
||||
|
||||
uniform int bars_count; // number of bars (left + right) (configurable)
|
||||
uniform int bar_width; // bar width (configurable), not used here
|
||||
uniform int bar_spacing; // space bewteen bars (configurable)
|
||||
|
||||
uniform vec3 u_resolution; // window resolution
|
||||
|
||||
// colors, configurable in cava config file (r,g,b) (0.0 - 1.0)
|
||||
uniform vec3 bg_color; // background color
|
||||
uniform vec3 fg_color; // foreground color
|
||||
|
||||
uniform int gradient_count;
|
||||
uniform vec3 gradient_colors[8]; // gradient colors
|
||||
|
||||
uniform float shader_time; // shader execution time s (not used here)
|
||||
|
||||
uniform sampler2D inputTexture; // Texture from the last render pass (not used here)
|
||||
|
||||
vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) {
|
||||
// create color based on fraction of this color and next color
|
||||
float yr = (y - y_min) / (y_max - y_min);
|
||||
return col_1 * (1.0 - yr) + col_2 * yr;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// find which bar to use based on where we are on the x axis
|
||||
float x = u_resolution.x * fragCoord.x;
|
||||
int bar = int(bars_count * fragCoord.x);
|
||||
|
||||
// calculate a bar size
|
||||
float bar_size = u_resolution.x / bars_count;
|
||||
|
||||
// the y coordinate and bar values are the same
|
||||
float y = bars[bar];
|
||||
|
||||
// make sure there is a thin line at bottom
|
||||
if (y * u_resolution.y < 1.0) {
|
||||
y = 1.0 / u_resolution.y;
|
||||
}
|
||||
|
||||
// draw the bar up to current height
|
||||
if (y > fragCoord.y) {
|
||||
// make some space between bars basen on settings
|
||||
if (x > (bar + 1) * (bar_size)-bar_spacing) {
|
||||
fragColor = vec4(bg_color, 1.0);
|
||||
} else {
|
||||
if (gradient_count == 0) {
|
||||
fragColor = vec4(fg_color, 1.0);
|
||||
} else {
|
||||
// find which color in the configured gradient we are at
|
||||
int color = int((gradient_count - 1) * fragCoord.y);
|
||||
|
||||
// find where on y this and next color is supposed to be
|
||||
float y_min = color / (gradient_count - 1.0);
|
||||
float y_max = (color + 1.0) / (gradient_count - 1.0);
|
||||
|
||||
// make color
|
||||
fragColor = vec4(normalize_C(fragCoord.y, gradient_colors[color],
|
||||
gradient_colors[color + 1], y_min, y_max),
|
||||
1.0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fragColor = vec4(bg_color, 1.0);
|
||||
}
|
||||
}
|
||||
117
.config/cava/shaders/eye_of_phi.frag
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
#version 330
|
||||
|
||||
// this shader was stolen from shadertoy user ChunderFPV
|
||||
|
||||
#define SCALE 8.0
|
||||
#define PI radians(180.0)
|
||||
#define TAU (PI * 2.0)
|
||||
#define CS(a) vec2(cos(a), sin(a))
|
||||
#define PT(u, r) smoothstep(0.0, r, r - length(u))
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform float bars[512];
|
||||
|
||||
uniform int bars_count; // number of bars (left + right) (configurable)
|
||||
uniform float shader_time; // shader execution time s
|
||||
uniform int bar_width; // bar width (configurable), not used here
|
||||
uniform int bar_spacing; // space bewteen bars (configurable)
|
||||
|
||||
uniform vec3 u_resolution; // window resolution
|
||||
|
||||
// colors, configurable in cava config file (r,g,b) (0.0 - 1.0)
|
||||
uniform vec3 bg_color; // background color
|
||||
uniform vec3 fg_color; // foreground color
|
||||
|
||||
uniform int gradient_count;
|
||||
uniform vec3 gradient_colors[8]; // gradient colors
|
||||
|
||||
// gradient map ( color, equation, time, width, shadow, reciprocal )
|
||||
vec3 gm(vec3 c, float n, float t, float w, float d, bool i) {
|
||||
float g = min(abs(n), 1.0 / abs(n));
|
||||
float s = abs(sin(n * PI - t));
|
||||
if (i)
|
||||
s = min(s, abs(sin(PI / n + t)));
|
||||
return (1.0 - pow(abs(s), w)) * c * pow(g, d) * 6.0;
|
||||
}
|
||||
|
||||
// denominator spiral, use 1/n for numerator
|
||||
// ( screen xy, spiral exponent, decimal, line width, hardness, rotation )
|
||||
float ds(vec2 u, float e, float n, float w, float h, float ro) {
|
||||
float ur = length(u); // unit radius
|
||||
float sr = pow(ur, e); // spiral radius
|
||||
float a = round(sr) * n * TAU; // arc
|
||||
vec2 xy = CS(a + ro) * ur; // xy coords
|
||||
float l = PT(u - xy, w); // line
|
||||
float s = mod(sr + 0.5, 1.0); // gradient smooth
|
||||
s = min(s, 1.0 - s); // darken filter
|
||||
return l * s * h;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float t = shader_time / PI * 2.0;
|
||||
vec4 m = vec4(0, 0, 0, 0); // iMouse;
|
||||
m.xy = m.xy * 2.0 / u_resolution.xy - 1.0; // ±1x, ±1y
|
||||
if (m.z > 0.0)
|
||||
t += m.y * SCALE; // move time with mouse y
|
||||
float z = (m.z > 0.0) ? pow(1.0 - abs(m.y), sign(m.y)) : 1.0; // zoom (+)
|
||||
float e = (m.z > 0.0) ? pow(1.0 - abs(m.x), -sign(m.x))
|
||||
: 1.0; // screen exponent (+)
|
||||
float se = (m.z > 0.0) ? e * -sign(m.y) : 1.0; // spiral exponent
|
||||
vec3 bg = vec3(0); // black background
|
||||
|
||||
float aa = 3.0; // anti-aliasing
|
||||
|
||||
for (float j = 0.0; j < aa; j++)
|
||||
for (float k = 0.0; k < aa; k++) {
|
||||
vec3 c = vec3(0);
|
||||
vec2 o = vec2(j, k) / aa;
|
||||
vec2 uv = (fragCoord * u_resolution.xy - 0.5 * u_resolution.xy + o) /
|
||||
u_resolution.y * SCALE * z; // apply cartesian, scale and zoom
|
||||
if (m.z > 0.0)
|
||||
uv =
|
||||
exp(log(abs(uv)) * e) * sign(uv); // warp screen space with exponent
|
||||
|
||||
float px = length(fwidth(uv)); // pixel width
|
||||
float x = uv.x; // every pixel on x
|
||||
float y = uv.y; // every pixel on y
|
||||
float l = length(uv); // hypot of xy: sqrt(x*x+y*y)
|
||||
|
||||
float mc = (x * x + y * y - 1.0) / y; // metallic circle at xy
|
||||
float g = min(abs(mc), 1.0 / abs(mc)); // gradient
|
||||
vec3 gold = vec3(1.0, 0.6, 0.0) * g * l;
|
||||
vec3 blue = vec3(0.3, 0.5, 0.9) * (1.0 - g);
|
||||
vec3 rgb = max(gold, blue);
|
||||
|
||||
float w = 0.1; // line width
|
||||
float d = 0.4; // shadow depth
|
||||
c = max(c, gm(rgb, mc, -t, w * bars[0], d, false)); // metallic
|
||||
c = max(c, gm(rgb, abs(y / x) * sign(y), -t, w * bars[1], d,
|
||||
false)); // tangent
|
||||
c = max(c, gm(rgb, (x * x) / (y * y) * sign(y), -t, w * bars[2], d,
|
||||
false)); // sqrt cotangent
|
||||
c = max(c, gm(rgb, (x * x) + (y * y), t, w * bars[3], d,
|
||||
true)); // sqrt circles
|
||||
|
||||
c += rgb * ds(uv, se, t / TAU, px * 2.0 * bars[4], 2.0, 0.0); // spiral 1a
|
||||
c += rgb * ds(uv, se, t / TAU, px * 2.0 * bars[5], 2.0, PI); // spiral 1b
|
||||
c +=
|
||||
rgb * ds(uv, -se, t / TAU, px * 2.0 * bars[6], 2.0, 0.0); // spiral 2a
|
||||
c += rgb * ds(uv, -se, t / TAU, px * 2.0 * bars[7], 2.0, PI); // spiral 2b
|
||||
c = max(c, 0.0); // clear negative color
|
||||
|
||||
c += pow(max(1.0 - l, 0.0), 3.0 / z); // center glow
|
||||
|
||||
if (m.z > 0.0) // display grid on click
|
||||
{
|
||||
vec2 xyg = abs(fract(uv + 0.5) - 0.5) / px; // xy grid
|
||||
c.gb += 0.2 * (1.0 - min(min(xyg.x, xyg.y), 1.0));
|
||||
}
|
||||
bg += c;
|
||||
}
|
||||
bg /= aa * aa;
|
||||
bg *= sqrt(bg) * 1.5;
|
||||
|
||||
fragColor = vec4(bg, 1.0);
|
||||
}
|
||||
34
.config/cava/shaders/northern_lights.frag
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#version 330
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
// bar values. defaults to left channels first (low to high), then right (high to low).
|
||||
uniform float bars[512];
|
||||
|
||||
uniform int bars_count; // number of bars (left + right) (configurable)
|
||||
|
||||
uniform vec3 u_resolution; // window resolution, not used here
|
||||
|
||||
//colors, configurable in cava config file
|
||||
uniform vec3 bg_color; // background color(r,g,b) (0.0 - 1.0), not used here
|
||||
uniform vec3 fg_color; // foreground color, not used here
|
||||
|
||||
void main()
|
||||
{
|
||||
// find which bar to use based on where we are on the x axis
|
||||
int bar = int(bars_count * fragCoord.x);
|
||||
|
||||
float bar_y = 1.0 - abs((fragCoord.y - 0.5)) * 2.0;
|
||||
float y = (bars[bar]) * bar_y;
|
||||
|
||||
float bar_x = (fragCoord.x - float(bar) / float(bars_count)) * bars_count;
|
||||
float bar_r = 1.0 - abs((bar_x - 0.5)) * 2;
|
||||
|
||||
bar_r = bar_r * bar_r * 2;
|
||||
|
||||
// set color
|
||||
fragColor.r = fg_color.x * y * bar_r;
|
||||
fragColor.g = fg_color.y * y * bar_r;
|
||||
fragColor.b = fg_color.z * y * bar_r;
|
||||
}
|
||||
14
.config/cava/shaders/pass_through.vert
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#version 330
|
||||
|
||||
|
||||
// Input vertex data, different for all executions of this shader.
|
||||
layout(location = 0) in vec3 vertexPosition_modelspace;
|
||||
|
||||
// Output data ; will be interpolated for each fragment.
|
||||
out vec2 fragCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vertexPosition_modelspace,1);
|
||||
fragCoord = (vertexPosition_modelspace.xy+vec2(1,1))/2.0;
|
||||
}
|
||||
53
.config/cava/shaders/spectrogram.frag
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#version 330
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
// bar values. defaults to left channels first (low to high), then right (high
|
||||
// to low).
|
||||
uniform float bars[512];
|
||||
|
||||
uniform int bars_count; // number of bars (left + right) (configurable)
|
||||
uniform int bar_width; // bar width (configurable), not used here
|
||||
uniform int bar_spacing; // space bewteen bars (configurable)
|
||||
|
||||
uniform vec3 u_resolution; // window resolution
|
||||
|
||||
// colors, configurable in cava config file (r,g,b) (0.0 - 1.0)
|
||||
uniform vec3 bg_color; // background color
|
||||
uniform vec3 fg_color; // foreground color
|
||||
|
||||
uniform int gradient_count;
|
||||
uniform vec3 gradient_colors[8]; // gradient colors
|
||||
|
||||
uniform sampler2D inputTexture; // Texture from the last render pass
|
||||
|
||||
vec3 normalize_C(float y, vec3 col_1, vec3 col_2, float y_min, float y_max) {
|
||||
// create color based on fraction of this color and next color
|
||||
float yr = (y - y_min) / (y_max - y_min);
|
||||
return col_1 * (1.0 - yr) + col_2 * yr;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// find which bar to use based on where we are on the y axis
|
||||
int bar = int(bars_count * fragCoord.y);
|
||||
float y = bars[bar];
|
||||
float band_size = 1.0 / float(bars_count);
|
||||
float current_band_min = bar * band_size;
|
||||
float current_band_max = (bar + 1) * band_size;
|
||||
|
||||
int hist_length = 512;
|
||||
float win_size = 1.0 / hist_length;
|
||||
|
||||
if (fragCoord.x > 1.0 - win_size) {
|
||||
|
||||
if (fragCoord.y > current_band_min && fragCoord.y < current_band_max) {
|
||||
|
||||
fragColor = vec4(fg_color * y, 1.0);
|
||||
}
|
||||
} else {
|
||||
vec2 offsetCoord = fragCoord;
|
||||
offsetCoord.x += float(win_size);
|
||||
fragColor = texture(inputTexture, offsetCoord);
|
||||
}
|
||||
}
|
||||
112
.config/cava/shaders/winamp_line_style_spectrum.frag
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#version 330
|
||||
|
||||
// Emulate the "line style" spectrum analyzer from Winamp 2.
|
||||
// Try this config for a demonstration:
|
||||
|
||||
/*
|
||||
[general]
|
||||
bar_width = 2
|
||||
bar_spacing = 0
|
||||
higher_cutoff_freq = 22000
|
||||
|
||||
[output]
|
||||
method = sdl_glsl
|
||||
channels = mono
|
||||
fragment_shader = winamp_line_style_spectrum.frag
|
||||
|
||||
[color]
|
||||
background = '#000000'
|
||||
gradient = 1
|
||||
gradient_color_1 = '#319C08'
|
||||
gradient_color_2 = '#29CE10'
|
||||
gradient_color_3 = '#BDDE29'
|
||||
gradient_color_4 = '#DEA518'
|
||||
gradient_color_5 = '#D66600'
|
||||
gradient_color_6 = '#CE2910'
|
||||
|
||||
[smoothing]
|
||||
noise_reduction = 10
|
||||
*/
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
// bar values. defaults to left channels first (low to high), then right (high to low).
|
||||
uniform float bars[512];
|
||||
|
||||
uniform int bars_count; // number of bars (left + right) (configurable)
|
||||
uniform int bar_width; // bar width (configurable), not used here
|
||||
uniform int bar_spacing; // space bewteen bars (configurable)
|
||||
|
||||
uniform vec3 u_resolution; // window resolution
|
||||
|
||||
//colors, configurable in cava config file (r,g,b) (0.0 - 1.0)
|
||||
uniform vec3 bg_color; // background color
|
||||
uniform vec3 fg_color; // foreground color
|
||||
|
||||
uniform int gradient_count;
|
||||
uniform vec3 gradient_colors[8]; // gradient colors
|
||||
|
||||
vec3 normalize_C(float y,vec3 col_1, vec3 col_2, float y_min, float y_max)
|
||||
{
|
||||
//create color based on fraction of this color and next color
|
||||
float yr = (y - y_min) / (y_max - y_min);
|
||||
return col_1 * (1.0 - yr) + col_2 * yr;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// find which bar to use based on where we are on the x axis
|
||||
float x = u_resolution.x * fragCoord.x;
|
||||
int bar = int(bars_count * fragCoord.x);
|
||||
|
||||
//calculate a bar size
|
||||
float bar_size = u_resolution.x / bars_count;
|
||||
|
||||
//the y coordinate is stretched by 4X to resemble Winamp
|
||||
float y = min(bars[bar] * 4.0, 1.0);
|
||||
|
||||
// make sure there is a thin line at bottom
|
||||
if (y * u_resolution.y < 1.0)
|
||||
{
|
||||
y = 1.0 / u_resolution.y;
|
||||
}
|
||||
|
||||
vec4 bar_color;
|
||||
|
||||
if (gradient_count == 0)
|
||||
{
|
||||
bar_color = vec4(fg_color,1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//find color in the configured gradient for the top of the bar
|
||||
int color = int((gradient_count - 1) * y);
|
||||
|
||||
//find where on y this and next color is supposed to be
|
||||
float y_min = float(color) / (gradient_count - 1.0);
|
||||
float y_max = float(color + 1) / (gradient_count - 1.0);
|
||||
|
||||
//make a solid color for the entire bar
|
||||
bar_color = vec4(normalize_C(y, gradient_colors[color], gradient_colors[color + 1], y_min, y_max), 1.0);
|
||||
}
|
||||
|
||||
|
||||
//draw the bar up to current height
|
||||
if (y > fragCoord.y)
|
||||
{
|
||||
//make some space between bars based on settings
|
||||
if (x > (bar + 1) * (bar_size) - bar_spacing)
|
||||
{
|
||||
fragColor = vec4(bg_color,1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fragColor = bar_color;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fragColor = vec4(bg_color,1.0);
|
||||
}
|
||||
}
|
||||
15
.config/cava/themes/solarized_dark
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[color]
|
||||
background = '#001e26'
|
||||
foreground = '#708183'
|
||||
|
||||
gradient = 1
|
||||
gradient_color_1 = '#268bd2'
|
||||
gradient_color_2 = '#6c71c4'
|
||||
gradient_color_3 = '#cb4b16'
|
||||
|
||||
horizontal_gradient = 1
|
||||
horizontal_gradient_color_1 = '#586e75'
|
||||
horizontal_gradient_color_2 = '#b58900'
|
||||
horizontal_gradient_color_3 = '#839496'
|
||||
|
||||
blend_direction = 'up'
|
||||
10
.config/cava/themes/tricolor
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[color]
|
||||
horizontal_gradient = 1
|
||||
horizontal_gradient_color_1 = '#c45161'
|
||||
horizontal_gradient_color_2 = '#e094a0'
|
||||
horizontal_gradient_color_3 = '#f2b6c0'
|
||||
horizontal_gradient_color_4 = '#f2dde1'
|
||||
horizontal_gradient_color_5 = '#cbc7d8'
|
||||
horizontal_gradient_color_6 = '#8db7d2'
|
||||
horizontal_gradient_color_7 = '#5e62a9'
|
||||
horizontal_gradient_color_8 = '#434279'
|
||||
1
.config/fastfetch
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5125578d9ceb787b923a91f4416f4b49f18806f3
|
||||
12
.config/fuzzel/fuzzel.ini
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[colors]
|
||||
background=eff1f5ff
|
||||
text=4c4f69ff
|
||||
prompt=5c5f77ff
|
||||
placeholder=8c8fa1ff
|
||||
input=4c4f69ff
|
||||
match=1e66f5ff
|
||||
selection=acb0beff
|
||||
selection-text=4c4f69ff
|
||||
selection-match=1e66f5ff
|
||||
counter=8c8fa1ff
|
||||
border=1e66f5ff
|
||||
21
.config/kitty/current-theme.conf
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
background #212733
|
||||
foreground #d9d7ce
|
||||
cursor #ffcc66
|
||||
selection_background #343f4c
|
||||
color0 #191e2a
|
||||
color8 #686868
|
||||
color1 #ed8274
|
||||
color9 #f28779
|
||||
color2 #a6cc70
|
||||
color10 #bae67e
|
||||
color3 #fad07b
|
||||
color11 #ffd580
|
||||
color4 #6dcbfa
|
||||
color12 #73d0ff
|
||||
color5 #cfbafa
|
||||
color13 #d4bfff
|
||||
color6 #90e1c6
|
||||
color14 #95e6cb
|
||||
color7 #c7c7c7
|
||||
color15 #ffffff
|
||||
selection_foreground #212733
|
||||
2801
.config/kitty/kitty.conf
Normal file
12
.config/mako/config
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Colors
|
||||
|
||||
background-color=#303446
|
||||
text-color=#c6d0f5
|
||||
border-color=#8caaee
|
||||
progress-color=over #414559
|
||||
default-timeout=5000
|
||||
border-radius=12
|
||||
font=hack 11
|
||||
|
||||
[urgency=high]
|
||||
border-color=#ef9f76
|
||||
1
.config/niri
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7648a2af7b3432e34a4fbcb5a2981f05a2c1f3b7
|
||||
29
.config/swaylock/config
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
color=1e1e2e
|
||||
bs-hl-color=f5e0dc
|
||||
caps-lock-bs-hl-color=f5e0dc
|
||||
caps-lock-key-hl-color=a6e3a1
|
||||
inside-color=00000000
|
||||
inside-clear-color=00000000
|
||||
inside-caps-lock-color=00000000
|
||||
inside-ver-color=00000000
|
||||
inside-wrong-color=00000000
|
||||
key-hl-color=a6e3a1
|
||||
layout-bg-color=00000000
|
||||
layout-border-color=00000000
|
||||
layout-text-color=cdd6f4
|
||||
line-color=00000000
|
||||
line-clear-color=00000000
|
||||
line-caps-lock-color=00000000
|
||||
line-ver-color=00000000
|
||||
line-wrong-color=00000000
|
||||
ring-color=b4befe
|
||||
ring-clear-color=f5e0dc
|
||||
ring-caps-lock-color=fab387
|
||||
ring-ver-color=89b4fa
|
||||
ring-wrong-color=eba0ac
|
||||
separator-color=00000000
|
||||
text-color=cdd6f4
|
||||
text-clear-color=f5e0dc
|
||||
text-caps-lock-color=fab387
|
||||
text-ver-color=89b4fa
|
||||
text-wrong-color=eba0ac
|
||||
100
.config/swaync/config.json
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"$schema": "/etc/xdg/swaync/configSchema.json",
|
||||
"ignore-gtk-theme": true,
|
||||
"positionX": "right",
|
||||
"positionY": "top",
|
||||
"layer": "overlay",
|
||||
"control-center-layer": "top",
|
||||
"layer-shell": true,
|
||||
"layer-shell-cover-screen": true,
|
||||
"cssPriority": "user",
|
||||
"control-center-margin-top": 0,
|
||||
"control-center-margin-bottom": 0,
|
||||
"control-center-margin-right": 0,
|
||||
"control-center-margin-left": 0,
|
||||
"notification-2fa-action": true,
|
||||
"notification-inline-replies": false,
|
||||
"notification-body-image-height": 100,
|
||||
"notification-body-image-width": 200,
|
||||
"timeout": 10,
|
||||
"timeout-low": 5,
|
||||
"timeout-critical": 0,
|
||||
"fit-to-screen": true,
|
||||
"relative-timestamps": true,
|
||||
"control-center-width": 500,
|
||||
"control-center-height": 600,
|
||||
"notification-window-width": 500,
|
||||
"keyboard-shortcuts": true,
|
||||
"notification-grouping": true,
|
||||
"image-visibility": "when-available",
|
||||
"transition-time": 200,
|
||||
"hide-on-clear": false,
|
||||
"hide-on-action": true,
|
||||
"text-empty": "No Notifications",
|
||||
"script-fail-notify": true,
|
||||
"scripts": {
|
||||
"example-script": {
|
||||
"exec": "echo 'Do something...'",
|
||||
"urgency": "Normal"
|
||||
},
|
||||
"example-action-script": {
|
||||
"exec": "echo 'Do something actionable!'",
|
||||
"urgency": "Normal",
|
||||
"run-on": "action"
|
||||
}
|
||||
},
|
||||
"notification-visibility": {
|
||||
"example-name": {
|
||||
"state": "muted",
|
||||
"urgency": "Low",
|
||||
"app-name": "Spotify"
|
||||
}
|
||||
},
|
||||
"widgets": [
|
||||
"inhibitors",
|
||||
"title",
|
||||
"dnd",
|
||||
"notifications"
|
||||
],
|
||||
"widget-config": {
|
||||
"notifications": {
|
||||
"vexpand": true
|
||||
},
|
||||
"inhibitors": {
|
||||
"text": "Inhibitors",
|
||||
"button-text": "Clear All",
|
||||
"clear-all-button": true
|
||||
},
|
||||
"title": {
|
||||
"text": "Notifications",
|
||||
"clear-all-button": true,
|
||||
"button-text": "Clear All"
|
||||
},
|
||||
"dnd": {
|
||||
"text": "Do Not Disturb"
|
||||
},
|
||||
"label": {
|
||||
"max-lines": 5,
|
||||
"text": "Label Text"
|
||||
},
|
||||
"mpris": {
|
||||
"blacklist": [],
|
||||
"autohide": false,
|
||||
"show-album-art": "always",
|
||||
"loop-carousel": false
|
||||
},
|
||||
"buttons-grid": {
|
||||
"buttons-per-row": 7,
|
||||
"actions": [
|
||||
{
|
||||
"label": "直",
|
||||
"type": "toggle",
|
||||
"active": true,
|
||||
"command": "sh -c '[[ $SWAYNC_TOGGLE_STATE == true ]] && nmcli radio wifi on || nmcli radio wifi off'",
|
||||
"update-command": "sh -c '[[ $(nmcli radio wifi) == \"enabled\" ]] && echo true || echo false'"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
"style": "~/.config/swaync/style.css"
|
||||
}
|
||||
328
.config/swaync/style.css
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
* {
|
||||
all: unset;
|
||||
font-size: 14px;
|
||||
font-family: "Ubuntu Nerd Font";
|
||||
transition: 200ms;
|
||||
}
|
||||
|
||||
trough highlight {
|
||||
background: #cdd6f4;
|
||||
}
|
||||
|
||||
scale {
|
||||
margin: 0 7px;
|
||||
}
|
||||
|
||||
scale trough {
|
||||
margin: 0rem 1rem;
|
||||
min-height: 8px;
|
||||
min-width: 70px;
|
||||
border-radius: 12.6px;
|
||||
}
|
||||
|
||||
trough slider {
|
||||
margin: -10px;
|
||||
border-radius: 12.6px;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
|
||||
transition: all 0.2s ease;
|
||||
background-color: #89b4fa;
|
||||
}
|
||||
|
||||
trough slider:hover {
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.8), 0 0 8px #89b4fa;
|
||||
}
|
||||
|
||||
trough {
|
||||
background-color: #313244;
|
||||
}
|
||||
|
||||
/* notifications */
|
||||
.notification-background {
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.8), inset 0 0 0 1px #45475a;
|
||||
border-radius: 12.6px;
|
||||
margin: 18px;
|
||||
background: #181825;
|
||||
color: #cdd6f4;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.notification-background .notification {
|
||||
padding: 7px;
|
||||
border-radius: 12.6px;
|
||||
}
|
||||
|
||||
.notification-background .notification.critical {
|
||||
box-shadow: inset 0 0 7px 0 #f38ba8;
|
||||
}
|
||||
|
||||
.notification .notification-content {
|
||||
margin: 7px;
|
||||
}
|
||||
|
||||
.notification .notification-content overlay {
|
||||
/* icons */
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.notification-content .summary {
|
||||
color: #cdd6f4;
|
||||
}
|
||||
|
||||
.notification-content .time {
|
||||
color: #a6adc8;
|
||||
}
|
||||
|
||||
.notification-content .body {
|
||||
color: #bac2de;
|
||||
}
|
||||
|
||||
.notification > *:last-child > * {
|
||||
min-height: 3.4em;
|
||||
}
|
||||
|
||||
.notification-background .close-button {
|
||||
margin: 7px;
|
||||
padding: 2px;
|
||||
border-radius: 6.3px;
|
||||
color: #1e1e2e;
|
||||
background-color: #f38ba8;
|
||||
}
|
||||
|
||||
.notification-background .close-button:hover {
|
||||
background-color: #eba0ac;
|
||||
}
|
||||
|
||||
.notification-background .close-button:active {
|
||||
background-color: #f5c2e7;
|
||||
}
|
||||
|
||||
.notification .notification-action {
|
||||
border-radius: 7px;
|
||||
color: #cdd6f4;
|
||||
box-shadow: inset 0 0 0 1px #45475a;
|
||||
margin: 4px;
|
||||
padding: 8px;
|
||||
font-size: 0.2rem; /* controls the button size not text size*/
|
||||
}
|
||||
|
||||
.notification .notification-action {
|
||||
background-color: #313244;
|
||||
}
|
||||
|
||||
.notification .notification-action:hover {
|
||||
background-color: #45475a;
|
||||
}
|
||||
|
||||
.notification .notification-action:active {
|
||||
background-color: #585b70;
|
||||
}
|
||||
|
||||
.notification.critical progress {
|
||||
background-color: #f38ba8;
|
||||
}
|
||||
|
||||
.notification.low progress,
|
||||
.notification.normal progress {
|
||||
background-color: #89b4fa;
|
||||
}
|
||||
|
||||
.notification progress,
|
||||
.notification trough,
|
||||
.notification progressbar {
|
||||
border-radius: 12.6px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
/* control center */
|
||||
.control-center {
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.8), inset 0 0 0 1px #313244;
|
||||
border-radius: 12.6px;
|
||||
background-color: #1e1e2e;
|
||||
color: #cdd6f4;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.control-center .notification-background {
|
||||
border-radius: 7px;
|
||||
box-shadow: inset 0 0 0 1px #45475a;
|
||||
margin: 4px 10px;
|
||||
}
|
||||
|
||||
.control-center .notification-background .notification {
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.control-center .notification-background .notification.low {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.control-center .widget-title > label {
|
||||
color: #cdd6f4;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.control-center .widget-title button {
|
||||
border-radius: 7px;
|
||||
color: #cdd6f4;
|
||||
background-color: #313244;
|
||||
box-shadow: inset 0 0 0 1px #45475a;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.control-center .widget-title button:hover {
|
||||
background-color: #45475a;
|
||||
}
|
||||
|
||||
.control-center .widget-title button:active {
|
||||
background-color: #585b70;
|
||||
}
|
||||
|
||||
.control-center .notification-group {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.control-center .notification-group:focus .notification-background {
|
||||
background-color: #313244;
|
||||
}
|
||||
|
||||
scrollbar slider {
|
||||
margin: -3px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
scrollbar trough {
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
/* dnd */
|
||||
.widget-dnd {
|
||||
margin-top: 5px;
|
||||
border-radius: 8px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.widget-dnd > switch {
|
||||
font-size: initial;
|
||||
border-radius: 8px;
|
||||
background: #313244;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.widget-dnd > switch:checked {
|
||||
background: #89b4fa;
|
||||
}
|
||||
|
||||
.widget-dnd > switch slider {
|
||||
background: #45475a;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* mpris */
|
||||
.widget-mpris-player {
|
||||
background: #313244;
|
||||
border-radius: 12.6px;
|
||||
color: #cdd6f4;
|
||||
}
|
||||
|
||||
.mpris-overlay {
|
||||
background-color: #313244;
|
||||
opacity: 0.9;
|
||||
padding: 15px 10px;
|
||||
}
|
||||
|
||||
.widget-mpris-album-art {
|
||||
-gtk-icon-size: 100px;
|
||||
border-radius: 12.6px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.widget-mpris-title {
|
||||
font-size: 1.2rem;
|
||||
color: #cdd6f4;
|
||||
}
|
||||
|
||||
.widget-mpris-subtitle {
|
||||
font-size: 1rem;
|
||||
color: #bac2de;
|
||||
}
|
||||
|
||||
.widget-mpris button {
|
||||
border-radius: 12.6px;
|
||||
color: #cdd6f4;
|
||||
margin: 0 5px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.widget-mpris button image {
|
||||
-gtk-icon-size: 1.8rem;
|
||||
}
|
||||
|
||||
.widget-mpris button:hover {
|
||||
background-color: #313244;
|
||||
}
|
||||
|
||||
.widget-mpris button:active {
|
||||
background-color: #45475a;
|
||||
}
|
||||
|
||||
.widget-mpris button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.widget-menubar > box > .menu-button-bar > button > label {
|
||||
font-size: 3rem;
|
||||
padding: 0.5rem 2rem;
|
||||
}
|
||||
|
||||
.widget-menubar > box > .menu-button-bar > :last-child {
|
||||
color: #f38ba8;
|
||||
}
|
||||
|
||||
.power-buttons button:hover,
|
||||
.powermode-buttons button:hover,
|
||||
.screenshot-buttons button:hover {
|
||||
background: #313244;
|
||||
}
|
||||
|
||||
.control-center .widget-label > label {
|
||||
color: #cdd6f4;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.widget-buttons-grid {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.widget-buttons-grid > flowbox > flowboxchild > button label {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.widget-volume {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.widget-volume label {
|
||||
color: #74c7ec;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.widget-volume trough highlight {
|
||||
background: #74c7ec;
|
||||
}
|
||||
|
||||
.widget-backlight trough highlight {
|
||||
background: #f9e2af;
|
||||
}
|
||||
|
||||
.widget-backlight label {
|
||||
font-size: 1.5rem;
|
||||
color: #f9e2af;
|
||||
}
|
||||
|
||||
.widget-backlight .KB {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.image {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
1
.config/waybar
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit d9bf08408520d01d221f7f1f49353ad5b98a623b
|
||||
7
.config/wlogout/icons/hibernate.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#8aadf4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><g><path d="M500,10C229.4,10,10,229.4,10,500s219.4,490,490,490s490-219.4,490-490S770.6,10,500,10z M500,885.1c-212.7,0-385.1-172.4-385.1-385.1S287.3,114.9,500,114.9S885.1,287.3,885.1,500S712.7,885.1,500,885.1z M576.5,308.7v382.4c0,42.2-34.2,76.5-76.5,76.5c-42.3,0-76.5-34.2-76.5-76.5V308.7c0-42.2,34.2-76.5,76.5-76.5C542.2,232.3,576.5,266.5,576.5,308.7z"/></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 969 B |
7
.config/wlogout/icons/lock.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#8aadf4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><g><path d="M321.8,455.5h356.4V321.8c0-49.2-17.4-91.2-52.2-126c-34.8-34.8-76.8-52.2-126-52.2c-49.2,0-91.2,17.4-126,52.2c-34.8,34.8-52.2,76.8-52.2,126L321.8,455.5L321.8,455.5z M900.9,522.3v400.9c0,18.6-6.5,34.3-19.5,47.3c-13,13-28.8,19.5-47.3,19.5H165.9c-18.6,0-34.3-6.5-47.3-19.5s-19.5-28.8-19.5-47.3V522.3c0-18.6,6.5-34.3,19.5-47.3c13-13,28.8-19.5,47.3-19.5h22.3V321.8c0-85.4,30.6-158.7,91.9-219.9C341.3,40.6,414.6,10,500,10c85.4,0,158.7,30.6,219.9,91.9c61.3,61.3,91.9,134.6,91.9,219.9v133.6h22.3c18.6,0,34.3,6.5,47.3,19.5C894.4,487.9,900.9,503.7,900.9,522.3L900.9,522.3z"/></g></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
7
.config/wlogout/icons/logout.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#8aadf4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M622.5,990H50.8C26.3,990,10,973.7,10,949.2V50.8C10,26.3,26.3,10,50.8,10h571.7c24.5,0,40.8,16.3,40.8,40.8v285.8c0,24.5-16.3,40.8-40.8,40.8s-40.8-16.3-40.8-40.8v-245h-490v816.7h490v-245c0-24.5,16.3-40.8,40.8-40.8s40.8,16.3,40.8,40.8v285.8C663.3,973.7,647,990,622.5,990z"/><path d="M949.2,540.8H336.7c-24.5,0-40.8-16.3-40.8-40.8c0-24.5,16.3-40.8,40.8-40.8h612.5c24.5,0,40.8,16.3,40.8,40.8C990,524.5,973.7,540.8,949.2,540.8z"/><path d="M949.2,540.8c-12.3,0-20.4-4.1-28.6-12.3L757.3,365.3c-16.3-16.3-16.3-40.8,0-57.2c16.3-16.3,40.8-16.3,57.2,0l163.3,163.3c16.3,16.3,16.3,40.8,0,57.2C969.6,536.8,961.4,540.8,949.2,540.8z"/><path d="M785.8,704.2c-12.3,0-20.4-4.1-28.6-12.3c-16.3-16.3-16.3-40.8,0-57.2l163.3-163.3c16.3-16.3,40.8-16.3,57.2,0c16.3,16.3,16.3,40.8,0,57.2L814.4,691.9C806.3,700.1,798.1,704.2,785.8,704.2z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
7
.config/wlogout/icons/reboot.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#8aadf4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M134.6,285.6C64.9,420.7,60.1,590,137.1,723.4L42,668.5l-32,55.4c93.1,52.1,133.6,75.9,184,106.2c28.5-51.5,52.8-94.4,107.4-186.1L246,612l-53.4,92.5C65.4,502.7,167.2,200.3,398.8,126.2C638,29.3,929,223.5,931.5,481.5c19.6,236.7-208.9,443.6-439.3,416.2l-29.5,51c277.7,54.4,556.5-201.7,524.7-483.1C976.1,170.8,637.1-41.2,367.1,77.5C262.8,114.2,183.1,191.5,134.6,285.6z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 877 B |
7
.config/wlogout/icons/shutdown.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#8aadf4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M764,152.1c30.9,22,58.3,46.8,82.4,74.6c24,27.8,44.6,57.8,61.8,90.1c17.2,32.3,30.2,66.4,39.1,102.4c8.9,36,13.4,72.6,13.4,109.6c0,63.8-12.2,123.7-36.5,179.6c-24.4,55.9-57.3,104.7-98.8,146.2c-41.5,41.5-90.2,74.5-146.2,98.8C623.2,977.8,563.3,990,499.5,990c-63.1,0-122.7-12.2-178.6-36.5c-55.9-24.4-104.8-57.3-146.7-98.8c-41.9-41.5-74.8-90.2-98.8-146.2c-24-55.9-36-115.8-36-179.6c0-36.4,4.3-72.1,12.9-107.1c8.6-35,20.8-68.3,36.5-99.9c15.8-31.6,35.3-61.1,58.7-88.5c23.3-27.5,49.4-52.2,78.2-74.1c15.1-11,31.4-15.1,48.9-12.4c17.5,2.7,31.7,11.3,42.7,25.7c11,14.4,15.1,30.5,12.4,48.4c-2.7,17.8-11.3,32.3-25.7,43.2c-43.2,31.6-76.4,70.3-99.3,116.3c-23,46-34.5,95.4-34.5,148.2c0,45.3,8.6,88,25.7,128.2c17.2,40.1,40.7,75.1,70.5,105c29.9,29.9,64.9,53.5,105,71c40.1,17.5,82.9,26.3,128.2,26.3c45.3,0,88-8.7,128.2-26.3c40.1-17.5,75.1-41.2,105-71s53.5-64.9,71-105c17.5-40.1,26.3-82.9,26.3-128.2c0-53.5-12.4-104.1-37.1-151.8c-24.7-47.7-59.4-87-104-117.9c-15.1-10.3-24.2-24.4-27.3-42.2c-3.1-17.8,0.5-34.3,10.8-49.4c10.3-14.4,24.4-23.2,42.2-26.2C732.5,138.2,748.9,141.8,764,152.1L764,152.1z M499.5,531.9c-17.8,0-33.1-6.3-45.8-19c-12.7-12.7-19-28-19-45.8V75.9c0-17.8,6.3-33.3,19-46.3c12.7-13,28-19.6,45.8-19.6c18.5,0,34.1,6.5,46.8,19.6c12.7,13,19,28.5,19,46.3v391.2c0,17.8-6.3,33.1-19,45.8C533.6,525.6,518,531.9,499.5,531.9L499.5,531.9z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
7
.config/wlogout/icons/suspend.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#8aadf4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M500,990c-66.1,0-130.3-13-190.7-38.5c-58.4-24.7-110.8-60-155.7-105s-80.3-97.4-105-155.7C23,630.3,10,566.1,10,500c0-66.1,13-130.3,38.5-190.7c24.7-58.4,60-110.8,105-155.7c45-45,97.4-80.3,155.7-105C369.7,23,433.9,10,500,10c66.1,0,130.3,13,190.7,38.5c58.4,24.7,110.8,60,155.7,105c45,45,80.3,97.4,105,155.7C977,369.7,990,433.9,990,500c0,66.1-13,130.3-38.5,190.7c-24.7,58.4-60,110.8-105,155.7s-97.4,80.3-155.7,105C630.3,977,566.1,990,500,990z M500,79.6c-112.3,0-217.9,43.7-297.3,123.1C123.3,282.1,79.6,387.7,79.6,500s43.7,217.9,123.1,297.3c79.4,79.4,185,123.1,297.3,123.1c112.3,0,217.9-43.7,297.3-123.1c79.4-79.4,123.1-185,123.1-297.3s-43.7-217.9-123.1-297.3C717.9,123.3,612.3,79.6,500,79.6z"/><path d="M322.5,290.6h108v412h-108V290.6z"/><path d="M561.6,290.6h107.9v412H561.6V290.6z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
36
.config/wlogout/layout
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"label" : "lock",
|
||||
"action" : "sh -c '( swaylock --screenshots --clock --indicator --indicator-radius 100 --indicator-thickness 7 --effect-blur 10x10)' & disown",
|
||||
"text" : "Lock",
|
||||
"keybind" : "l"
|
||||
}
|
||||
{
|
||||
"label" : "hibernate",
|
||||
"action" : "systemctl hibernate",
|
||||
"text" : "Hibernate",
|
||||
"keybind" : "h"
|
||||
}
|
||||
{
|
||||
"label" : "logout",
|
||||
"action" : "sh -c 'niri msg action quit skip-confirmation=true'",
|
||||
"text" : "Logout",
|
||||
"keybind" : "e"
|
||||
}
|
||||
{
|
||||
"label" : "shutdown",
|
||||
"action" : "systemctl poweroff",
|
||||
"text" : "Shutdown",
|
||||
"keybind" : "s"
|
||||
}
|
||||
{
|
||||
"label" : "suspend",
|
||||
"action" : "systemctl suspend",
|
||||
"text" : "Suspend",
|
||||
"keybind" : "u"
|
||||
}
|
||||
{
|
||||
"label" : "reboot",
|
||||
"action" : "systemctl reboot",
|
||||
"text" : "Reboot",
|
||||
"keybind" : "r"
|
||||
}
|
||||
54
.config/wlogout/style.css
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
* {
|
||||
background-image: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
window {
|
||||
background-color: rgba(30, 30, 46, 0.5);
|
||||
}
|
||||
|
||||
button {
|
||||
border-color: #89b4fa;
|
||||
text-decoration-color: #cdd6f4;
|
||||
color: #cdd6f4;
|
||||
background-color: #181825;
|
||||
border-style: solid;
|
||||
border-width: 1.5px;
|
||||
border-radius: 8px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 45%;
|
||||
background-size: 18%;
|
||||
margin: 13px;
|
||||
}
|
||||
|
||||
button:focus, button:active, button:hover {
|
||||
/* 20% Overlay 2, 80% mantle */
|
||||
background-color: rgb(48, 50, 66);
|
||||
outline-style: none;
|
||||
}
|
||||
|
||||
|
||||
#lock {
|
||||
background-image: url("./icons/lock.svg");
|
||||
}
|
||||
|
||||
#logout {
|
||||
background-image: url("./icons/logout.svg");
|
||||
}
|
||||
|
||||
#suspend {
|
||||
background-image: url("./icons/suspend.svg");
|
||||
}
|
||||
|
||||
#hibernate {
|
||||
background-image: url("./icons/hibernate.svg");
|
||||
}
|
||||
|
||||
#shutdown {
|
||||
background-image: url("./icons/shutdown.svg");
|
||||
}
|
||||
|
||||
#reboot {
|
||||
background-image: url("./icons/reboot.svg");
|
||||
}
|
||||
15
.config/wofi/config
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
hide_scroll=true
|
||||
prompt=Launch
|
||||
normal_window=true
|
||||
no_actions=true
|
||||
line_wrap=word
|
||||
show-icons=true
|
||||
width=550
|
||||
height=335
|
||||
allow_images=true
|
||||
always_parse_args=true
|
||||
show_all=false
|
||||
term=kitty
|
||||
insensitive=true
|
||||
print_command=true
|
||||
gtk_dark=false
|
||||
5
.config/wofi/gruvbox.css
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@define-color accent #BFAA80;
|
||||
@define-color txt #DDD5C4;
|
||||
@define-color bg #2C2A24;
|
||||
@define-color bg2 #3A372F;
|
||||
@define-color accent2 #8D7AAE;
|
||||
76
.config/wofi/style.css
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
@import '/home/cloverta/.config/wofi/gruvbox.css';
|
||||
|
||||
* {
|
||||
font-family: 'Iosevka Nerd Font mono';
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Window */
|
||||
window {
|
||||
margin: 0px;
|
||||
padding: 10px;
|
||||
border-radius: 0px;
|
||||
background-color: @bg;
|
||||
}
|
||||
|
||||
/* Inner Box */
|
||||
#inner-box {
|
||||
margin: 5px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background-color: @bg;
|
||||
}
|
||||
|
||||
|
||||
/* Outer Box */
|
||||
#outer-box {
|
||||
margin: 5px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
background-color: @bg;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Scroll */
|
||||
#scroll {
|
||||
margin: 0px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Input */
|
||||
#input {
|
||||
margin: 10px 25px 10px 25px;
|
||||
padding: 10px;
|
||||
color: @accent;
|
||||
background-color: @bg;
|
||||
border: 2px solid @accent;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Text */
|
||||
#text {
|
||||
margin: 5px;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
color: @txt;
|
||||
}
|
||||
|
||||
/* Selected Entry */
|
||||
#entry:selected {
|
||||
background-color: @bg;
|
||||
border: 1px solid @accent2;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#entry:selected #text {
|
||||
color: @txt;
|
||||
}
|
||||
image {
|
||||
margin-left: 10px;
|
||||
}
|
||||
/*entfernen des anderen durch .left oder .right*/
|
||||
#input > image.right {
|
||||
-gtk-icon-transform:scaleX(0);
|
||||
}
|
||||
218
install.sh
Executable file
|
|
@ -0,0 +1,218 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "This Script is used to install this dot from a CLEAN INSTALLATION of ARCH LINUX."
|
||||
echo "If you have set up Niri/sddm/other DE already, you can simply use the other Script replace.sh."
|
||||
echo "Note that this Script is more about convience so it might break your own configuration."
|
||||
echo "Do you wish to continue?[y/N]"
|
||||
|
||||
while true; do
|
||||
read -r yn2 || yn2=""
|
||||
yn2=${yn2:-n}
|
||||
case "$yn2" in
|
||||
[Yy])
|
||||
echo "Lets GO!"
|
||||
break
|
||||
;;
|
||||
[Nn])
|
||||
echo "Aborting.."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Input y/n (default=n)"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo "This Script contains installation, which needs your sudo permission:"
|
||||
sudo -v
|
||||
|
||||
# Print key-value nicely: key: value
|
||||
kv() {
|
||||
local k="$1"
|
||||
shift
|
||||
local v="${1:-}"
|
||||
printf "%-14s %s\n" "${k}:" "${v}"
|
||||
}
|
||||
|
||||
# Defaults
|
||||
ID=""
|
||||
ID_LIKE=""
|
||||
NAME=""
|
||||
PRETTY_NAME=""
|
||||
VERSION_ID=""
|
||||
VERSION_CODENAME=""
|
||||
|
||||
# 1) Best source: /etc/os-release
|
||||
if [[ -r /etc/os-release ]]; then
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/os-release
|
||||
ID="${ID:-}"
|
||||
ID_LIKE="${ID_LIKE:-}"
|
||||
NAME="${NAME:-}"
|
||||
PRETTY_NAME="${PRETTY_NAME:-}"
|
||||
VERSION_ID="${VERSION_ID:-}"
|
||||
VERSION_CODENAME="${VERSION_CODENAME:-}"
|
||||
|
||||
# 2) Fallback: lsb_release
|
||||
elif command -v lsb_release >/dev/null 2>&1; then
|
||||
NAME="$(lsb_release -si 2>/dev/null || true)"
|
||||
VERSION_ID="$(lsb_release -sr 2>/dev/null || true)"
|
||||
VERSION_CODENAME="$(lsb_release -sc 2>/dev/null || true)"
|
||||
PRETTY_NAME="${NAME} ${VERSION_ID}"
|
||||
|
||||
# 3) Fallback: hostnamectl (systemd)
|
||||
elif command -v hostnamectl >/dev/null 2>&1; then
|
||||
# Example line: "Operating System: Arch Linux"
|
||||
PRETTY_NAME="$(hostnamectl 2>/dev/null | awk -F': ' '/Operating System/ {print $2; exit}' || true)"
|
||||
|
||||
# 4) Last resort: /etc/issue
|
||||
elif [[ -r /etc/issue ]]; then
|
||||
PRETTY_NAME="$(head -n1 /etc/issue | sed 's/\\.*$//' | xargs || true)"
|
||||
fi
|
||||
|
||||
# Normalize: if PRETTY_NAME empty, try to build
|
||||
if [[ -z "${PRETTY_NAME}" ]]; then
|
||||
PRETTY_NAME="${NAME:-Unknown Linux}${VERSION_ID:+ ${VERSION_ID}}"
|
||||
fi
|
||||
|
||||
echo "== Distro info =="
|
||||
kv "PRETTY_NAME" "${PRETTY_NAME}"
|
||||
kv "ID" "${ID}"
|
||||
kv "ID_LIKE" "${ID_LIKE}"
|
||||
kv "NAME" "${NAME}"
|
||||
kv "VERSION_ID" "${VERSION_ID}"
|
||||
kv "CODENAME" "${VERSION_CODENAME}"
|
||||
|
||||
# Optional: classify into a "family"
|
||||
family="unknown"
|
||||
case "${ID:-}" in
|
||||
arch | manjaro | endeavouros) family="arch" ;;
|
||||
ubuntu | debian | linuxmint | pop | elementary | kali) family="debian" ;;
|
||||
fedora | rhel | centos | rocky | alma | ol) family="rhel" ;;
|
||||
opensuse* | sles) family="suse" ;;
|
||||
alpine) family="alpine" ;;
|
||||
esac
|
||||
kv "FAMILY" "${family}"
|
||||
|
||||
if [ "$family" = "arch" ]; then
|
||||
echo "This dot recommends you to install the following packages:"
|
||||
echo "cava fastfetch fuzzel kitty mako niri swaylock-fancy-git swaync waybar wlogout wofi sddm"
|
||||
echo "Do you wish to install these needed packages? [Y/n]"
|
||||
while true; do
|
||||
read -r yn || yn=""
|
||||
yn=${yn:-y} # 回车默认 y
|
||||
case "$yn" in
|
||||
[Yy])
|
||||
echo "OK, installing..."
|
||||
|
||||
aur_helper=""
|
||||
if command -v yay >/dev/null 2>&1; then
|
||||
aur_helper="yay"
|
||||
elif command -v paru >/dev/null 2>&1; then
|
||||
aur_helper="paru"
|
||||
fi
|
||||
|
||||
if [[ -n "$aur_helper" ]]; then
|
||||
echo "Found AUR helper: $aur_helper"
|
||||
else
|
||||
echo "No AUR helper found (yay/paru). Do you wish to install yay/paru?[y(yay)/p(paru)/n(don't install)]"
|
||||
while true; do
|
||||
read -r yn1 || yn1=""
|
||||
case "$yn1" in
|
||||
[Yy])
|
||||
echo "Installing Yay for you..."
|
||||
sudo pacman -S --needed git base-devel
|
||||
tmpdir="$(mktemp -d)"
|
||||
(
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
cd "$tmpdir"
|
||||
git clone https://aur.archlinux.org/yay-bin.git
|
||||
cd yay-bin
|
||||
makepkg -si --noconfirm
|
||||
)
|
||||
command -v yay >/dev/null 2>&1 && aur_helper="yay" || aur_helper=""
|
||||
break
|
||||
;;
|
||||
[Pp])
|
||||
echo "Installing Paru for you..."
|
||||
sudo pacman -S --needed git base-devel
|
||||
tmpdir="$(mktemp -d)"
|
||||
(
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
cd "$tmpdir"
|
||||
git clone https://aur.archlinux.org/paru.git
|
||||
cd paru
|
||||
makepkg -si --noconfirm
|
||||
)
|
||||
command -v paru >/dev/null 2>&1 && aur_helper="paru" || aur_helper=""
|
||||
break
|
||||
;;
|
||||
[Nn])
|
||||
echo "Skipped."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Please enter y/p/n."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -z "$aur_helper" ]]; then
|
||||
echo "Continue installing using pacman, replacing swaylock-fancy with swaylock"
|
||||
sudo pacman -S --needed cava fastfetch fuzzel kitty mako niri swaylock swaync waybar wlogout wofi sddm
|
||||
else
|
||||
echo "Installing packages..."
|
||||
"$aur_helper" -S --needed cava fastfetch fuzzel kitty mako niri swaylock-fancy-git swaync waybar wlogout wofi sddm
|
||||
fi
|
||||
|
||||
echo "Setting up SDDM..."
|
||||
sudo systemctl enable --now sddm.service
|
||||
sudo systemctl set-default graphical.target
|
||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/keyitdev/sddm-astronaut-theme/master/setup.sh)" || echo "SDDM theme setup failed, skipped."
|
||||
|
||||
mkdir -p ~/.config
|
||||
shopt -s nullglob dotglob
|
||||
cp -r "$script_dir/.configs/"* ~/.config/
|
||||
shopt -u nullglob dotglob
|
||||
|
||||
echo "Do you wish to use the grub theme from https://github.com/mateosss/matter?[Y/n]"
|
||||
while true; do
|
||||
read -r yn3 || yn3=""
|
||||
yn3=${yn3:-y}
|
||||
case "$yn3" in
|
||||
[Yy])
|
||||
echo "Setting up grub theme..."
|
||||
python3 "$script_dir/matter/matter.py"
|
||||
echo "./matter/matter.py -i(write your params here):"
|
||||
read -r -a tokens || tokens=()
|
||||
python3 "$script_dir/matter/matter.py" -i "${tokens[@]}"
|
||||
break
|
||||
;;
|
||||
[Nn])
|
||||
echo "Skipped."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Please Input y/n (default=y)"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
break
|
||||
;;
|
||||
[Nn])
|
||||
echo "Skipped."
|
||||
break
|
||||
;;
|
||||
*) echo "Please enter y or n (default: y): " ;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
echo "Your Distro is not supported yet, Please install these needed packages manually:"
|
||||
echo "cava fastfetch fuzzel kitty mako niri swaylock swaync waybar wlogout wofi sddm"
|
||||
echo "You can use the replace.sh to replace all the configs after install. :)"
|
||||
fi
|
||||
23
matter/LICENSE
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
3
matter/Matter/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Based on Vimix by Vince Liuice
|
||||
|
||||
https://www.gnu.org/software/grub/manual/grub/html_node/Theme-file-format.html
|
||||
BIN
matter/Matter/font.pf2
Normal file
1
matter/Matter/icons/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
The converted png icons you choose for the --set-icons option will be saved to this folder.
|
||||
BIN
matter/Matter/icons/arch.png
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
matter/Matter/icons/cog.png
Normal file
|
After Width: | Height: | Size: 980 B |
BIN
matter/Matter/icons/microsoft-windows.png
Normal file
|
After Width: | Height: | Size: 700 B |
BIN
matter/Matter/select_c.png
Normal file
|
After Width: | Height: | Size: 932 B |
BIN
matter/Matter/select_e.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
matter/Matter/select_n.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
matter/Matter/select_ne.png
Normal file
|
After Width: | Height: | Size: 956 B |
BIN
matter/Matter/select_nw.png
Normal file
|
After Width: | Height: | Size: 955 B |
BIN
matter/Matter/select_s.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
matter/Matter/select_se.png
Normal file
|
After Width: | Height: | Size: 955 B |
BIN
matter/Matter/select_sw.png
Normal file
|
After Width: | Height: | Size: 960 B |
BIN
matter/Matter/select_w.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
matter/Matter/terminal_box_c.png
Normal file
|
After Width: | Height: | Size: 976 B |
BIN
matter/Matter/terminal_box_e.png
Normal file
|
After Width: | Height: | Size: 952 B |
BIN
matter/Matter/terminal_box_n.png
Normal file
|
After Width: | Height: | Size: 963 B |
BIN
matter/Matter/terminal_box_ne.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
matter/Matter/terminal_box_nw.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
matter/Matter/terminal_box_s.png
Normal file
|
After Width: | Height: | Size: 963 B |
BIN
matter/Matter/terminal_box_se.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
matter/Matter/terminal_box_sw.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
matter/Matter/terminal_box_w.png
Normal file
|
After Width: | Height: | Size: 952 B |
48
matter/Matter/theme.txt
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# If this file is called theme.txt then the theme template has been
|
||||
# already parsed and the comments below could not make too much sense.
|
||||
|
||||
# theme.txt.template represents a python string that gets format()-ed
|
||||
# Note: for escaping literal curly braces, double them like so: { or }
|
||||
|
||||
# Matter Theme File
|
||||
# Designed for any resolution
|
||||
|
||||
# Global Property
|
||||
title-text: ""
|
||||
# desktop-image: "background.png"
|
||||
desktop-color: "#263238"
|
||||
terminal-font: "Unifont Regular 16" # A smaller font for the console
|
||||
terminal-box: "terminal_box_*.png"
|
||||
terminal-left: "0"
|
||||
terminal-top: "0"
|
||||
terminal-width: "100%"
|
||||
terminal-height: "100%"
|
||||
terminal-border: "0"
|
||||
|
||||
# Show the boot menu
|
||||
+ boot_menu {
|
||||
left = 36%
|
||||
top = 29%
|
||||
width = 28%
|
||||
height = 60%
|
||||
item_font = "Josefin Sans Regular 32"
|
||||
item_color = "#ffffff"
|
||||
selected_item_color = "#e91e63"
|
||||
icon_width = 72
|
||||
icon_height = 72
|
||||
item_height = 72
|
||||
item_spacing = 36
|
||||
selected_item_pixmap_style = "select_*.png"
|
||||
}
|
||||
|
||||
# Show a countdown message using the label component
|
||||
+ label {
|
||||
top = 82%
|
||||
left = 35%
|
||||
width = 30%
|
||||
align = "center"
|
||||
id = "__timeout__"
|
||||
text = "Booting in %d seconds"
|
||||
color = "#ffffff"
|
||||
font = "Josefin Sans Regular 32"
|
||||
}
|
||||
397
matter/README.md
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
# Matter
|
||||
|
||||
Minimalist grub theme originally inspired by material design 2.
|
||||
|
||||

|
||||
|
||||
Feel free to open issues for any problem or request you have and/or submit pull
|
||||
requests.
|
||||
|
||||
# Index
|
||||
|
||||
- [Matter](#matter)
|
||||
- **[Download](#download)**
|
||||
- [Usage](#usage)
|
||||
- [Help](#help)
|
||||
- **[Quick Start](#quick-start)**
|
||||
- [Uninstall](#uninstall)
|
||||
- [Fonts](#fonts)
|
||||
- [Colors](#colors)
|
||||
- [Images](#images-unfinished)
|
||||
- [Testing Without Rebooting](#testing-without-rebooting)
|
||||
- [What does Matter do to my system
|
||||
files?](#what-does-matter-do-to-my-system-files)
|
||||
- [Gallery](#gallery): [1](#example-1), [2](#example-2), [3](#example-3),
|
||||
[4](#example-4), [5](#example-5), [6](#example-6), [7](#example-7),
|
||||
[8](#example-8), [9](#example-9), [10](#example-10), [11](#example-11)
|
||||
- [Contributing](#contributing)
|
||||
- [Thanks](#thanks)
|
||||
|
||||
# Download
|
||||
|
||||
[Click here to download Matter](https://github.com/mateosss/matter/releases/latest/download/matter.zip)
|
||||
|
||||
It is **strongly advised** to put the downloaded files in some folder that will
|
||||
not get deleted, as the main script `matter.py` is needed for future grub
|
||||
updates made by your system. Also if you want to uninstall matter you could do
|
||||
it from there as well.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Matter will inform you of any missing dependencies, but here is a list anyways:
|
||||
|
||||
- `inkscape` (**Main dependency**): This brings the `convert` command from
|
||||
`imagemagick` with best svg to png conversion.
|
||||
- `grub-mkconfig` and `grub-mkfont`: General grub utilities needed. If you
|
||||
don't have these, please create an issue with more information about your
|
||||
system as I've only worked with ones that have these commands.
|
||||
- `PIL` (Optional): For image conversions with the `--downloadbackground/-dlbg`
|
||||
option. Can be installed with either of: `pip install Pillow`, `sudo apt
|
||||
install python3-pil` (Ubuntu), `pacman -S python-pillow` (Arch).
|
||||
- [`grub2-theme-preview`](https://github.com/hartwork/grub2-theme-preview)
|
||||
(Optional): For testing results (`--test/-t` argument) without rebooting.
|
||||
|
||||
# Usage
|
||||
|
||||
## Help
|
||||
|
||||
You always can see the command reference with `./matter.py -h`, next up are some
|
||||
sections that may be useful, or may not be very well documented in the command's
|
||||
help.
|
||||
|
||||
## Quick Start
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Note for Fedora users (click to show)</summary>
|
||||
|
||||
*Matter does not yet support [The Boot Loader
|
||||
Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION/) so before executing
|
||||
`matter.py` you should set `GRUB_ENABLE_BLSCFG="false"` in `/etc/default/grub` and then
|
||||
update your grub file with `sudo grub2-mkconfig -o /boot/grub2/grub.cfg`*
|
||||
|
||||
*See [this issue](https://github.com/mateosss/matter/issues/41) for updates
|
||||
or if you want to help out with fedora support*
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Note for users with screen resolution other than 1920x1080 (click to show)</summary>
|
||||
|
||||
*Matter layout might break in other resolutions with the default installation,
|
||||
you might need to tweak the [`grub.template`](grub.template) `GRUB_GFXMODE`
|
||||
property and [`theme.txt.template`](theme.txt.template) percentages*
|
||||
|
||||
*See [this issue](https://github.com/mateosss/matter/issues/4) for more
|
||||
information.*
|
||||
|
||||
</details>
|
||||
|
||||
Following is a Matter installation with default values. Don't worry, it is very
|
||||
easy to rollback or overwrite this installation later if you want to.
|
||||
|
||||
The script that does all the work is `matter.py`, so let's start by running it
|
||||
|
||||
```sh
|
||||
./matter.py
|
||||
```
|
||||
|
||||
It outputs almost everything you need to know for later, but for now let's focus
|
||||
on the list it shows, those are your grub entries. It should look similar to
|
||||
this one:
|
||||
|
||||
```sh
|
||||
1. Ubuntu
|
||||
2. Windows
|
||||
3. More Options
|
||||
4. Ubuntu, with Linux 5.3.0-61-generic
|
||||
5. Ubuntu, with Linux 5.3.0-61-generic (recovery mode)
|
||||
6. Ubuntu, with Linux 5.3.0-59-generic
|
||||
7. Ubuntu, with Linux 5.3.0-59-generic (recovery mode)
|
||||
8. System Setup
|
||||
```
|
||||
|
||||
Now you should pick some icons from <https://materialdesignicons.com> for each entry
|
||||
listed (you only need the icon's name, use the search panel and hover over any
|
||||
icon you like to see its name). For this example I will pick `ubuntu` for entry
|
||||
1, `microsoft-windows` for 2, `folder` for 3 (as it is a submenu in my
|
||||
particular case), and `cog` for 8. I don't care about all the remaining entries
|
||||
so I will just use "`_`" (underscore) for those.
|
||||
|
||||
```sh
|
||||
# Installs matter with icons matching the corresponding entries
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ cog
|
||||
```
|
||||
|
||||
**And thats it!** If you reboot now, you should get something like this:
|
||||
|
||||

|
||||
|
||||
*Tip: If you need to tidy up your grub entries hierarchy and names I recommend
|
||||
using [grub-customizer](https://launchpad.net/grub-customizer)
|
||||
([tutorial](https://vitux.com/how-to-install-grub-customizer-on-ubuntu/))*.
|
||||
|
||||
## Uninstall
|
||||
|
||||
You can completely remove Matter from your system with `./matter.py -u`
|
||||
|
||||
## Fonts
|
||||
|
||||
Matter uses `.ttf` fonts and only one, the default, comes prepackaged. You can
|
||||
specify your own fonts by giving a `.ttf` file, the font name, and an optional
|
||||
font size like so:
|
||||
|
||||
```sh
|
||||
./matter.py -ff ~/fonts/Cinzel/Cinzel-Regular.ttf -fn Cinzel Regular -fs 40
|
||||
```
|
||||
|
||||
- `--fontfile/-ff`: The `.ttf` path
|
||||
- `--fontname/-fn`: The name of the font, in this case `Cinzel Regular` but
|
||||
could be `Open Sans Bold` (*Tip: If you don't know the font name, you can
|
||||
specify any name, go to the grub, press C to open console, and type `lsfonts`
|
||||
to list the font names*)
|
||||
- `--fontsize/-fs`: By default it is 32, recommended values are multiples of 4.
|
||||
- `--font/-f`: This argument is not used in this example as it is used to select
|
||||
prepackaged fonts. Note that after giving a ttf file to `-ff`, matter will
|
||||
save it as a prepackaged font, so it could be referenced later on with this
|
||||
flag. See prepackaged (available) fonts at the end of `--help/-h` output
|
||||
|
||||
*Tip: [Google Fonts](https://fonts.google.com/) is a good place to get fonts*
|
||||
|
||||
## Colors
|
||||
|
||||
You can specify the color of 4 elements: `--foreground/-fg`, `--background/-bg`,
|
||||
`--iconcolor/-ic` and `--highlight/-hl` (selected text color), there are some
|
||||
Material Design colors prepackaged that you can see at the end of the
|
||||
`--help/-h` output, you can also specify custom colors. Here is an example of
|
||||
the syntax:
|
||||
|
||||
```sh
|
||||
./matter.py -hl FFC107 -fg white -bg 2196f3 -ic pink
|
||||
```
|
||||
|
||||
## Images (unfinished)
|
||||
|
||||
You can specify a background image with `--image/-im`, the supported image
|
||||
formats/extensions are PNG, JPG, JPEG, and TGA. This feature is considered
|
||||
*unfinished* because it does not yet work as well as it could *(see
|
||||
[#58](https://github.com/mateosss/matter/issues/58))*
|
||||
|
||||
Here is an example of the syntax:
|
||||
|
||||
```sh
|
||||
./matter.py -im ~/Pictures/some-cool-image-that-has-good-contrast-with-my-text-color.png
|
||||
```
|
||||
|
||||
You can also specify an URL with --downloadbackground/-dlbg to automatically download an image from the internet. The image will be converted to png so it doesn't need to be a grub-compatible 8-bit jpg. It should be in the `jpg` or `png` format though. This feature is also considered *unfinished*.
|
||||
|
||||
```sh
|
||||
./matter.py -dlbg "https://source.unsplash.com/1920x1080/?nature"
|
||||
```
|
||||
|
||||
## Testing Without Rebooting
|
||||
|
||||
If you install the `pip` package
|
||||
[`grub2-theme-preview`](https://github.com/hartwork/grub2-theme-preview) you can
|
||||
test combinations of fonts and colors with the `--buildonly/-b` and `--test/-t`
|
||||
flags like so:
|
||||
|
||||
```sh
|
||||
./matter.py -t -b -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl FFC107 -fg white -bg 2196F3 \
|
||||
-ff ~/fonts/MuseoModerno/static/MuseoModerno-Regular.ttf \
|
||||
-fn MuseoModerno Regular -fs 40
|
||||
```
|
||||
|
||||
*Note: it will use your system's grub.cfg, so set your icons beforehand*.
|
||||
|
||||
# What does Matter do to my system files?
|
||||
|
||||
Besides the need for the extracted files to be in a persistent location, Matter
|
||||
needs to edit three files:
|
||||
|
||||
1. `/etc/default/grub`: For setting theme and resolution.
|
||||
2. `/boot/grub/grub.cfg`: For setting icons.
|
||||
3. `/usr/sbin/grub-mkconfig`: For making icons persistent across grub updates.
|
||||
4. `/etc/grub.d/99_matter`: For making icons persistent across grub upgrades.
|
||||
|
||||
Also it places the theme files in `/boot/grub/themes/Matter/`, this one is
|
||||
standard to grub themes in general.
|
||||
|
||||
Both **(1)** and **(3)** are clearly distinguished with special `BEGIN`/`END`
|
||||
comments at the end of each file. **(2)** Adds a `--class` flag to each entry,
|
||||
but it can be restored as new with `update-grub`. And **(4)** is a custom file.
|
||||
|
||||
*All of these modifications are **completely** cleaned up by uninstalling*
|
||||
|
||||
# Gallery
|
||||
|
||||
Here are some examples with their respective commands that you can copy or get
|
||||
inspired from.
|
||||
|
||||
## Example 1
|
||||
|
||||

|
||||
|
||||
*Font: [Josefin Sans Regular
|
||||
400](https://fonts.google.com/specimen/Josefin+Sans)*
|
||||
|
||||
```sh
|
||||
# Light version, invert -fg and -bg for dark one
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl ef233c -fg 2b2d42 -bg edf2f4 \
|
||||
-ff ~/fonts/Josefin_Sans/static/JosefinSans-Regular.ttf \
|
||||
-fn Josefin Sans Regular -fs 32
|
||||
```
|
||||
|
||||
## Example 2
|
||||
|
||||

|
||||
|
||||
*Font: [Comfortaa Medium 500](https://fonts.google.com/specimen/Comfortaa)*
|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl white -fg f0f0f0 -bg ff0d7b \
|
||||
-ff ~/fonts/Comfortaa/static/Comfortaa-Medium.ttf \
|
||||
-fn Comfortaa Regular -fs 32
|
||||
```
|
||||
|
||||
## Example 3
|
||||
|
||||

|
||||
|
||||
*Font: [Lobster Regular 400](https://fonts.google.com/specimen/Lobster)*
|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl 118ab2 -fg ffd166 -bg 073b4c \
|
||||
-ff ~/fonts/Lobster/Lobster-Regular.ttf \
|
||||
-fn Lobster Regular -fs 32
|
||||
```
|
||||
|
||||
## Example 4
|
||||
|
||||

|
||||
|
||||
*Fonts: [Bebas Neue Regular 400](https://fonts.google.com/specimen/Bebas+Neue)
|
||||
and [Russo One Regular 400](https://fonts.google.com/specimen/Russo+One)*
|
||||
|
||||
```sh
|
||||
# Using Bebas Neue font (more compact), the other uses Russo One
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl 2c251b -fg 2c251b -bg ffe70b \
|
||||
-ff ~/fonts/Bebas_Neue/BebasNeue-Regular.ttf \
|
||||
-fn Bebas Neue Regular -fs 36
|
||||
# -ff ~/fonts/Russo_One/RussoOne-Regular.ttf \
|
||||
# -fn Russo One Regular -fs 36
|
||||
|
||||
```
|
||||
|
||||
## Example 5
|
||||
|
||||

|
||||
|
||||
*Font: [Poiret One Regular 400](https://fonts.google.com/specimen/Poiret+One)*
|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl black -fg 101010 -bg fce1e0 \
|
||||
-ff ~/fonts/Poiret_One/PoiretOne-Regular.ttf \
|
||||
-fn Poiret One Regular -fs 48
|
||||
```
|
||||
|
||||
## Example 6
|
||||
|
||||

|
||||
|
||||
*Font: [Josefin Sans Medium
|
||||
500](https://fonts.google.com/specimen/Josefin+Sans)*
|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl ffe78a -fg fdf7f9 -bg 582335 \
|
||||
-ff ~/fonts/Josefin_Sans/static/JosefinSans-Medium.ttf \
|
||||
-fn Josefin Sans Regular -fs 32
|
||||
```
|
||||
|
||||
## Example 7
|
||||
|
||||

|
||||
|
||||
*Font: [Josefin Slab Bold 700](https://fonts.google.com/specimen/Josefin+Slab)*
|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl A4E11E -fg white -bg 5b1ee1 \
|
||||
-ff ~/fonts/Josefin_Slab/JosefinSlab-Bold.ttf \
|
||||
-fn Josefin Slab Bold -fs 36
|
||||
```
|
||||
|
||||
## Example 8
|
||||
|
||||

|
||||
|
||||
*Font: [MuseoModerno Regular
|
||||
400](https://fonts.google.com/specimen/MuseoModerno)*
|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl FFC107 -fg white -bg 2196F3 \
|
||||
-ff ~/fonts/MuseoModerno/static/MuseoModerno-Regular.ttf \
|
||||
-fn MuseoModerno Regular -fs 32
|
||||
```
|
||||
|
||||
## Example 9
|
||||
|
||||

|
||||
|
||||
*Font: [Amatic SC Regular 400](https://fonts.google.com/specimen/Amatic+SC)*
|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-bg FFF8E1 -fg 263238 -hl E91E63 \
|
||||
-ff ~/fonts/Amatic_SC/AmaticSC-Regular.ttf \
|
||||
-fn Amatic SC Regular -fs 64
|
||||
```
|
||||
|
||||
## Example 10
|
||||
|
||||

|
||||
|
||||
*Font: [Cinzel Regular 400](https://fonts.google.com/specimen/Cinzel)*
|
||||
|
||||
```sh
|
||||
# This is the light version, the dark one uses -bg 1a1d21 -fg c9a45b instead
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-hl c28f2c -bg white -fg d0a85c \
|
||||
-ff ~/fonts/Cinzel/Cinzel-Regular.ttf \
|
||||
-fn Cinzel Regular -fs 40
|
||||
# -hl c28f2c -bg 1a1d21 -fg c9a45b \
|
||||
```
|
||||
|
||||
## Example 11
|
||||
|
||||

|
||||
|
||||
```sh
|
||||
./matter.py -i ubuntu microsoft-windows folder _ _ _ _ _ _ cog \
|
||||
-im ~/images/material-background.png
|
||||
```
|
||||
|
||||
# Contributing
|
||||
|
||||
Feel free to submit any pull request that improves in any way the project.
|
||||
|
||||
Read the wiki <https://github.com/mateosss/matter/wiki>, that's where any useful
|
||||
information for developers will reside.
|
||||
|
||||
If you think you got a nice result out of Matter and would like to share it,
|
||||
please create an issue with it! I would love to see your results.
|
||||
|
||||
# Thanks
|
||||
|
||||
- Originally inspired by <https://github.com/vinceliuice/grub2-themes>
|
||||
- Icons from <https://materialdesignicons.com/>
|
||||
- Fonts mainly from <https://fonts.google.com>
|
||||
BIN
matter/__pycache__/svg2png.cpython-313.pyc
Normal file
BIN
matter/__pycache__/utils.cpython-313.pyc
Normal file
1
matter/bg/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
The background images you choose for the --downloadbackground option will be saved to this folder.
|
||||
1
matter/config.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"icons": {"Arch Linux, with Linux linux": "arch", "UEFI Firmware Settings": "cog", "Windows 11 (EFI)": "microsoft-windows"}}
|
||||
BIN
matter/fonts/Josefin_Sans_Regular.ttf
Normal file
BIN
matter/fonts/Poiret_One_Regular.ttf
Normal file
1
matter/fonts/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Preloaded Matter fonts, for adding a new one update FONTS dict in matter.py
|
||||
6
matter/grub.template
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
GRUB_THEME={installation_dir}/theme.txt
|
||||
GRUB_GFXMODE=1920x1080,auto
|
||||
|
||||
# Fedora specific fixes
|
||||
GRUB_ENABLE_BLSCFG=false
|
||||
GRUB_TERMINAL_OUTPUT=""
|
||||
79
matter/hookcheck.py.template
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
This template file goes into /etc/grub.d/99_matter
|
||||
It checks that the theme is still hooked to grub-mkconfig.
|
||||
Hooks it back again if not.
|
||||
|
||||
This is a template file, be careful of your use of curly braces. Use {{ and }} instead.
|
||||
|
||||
# About /etc/grub.d
|
||||
Files in /etc/grub.d run in the order of their prefix number.
|
||||
We use the 99 number because the hook should be run after the entire grub.cfg file is generated.
|
||||
Everything echoed to stdout is written to /boot/grub/grub.cfg after the previous files.
|
||||
Everything echoed to stderr is shown to the user wherever there is a grub update.
|
||||
This script does not write to stdout.
|
||||
More @ https://www.gnu.org/software/grub/manual/grub/grub.html#Simple-configuration
|
||||
|
||||
# Why this script exists?
|
||||
Files in /etc/grub.d are not erased after your distro upgrades the grub package.
|
||||
As this theme relies on being hooked to the grub-mkconfig file (i.e. executed by it)
|
||||
and grub package upgrades restore the mkconfig file, this file detects
|
||||
when the grub-mkconfig file has been restored and then hook the theme back onto it.
|
||||
"""
|
||||
|
||||
import re
|
||||
from subprocess import run
|
||||
from sys import stderr
|
||||
|
||||
GRUB_MKCONFIG_PATH = "{GRUB_MKCONFIG_PATH}"
|
||||
THEME_NAME = "{THEME_NAME}"
|
||||
THEME_OVERRIDES_TITLE = "{THEME_OVERRIDES_TITLE}"
|
||||
BEGIN_THEME_OVERRIDES = "{BEGIN_THEME_OVERRIDES}"
|
||||
END_THEME_OVERRIDES = "{END_THEME_OVERRIDES}"
|
||||
SETICONS_CALL = "{SETICONS_CALL}"
|
||||
|
||||
cyan = "\033[36m"
|
||||
pink = "\033[38;5;206m"
|
||||
endcolor ="\033[0m"
|
||||
def info(msg):
|
||||
# info with cyan [I]
|
||||
print(f"{{cyan}}[I]{{endcolor}} {{msg}}", file=stderr)
|
||||
|
||||
|
||||
def sh(command):
|
||||
"Executes command in shell and returns its exit status"
|
||||
return run(command, shell=True).returncode
|
||||
|
||||
info(f"{{pink}}[Matter]{{endcolor}} Setting entry icons")
|
||||
|
||||
with open(GRUB_MKCONFIG_PATH, "r", newline="") as f:
|
||||
grub_mkconfig = f.read()
|
||||
|
||||
theme_overrides = f"\n*{{BEGIN_THEME_OVERRIDES}}.*{{END_THEME_OVERRIDES}}\n*"
|
||||
theme_hooked = re.search(theme_overrides, grub_mkconfig, flags=re.DOTALL) is not None
|
||||
|
||||
if theme_hooked:
|
||||
info(f"Found {{GRUB_MKCONFIG_PATH}} hook")
|
||||
exit(0)
|
||||
|
||||
info(f"Hook back onto {{GRUB_MKCONFIG_PATH}}")
|
||||
|
||||
grub_mkconfig += (
|
||||
f"\n\n{{BEGIN_THEME_OVERRIDES}}\n{{SETICONS_CALL}}\n{{END_THEME_OVERRIDES}}\n\n"
|
||||
)
|
||||
|
||||
with open(GRUB_MKCONFIG_PATH, "w") as f:
|
||||
f.write(grub_mkconfig)
|
||||
|
||||
info(
|
||||
f"{{GRUB_MKCONFIG_PATH}} successfully patched, icons will now persist between grub updates."
|
||||
)
|
||||
|
||||
|
||||
# Lastly call the hook as mkconfig is currently running and should be loaded in memory.
|
||||
# NOTE: Some bash interpreters seem to not load the entire script in memory
|
||||
# so appending commands to the end of the script at runtime will indeed make
|
||||
# mkconfig run them. That's what's happening is you see the
|
||||
# 'grub.cfg icons patched' message twice
|
||||
sh(SETICONS_CALL)
|
||||
1
matter/icons/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
The icons svg you choose for the --set-icons option will be saved to this folder.
|
||||
1
matter/icons/arch.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" id="mdi-arch" viewBox="0 0 24 24"><path d="M12,2C11.11,4.18 10.57,5.61 9.58,7.73C10.19,8.37 10.93,9.12 12.14,9.97C10.84,9.43 9.95,8.9 9.29,8.34C8,11 6.03,14.75 2,22C5.17,20.17 7.63,19.04 9.92,18.61C9.82,18.19 9.76,17.73 9.77,17.25V17.15C9.82,15.12 10.88,13.56 12.13,13.67C13.38,13.77 14.35,15.5 14.3,17.54C14.29,17.92 14.25,18.29 14.18,18.63C16.44,19.07 18.87,20.19 22,22C21.38,20.86 20.83,19.84 20.31,18.87C19.5,18.23 18.61,17.39 16.85,16.5C18.06,16.8 18.93,17.16 19.61,17.57C14.26,7.62 13.83,6.3 12,2Z" /></svg>
|
||||
|
After Width: | Height: | Size: 553 B |
1
matter/icons/cog.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" id="mdi-cog" viewBox="0 0 24 24"><path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" /></svg>
|
||||
|
After Width: | Height: | Size: 999 B |
1
matter/icons/microsoft-windows.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" id="mdi-microsoft-windows" viewBox="0 0 24 24"><path d="M3,12V6.75L9,5.43V11.91L3,12M20,3V11.75L10,11.9V5.21L20,3M3,13L9,13.09V19.9L3,18.75V13M20,13.25V22L10,20.09V13.1L20,13.25Z" /></svg>
|
||||
|
After Width: | Height: | Size: 228 B |
882
matter/matter.py
Executable file
|
|
@ -0,0 +1,882 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# Standard library modules
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import argparse
|
||||
import urllib.request as request
|
||||
from urllib.error import HTTPError, URLError
|
||||
from argparse import ArgumentParser, RawTextHelpFormatter
|
||||
from os.path import dirname, basename, isdir, exists
|
||||
from shutil import which, rmtree, copytree, copyfile
|
||||
try:
|
||||
from PIL import Image
|
||||
except:
|
||||
has_PIL = False
|
||||
else:
|
||||
has_PIL = True
|
||||
|
||||
# Local Matter modules
|
||||
from utils import *
|
||||
from svg2png import inkscape_convert_svg2png, magick_convert_svg2png
|
||||
|
||||
# Configuration constants
|
||||
|
||||
MIN_PYTHON_VERSION = (3, 6) # Mainly for f-strings
|
||||
|
||||
THEME_NAME = "Matter"
|
||||
THEME_DESCRIPTION = (
|
||||
"Matter is a minimalist grub theme originally inspired by material design 2.\n"
|
||||
"Run this script without arguments for next steps on installing Matter."
|
||||
)
|
||||
|
||||
|
||||
|
||||
if exists("/boot/grub"):
|
||||
BOOT_GRUB_PATH = "/boot/grub"
|
||||
elif exists("/boot/grub2"):
|
||||
BOOT_GRUB_PATH = "/boot/grub2"
|
||||
else:
|
||||
error("Could not find your grub's boot path (tried /boot/grub and /boot/grub2)")
|
||||
|
||||
INSTALLER_ABSPATH = os.path.abspath(__file__)
|
||||
INSTALLER_NAME = basename(INSTALLER_ABSPATH)
|
||||
INSTALLER_DIR = dirname(INSTALLER_ABSPATH)
|
||||
INSTALLATION_SOURCE_DIR = f"{INSTALLER_DIR}/{THEME_NAME}"
|
||||
INSTALLATION_TARGET_DIR = f"{BOOT_GRUB_PATH}/themes/{THEME_NAME}"
|
||||
|
||||
THEME_DEFAULT_HIGHLIGHT = "pink"
|
||||
THEME_DEFAULT_FOREGROUND = "white"
|
||||
THEME_DEFAULT_BACKGROUND = "bluegrey-900"
|
||||
THEME_DEFAULT_FONT_NAME = "Josefin Sans Regular"
|
||||
THEME_DEFAULT_FONT = THEME_DEFAULT_FONT_NAME.replace(" ", "_")
|
||||
THEME_DEFAULT_FONT_SIZE = 32
|
||||
|
||||
GRUB_DEFAULTS_PATH = "/etc/default/grub"
|
||||
GRUB_SCRIPTS_PATH = "/etc/grub.d"
|
||||
GRUB_CFG_PATH = f"{BOOT_GRUB_PATH}/grub.cfg"
|
||||
GRUB_MKCONFIG_PATH = which("grub-mkconfig") or which("grub2-mkconfig")
|
||||
if GRUB_MKCONFIG_PATH is None:
|
||||
error("Could not find grub-mkconfig command file (grub2-mkconfig neither)")
|
||||
|
||||
|
||||
THEME_TEMPLATE_PATH = f"{INSTALLER_DIR}/theme.txt.template"
|
||||
GRUB_DEFAULTS_TEMPLATE_PATH = f"{INSTALLER_DIR}/grub.template"
|
||||
HOOKCHECK_TEMPLATE_PATH = f"{INSTALLER_DIR}/hookcheck.py.template"
|
||||
|
||||
THEME_OVERRIDES_TITLE = f"{THEME_NAME} Theme Overrides"
|
||||
BEGIN_THEME_OVERRIDES = f"### BEGIN {THEME_OVERRIDES_TITLE}"
|
||||
END_THEME_OVERRIDES = f"### END {THEME_OVERRIDES_TITLE}"
|
||||
|
||||
ICON_SVG_PATHF = f"{INSTALLER_DIR}/icons/{{}}.svg"
|
||||
ICON_PNG_PATHF = f"{INSTALLATION_SOURCE_DIR}/icons/{{}}.png"
|
||||
|
||||
BACKGROUND_TMP_PATHF = f"{INSTALLER_DIR}/bg/{{}}.tmp"
|
||||
BACKGROUND_PNG_PATHF = f"{INSTALLER_DIR}/bg/{{}}.png"
|
||||
|
||||
CONFIG_FILE_PATH = f"{INSTALLER_DIR}/config.json"
|
||||
|
||||
PALETTE = {
|
||||
"red": "f44336",
|
||||
"pink": "e91e63",
|
||||
"purple": "9c27b0",
|
||||
"deeppurple": "673ab7",
|
||||
"indigo": "3f51b5",
|
||||
"blue": "2196f3",
|
||||
"lightblue": "03a9f4",
|
||||
"cyan": "00bcd4",
|
||||
"teal": "009688",
|
||||
"green": "4caf50",
|
||||
"lightgreen": "8bc34a",
|
||||
"lime": "cddc39",
|
||||
"yellow": "ffeb3b",
|
||||
"amber": "ffc107",
|
||||
"orange": "ff9800",
|
||||
"deeporange": "ff5722",
|
||||
"brown": "795548",
|
||||
"grey": "9e9e9e",
|
||||
"bluegrey": "607d8b",
|
||||
"white": "ffffff",
|
||||
"black": "000000",
|
||||
# Custom default colors
|
||||
"white-350": "9E9E9E",
|
||||
"bluegrey-900": "263238",
|
||||
}
|
||||
AVAILABLE_COLORS = list(PALETTE.keys())
|
||||
|
||||
MDI_CDN = "https://raw.githubusercontent.com/Templarian/MaterialDesign-SVG/master/svg/"
|
||||
|
||||
# Global user arguments set in main()
|
||||
user_args: argparse.Namespace
|
||||
|
||||
# Utils
|
||||
|
||||
def check_python_version():
|
||||
installed = (sys.version_info.major, sys.version_info.minor)
|
||||
required = MIN_PYTHON_VERSION
|
||||
if installed < required:
|
||||
error(f"Python {required[0]}.{required[1]} or later required")
|
||||
|
||||
|
||||
def check_root_or_prompt():
|
||||
if os.geteuid() != 0:
|
||||
info("Request root access")
|
||||
exit_code = sh("sudo -v")
|
||||
if exit_code != 0:
|
||||
error("Could not verify root access, you could try with sudo")
|
||||
# Relaunch the program with sudo
|
||||
args = " ".join(sys.argv[1:])
|
||||
child_exit_code = sh(f"sudo {INSTALLER_DIR}/{INSTALLER_NAME} {args}")
|
||||
exit(child_exit_code) # Propagate exit code
|
||||
|
||||
|
||||
def delete_dir(directory):
|
||||
if isdir(directory):
|
||||
rmtree(directory)
|
||||
|
||||
|
||||
def read_cleaned_grub_defaults():
|
||||
# Read previous defaults
|
||||
with open(GRUB_DEFAULTS_PATH, "r", newline="") as f:
|
||||
grub_defaults = f.read()
|
||||
|
||||
# Remove previous theme defaults
|
||||
cleaned_grub_defaults = re.sub(
|
||||
f"\n*{BEGIN_THEME_OVERRIDES}.*{END_THEME_OVERRIDES}\n*",
|
||||
"",
|
||||
grub_defaults,
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
return cleaned_grub_defaults
|
||||
|
||||
|
||||
def read_cleaned_grub_mkconfig():
|
||||
# Read previous defaults
|
||||
with open(GRUB_MKCONFIG_PATH, "r", newline="") as f:
|
||||
grub_mkconfig = f.read()
|
||||
|
||||
# Remove previous theme defaults
|
||||
cleaned_grub_mkconfig = re.sub(
|
||||
f"\n*{BEGIN_THEME_OVERRIDES}.*{END_THEME_OVERRIDES}\n*",
|
||||
"",
|
||||
grub_mkconfig,
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
return cleaned_grub_mkconfig
|
||||
|
||||
|
||||
def download_icon(icon_name):
|
||||
info(f"Download {icon_name}.svg")
|
||||
url = f"{MDI_CDN}{icon_name}.svg"
|
||||
try:
|
||||
with request.urlopen(url) as f:
|
||||
response = f.read()
|
||||
except HTTPError as err: # A subclass of URLError
|
||||
error(f"Couldn't get icon {icon_name} ({err.reason})", f"At URL {err.geturl()}")
|
||||
except URLError as err:
|
||||
error(f"Couldn't get icon {icon_name} ({err.reason})")
|
||||
svg_path = ICON_SVG_PATHF.format(icon_name)
|
||||
with open(svg_path, "wb") as f:
|
||||
f.write(response)
|
||||
return svg_path
|
||||
|
||||
|
||||
def download_background(background_path):
|
||||
if not has_PIL:
|
||||
error("PIL not detected, cannot download background")
|
||||
info(f"Downloading background image")
|
||||
|
||||
url = f"{background_path}"
|
||||
try:
|
||||
with request.urlopen(url) as f:
|
||||
response = f.read()
|
||||
except HTTPError as err: # A subclass of URLError
|
||||
error(f"Couldn't get background image ({err.reason})", f"At URL {err.geturl()}")
|
||||
except URLError as err:
|
||||
error(f"Couldn't get background image ({err.reason})")
|
||||
bg_path = BACKGROUND_TMP_PATHF.format('background_image')
|
||||
conv_path = BACKGROUND_PNG_PATHF.format('background_image')
|
||||
with open(bg_path, "wb") as f:
|
||||
f.write(response)
|
||||
im = Image.open(bg_path)
|
||||
im.save(conv_path)
|
||||
return conv_path
|
||||
|
||||
|
||||
|
||||
def get_converted_icons():
|
||||
return [
|
||||
filename[:-4] # Remove .png
|
||||
for filename in os.listdir(f"{INSTALLATION_SOURCE_DIR}/icons/")
|
||||
if filename.endswith(".png")
|
||||
]
|
||||
|
||||
|
||||
def is_icon_downloaded(icon_name):
|
||||
svg_path = ICON_SVG_PATHF.format(icon_name)
|
||||
return exists(svg_path)
|
||||
|
||||
|
||||
def convert_icon_svg2png(icon_name, whisper=False):
|
||||
if not has_command("inkscape"):
|
||||
if not has_command("convert"):
|
||||
error(
|
||||
"Stop. Both `inkscape` and `convert` command from imagemagick were not found",
|
||||
"Consider installing `inkscape` for the best results",
|
||||
)
|
||||
else:
|
||||
command = "convert"
|
||||
else:
|
||||
command = "inkscape"
|
||||
|
||||
color = (
|
||||
parse_color(user_args.iconcolor)
|
||||
if user_args.iconcolor
|
||||
else parse_color(user_args.foreground)
|
||||
)
|
||||
src_path = ICON_SVG_PATHF.format(icon_name)
|
||||
dst_path = ICON_PNG_PATHF.format(icon_name)
|
||||
|
||||
if command == "convert":
|
||||
warning("Resulting icons could look a bit off, consider installing inkscape")
|
||||
converter = magick_convert_svg2png
|
||||
elif command == "inkscape":
|
||||
converter = inkscape_convert_svg2png
|
||||
|
||||
exit_code = converter(color, src_path, dst_path, whisper=whisper)
|
||||
if exit_code != 0:
|
||||
error(f"Stop. The `{command}` command returned an error")
|
||||
|
||||
|
||||
def get_available_fonts():
|
||||
"Returns the fonts present in /fonts"
|
||||
return [
|
||||
filename[:-4] # Remove .ttf
|
||||
for filename in os.listdir(f"{INSTALLER_DIR}/fonts/")
|
||||
if filename.endswith(".ttf")
|
||||
]
|
||||
|
||||
|
||||
def parse_color(color_string):
|
||||
if color_string in AVAILABLE_COLORS:
|
||||
color = PALETTE[color_string]
|
||||
elif re.match(r"[0-9A-Fa-f]{6}", color_string) is not None:
|
||||
color = color_string
|
||||
else:
|
||||
error(
|
||||
f"Invalid color parsed from {color_string}",
|
||||
f"Color must be an hex code like C00FFE or one of: {AVAILABLE_COLORS}",
|
||||
)
|
||||
return f"#{color}"
|
||||
|
||||
|
||||
def check_icon_converted(icon):
|
||||
available_icons = get_converted_icons()
|
||||
if icon not in available_icons + ["_"]:
|
||||
error(f"Invalid icon name: {icon}", f"Icons present are: {available_icons}")
|
||||
return icon
|
||||
|
||||
|
||||
def parse_font(font):
|
||||
"""From a given --font check if available and return its font name
|
||||
e.g. Open_Sans_Regular to Open Sans Regular"""
|
||||
available_fonts = get_available_fonts()
|
||||
if font not in available_fonts:
|
||||
error(
|
||||
f"Invalid font name: {font}", f"Available font names: {available_fonts}",
|
||||
)
|
||||
return font.replace("_", " ")
|
||||
|
||||
|
||||
# Procedures
|
||||
|
||||
|
||||
def clean_install_dir():
|
||||
info("Clean install directory")
|
||||
if isdir(INSTALLATION_TARGET_DIR):
|
||||
rmtree(INSTALLATION_TARGET_DIR)
|
||||
|
||||
|
||||
def prepare_source_dir():
|
||||
info("Build theme from user preferences")
|
||||
# Get user color preferences
|
||||
highlight = parse_color(user_args.highlight)
|
||||
foreground = parse_color(user_args.foreground)
|
||||
background = parse_color(
|
||||
THEME_DEFAULT_BACKGROUND
|
||||
if user_args.background is None
|
||||
else user_args.background
|
||||
)
|
||||
image = (
|
||||
user_args.image
|
||||
if user_args.downloadbackground is None
|
||||
else download_background(user_args.downloadbackground)
|
||||
)
|
||||
fontkey = user_args.font
|
||||
fontfile = user_args.fontfile
|
||||
fontname = user_args.fontname
|
||||
fontsize = user_args.fontsize
|
||||
icons = user_args.icons
|
||||
|
||||
# Image checks
|
||||
if image:
|
||||
if not exists(image):
|
||||
error(f"{image} does not exist")
|
||||
if os.path.splitext(image)[1] not in (".png", ".jpg", ".jpeg", ".tga"):
|
||||
error("Background image must be one of .png, .jpg, .jpeg or .tga formats.")
|
||||
image_name = basename(image)
|
||||
copyfile(image, f"{INSTALLATION_SOURCE_DIR}/{image_name}")
|
||||
if user_args.background:
|
||||
warning(
|
||||
f"Both --background and --image arguments specified. Background color {background} will be ignored."
|
||||
)
|
||||
else:
|
||||
image_name = "background.png"
|
||||
|
||||
# Icon checks
|
||||
# Get entries from grub.cfg
|
||||
entries = get_entry_names()
|
||||
# Do icon count match grub entry count?
|
||||
if len(icons) != len(entries):
|
||||
error(
|
||||
f"You must specify {len(entries)} icons ({len(icons)} provided) for entries:",
|
||||
should_exit=False,
|
||||
)
|
||||
for i, m in enumerate(entries):
|
||||
print(f"{i + 1}. {m['entryname']}")
|
||||
exit(1)
|
||||
|
||||
# Font checks
|
||||
# grub-mkfont present
|
||||
grub_mkfont = which("grub-mkfont") or which("grub2-mkfont")
|
||||
if grub_mkfont is None:
|
||||
error(f"grub-mkfont command not found in your system (grub2-mkfont neither)")
|
||||
# Valid font arguments
|
||||
if fontfile is None: # User did not specify custom font file
|
||||
fontfile = f"{INSTALLER_DIR}/fonts/{fontkey}.ttf"
|
||||
fontname = f"{parse_font(fontkey)} {fontsize}"
|
||||
elif not fontfile.endswith(".ttf"): # font file is not ttf
|
||||
error(f"{fontfile} is not a .ttf file")
|
||||
elif fontname is None: # User did, but did not gave its name
|
||||
error(
|
||||
"--fontname/-fn not specified for given font file.",
|
||||
"e.g. 'Open Sans Regular'",
|
||||
)
|
||||
else: # User specified a custom fontfile
|
||||
fontname = " ".join(fontname) # e.g. Open Sans Regular
|
||||
dst_fontfile = f"{INSTALLER_DIR}/fonts/{fontname.replace(' ', '_')}.ttf" # e.g. .../Open_Sans_Regular.ttf
|
||||
copyfile(fontfile, dst_fontfile)
|
||||
fontfile = dst_fontfile
|
||||
fontname = f"{fontname} {fontsize}" # e.g. Open Sans Regular 32
|
||||
|
||||
# Prepare Icons
|
||||
|
||||
# Download not-yet-downloaded icons
|
||||
for icon in icons:
|
||||
if not is_icon_downloaded(icon) and icon != "_":
|
||||
download_icon(icon)
|
||||
|
||||
# Convert icons
|
||||
info("Convert icons")
|
||||
for i, icon in enumerate(icons):
|
||||
if icon != "_":
|
||||
if i == 0:
|
||||
convert_icon_svg2png(icon)
|
||||
else:
|
||||
convert_icon_svg2png(icon, whisper=True)
|
||||
|
||||
# Prepare Font
|
||||
|
||||
# Generate font file
|
||||
info("Build font")
|
||||
stdout = shout(
|
||||
f"{grub_mkfont} -o {INSTALLATION_SOURCE_DIR}/font.pf2 {fontfile} -s {fontsize}"
|
||||
)
|
||||
if stdout:
|
||||
error(
|
||||
f"{grub_mkfont} execution was not clean", f"for fontfile: {fontfile}",
|
||||
)
|
||||
|
||||
# Prepare Theme.txt
|
||||
|
||||
# Parse theme template with user preferences
|
||||
with open(THEME_TEMPLATE_PATH, "r", newline="") as f:
|
||||
template = f.read()
|
||||
|
||||
context = {
|
||||
"theme_name": THEME_NAME,
|
||||
"highlight": highlight,
|
||||
"foreground": foreground,
|
||||
"background": background,
|
||||
"image_name": image_name,
|
||||
"fontname": fontname,
|
||||
}
|
||||
parsed_theme = template.format(**context)
|
||||
|
||||
if image:
|
||||
parsed_theme = parsed_theme.replace("# desktop-image", "desktop-image")
|
||||
|
||||
theme_file_path = f"{INSTALLATION_SOURCE_DIR}/theme.txt"
|
||||
with open(theme_file_path, "w") as f:
|
||||
f.write(parsed_theme)
|
||||
|
||||
|
||||
def prepare_target_dir():
|
||||
info("Prepare installation directory")
|
||||
clean_install_dir()
|
||||
|
||||
|
||||
def copy_source_to_target():
|
||||
info("Copy built theme to installation directory")
|
||||
copytree(INSTALLATION_SOURCE_DIR, INSTALLATION_TARGET_DIR)
|
||||
|
||||
|
||||
def update_grub_cfg():
|
||||
info("Update grub.cfg")
|
||||
update_command = (
|
||||
which("update-grub") or which("grub-mkconfig") or which("grub2-mkconfig")
|
||||
)
|
||||
if update_command is None:
|
||||
error(
|
||||
f"Command for generating grub.cfg not found (tried update-grub, grub-mkconfig and grub2-mkconfig)"
|
||||
)
|
||||
command = f"{update_command} -o {GRUB_CFG_PATH}"
|
||||
info(f"Remake grub.cfg with {command}")
|
||||
sh(command)
|
||||
|
||||
|
||||
def update_grub_defaults():
|
||||
info(f"Patch {GRUB_DEFAULTS_PATH} with {THEME_OVERRIDES_TITLE}")
|
||||
grub_configs = read_cleaned_grub_defaults()
|
||||
|
||||
# Parse grub defaults template, append parsed contents, and write back
|
||||
|
||||
with open(GRUB_DEFAULTS_TEMPLATE_PATH, "r", newline="") as f:
|
||||
template = f.read()
|
||||
|
||||
context = {"installation_dir": INSTALLATION_TARGET_DIR}
|
||||
parsed_extra_grub = template.format(**context)
|
||||
grub_configs += (
|
||||
f"\n\n{BEGIN_THEME_OVERRIDES}\n{parsed_extra_grub}\n{END_THEME_OVERRIDES}\n\n"
|
||||
)
|
||||
|
||||
with open(GRUB_DEFAULTS_PATH, "w") as f:
|
||||
f.write(grub_configs)
|
||||
|
||||
|
||||
def clean_grub_defaults():
|
||||
info(f"Clean {THEME_OVERRIDES_TITLE} from {GRUB_DEFAULTS_PATH}")
|
||||
cleaned_grub_defaults = read_cleaned_grub_defaults()
|
||||
with open(GRUB_DEFAULTS_PATH, "w") as f:
|
||||
f.write(cleaned_grub_defaults)
|
||||
|
||||
|
||||
def clean_grub_mkconfig():
|
||||
info(f"Clean {THEME_OVERRIDES_TITLE} from {GRUB_MKCONFIG_PATH}")
|
||||
cleaned_grub_mkconfig = read_cleaned_grub_mkconfig()
|
||||
with open(GRUB_MKCONFIG_PATH, "w") as f:
|
||||
f.write(cleaned_grub_mkconfig)
|
||||
|
||||
|
||||
def clean_hookcheck():
|
||||
info(f"Remove hookcheck script from {GRUB_SCRIPTS_PATH}")
|
||||
hookcheck = f"{GRUB_SCRIPTS_PATH}/99_matter"
|
||||
if exists(hookcheck):
|
||||
os.remove(hookcheck)
|
||||
|
||||
|
||||
def get_entry_names():
|
||||
"Gets the entry names from grub.cfg contents"
|
||||
with open(GRUB_CFG_PATH, "r", newline="") as f:
|
||||
grub_cfg = f.read()
|
||||
pattern = (
|
||||
r"(?P<head>(?:submenu|menuentry) ?)" # menuentry or submenu
|
||||
r"(?:\"|')" # " or '
|
||||
r"(?P<entryname>[^\"']*)" # capture the entry name (without quotes)
|
||||
r"(?:\"|')" # " or '
|
||||
r"(?P<tail>[^\{]*\{)" # The rest of the entry header until a { is found
|
||||
)
|
||||
matchiter = re.finditer(pattern, grub_cfg)
|
||||
matches = list(matchiter)
|
||||
return matches
|
||||
|
||||
|
||||
# Main procedures
|
||||
|
||||
|
||||
def do_preinstall_hint():
|
||||
info(
|
||||
f"{color_string('[ ', fg='brightwhite')}"
|
||||
f"{color_string(THEME_NAME, fg='brightmagenta')} "
|
||||
f"{color_string('Grub Theme'.upper(), fg='lightcyan')}"
|
||||
f"{color_string(' ]', fg='brightwhite')}"
|
||||
)
|
||||
info("Argument -i required. Which icons go to which grub entries?")
|
||||
info("Your grub entries are:")
|
||||
do_list_grub_cfg_entries()
|
||||
info("Look for icons you like at https://materialdesignicons.com/")
|
||||
info("Then install with:")
|
||||
info("./matter.py -i icon-for-entry-1 icon-for-entry-2 ...")
|
||||
info("Example (with 8 entries, _ means ignore):")
|
||||
info("./matter.py -i ubuntu microsoft-windows folder _ _ _ _ cog")
|
||||
|
||||
|
||||
def do_test():
|
||||
info("Begin grub2-theme-preview")
|
||||
warning(
|
||||
"Argument --icons/-i does not have effect when testing",
|
||||
"The icon names used are coming from your system's current grub.cfg",
|
||||
"This is a feature that may work in the future",
|
||||
)
|
||||
if not has_command("grub2-theme-preview"):
|
||||
error(
|
||||
"You need grub2-theme-preview for testing",
|
||||
"See https://github.com/hartwork/grub2-theme-preview",
|
||||
)
|
||||
sh(f"grub2-theme-preview {INSTALLATION_SOURCE_DIR}")
|
||||
|
||||
|
||||
def do_install():
|
||||
info(f"Begin {THEME_NAME} install")
|
||||
prepare_source_dir()
|
||||
check_root_or_prompt()
|
||||
prepare_target_dir()
|
||||
copy_source_to_target()
|
||||
update_grub_defaults()
|
||||
do_set_icons(patch_grubcfg=True)
|
||||
install_hookcheck()
|
||||
update_grub_cfg()
|
||||
info(f"{THEME_NAME} successfully installed")
|
||||
|
||||
|
||||
def do_uninstall():
|
||||
info(f"Begin {THEME_NAME} uninstall")
|
||||
check_root_or_prompt()
|
||||
clean_grub_defaults()
|
||||
clean_grub_mkconfig()
|
||||
clean_hookcheck()
|
||||
clean_install_dir()
|
||||
update_grub_cfg()
|
||||
info(f"{THEME_NAME} successfully uninstalled")
|
||||
|
||||
|
||||
def do_list_grub_cfg_entries():
|
||||
# Read current grub cfg
|
||||
with open(GRUB_CFG_PATH, "r", newline="") as f:
|
||||
grub_cfg = f.read()
|
||||
|
||||
entries = get_entry_names()
|
||||
|
||||
for i, m in enumerate(entries):
|
||||
print(f"{i + 1}. {m['entryname']}")
|
||||
|
||||
|
||||
def create_config_file():
|
||||
icons = user_args.icons
|
||||
# Read current grub cfg
|
||||
entries = get_entry_names()
|
||||
|
||||
entries_to_icons = {}
|
||||
for icon, entry in zip(icons, entries):
|
||||
entryname = entry.group("entryname")
|
||||
if entryname in entries_to_icons:
|
||||
warning(f"Duplicate entry '{entryname}'. Unexpected behaviour may occur. Consider changing names using Grub Customizer.")
|
||||
entries_to_icons[entryname] = icon
|
||||
|
||||
config = {"icons": entries_to_icons}
|
||||
|
||||
with open(CONFIG_FILE_PATH, 'w') as f:
|
||||
f.write(json.dumps(config))
|
||||
|
||||
|
||||
def patch_from_config_file():
|
||||
# Read current grub cfg
|
||||
current_entries = get_entry_names()
|
||||
|
||||
with open(CONFIG_FILE_PATH) as f:
|
||||
config = json.loads(f.read())
|
||||
|
||||
entries_to_icons = config["icons"]
|
||||
|
||||
icons = []
|
||||
for entry in current_entries:
|
||||
entryname = entry.group("entryname")
|
||||
if entryname in entries_to_icons:
|
||||
icons.append(entries_to_icons[entryname])
|
||||
else:
|
||||
warning(
|
||||
f"{entryname} is a new grub menu entry, no icon will be set for it. "
|
||||
f"Rerun matter.py to set icons"
|
||||
)
|
||||
icons.append("_")
|
||||
|
||||
do_patch_grub_cfg_icons(icons)
|
||||
|
||||
|
||||
def do_patch_grub_cfg_icons(icons):
|
||||
|
||||
info(f"Begin {GRUB_CFG_PATH} patch")
|
||||
with open(GRUB_CFG_PATH, "r", newline="") as f:
|
||||
grub_cfg = f.read()
|
||||
# Read current grub cfg
|
||||
entries = get_entry_names()
|
||||
|
||||
# Build new grub cfg with given icons
|
||||
new_grub_cfg = ""
|
||||
next_seek = 0
|
||||
for m, i in zip(entries, icons):
|
||||
mstart, mend = m.span()
|
||||
new_grub_cfg += grub_cfg[next_seek:mstart]
|
||||
icon_class = f" --class {i} " if i != "_" else ""
|
||||
new_grub_cfg += f'{m["head"]}"{m["entryname"]}"{icon_class}{m["tail"]}'
|
||||
next_seek = mend
|
||||
new_grub_cfg += grub_cfg[mend:]
|
||||
|
||||
# Write new grub cfg back
|
||||
check_root_or_prompt()
|
||||
with open(GRUB_CFG_PATH, "w") as f:
|
||||
f.write(new_grub_cfg)
|
||||
|
||||
info(f"{len(icons)} icons successfully patched onto {GRUB_CFG_PATH}")
|
||||
|
||||
|
||||
def do_set_icons(patch_grubcfg):
|
||||
|
||||
icons = user_args.icons
|
||||
|
||||
if icons is None:
|
||||
error("Stop. Unspecified icons (--icons/-i argument)")
|
||||
icons = [check_icon_converted(i) for i in icons]
|
||||
|
||||
# Read current grub cfg
|
||||
entries = get_entry_names()
|
||||
if len(icons) != len(entries):
|
||||
error(
|
||||
f"You must specify {len(entries)} "
|
||||
f"icons ({len(icons)} provided) for entries:",
|
||||
should_exit=False,
|
||||
)
|
||||
for i, m in enumerate(entries):
|
||||
print(f"{i + 1}. {m['entryname']}")
|
||||
# NOTE: We exit with 0 here to not stop the apt upgrade process
|
||||
# eventually it will be solved with an autoremove
|
||||
exit(0)
|
||||
|
||||
do_patch_grub_cfg_icons(user_args.icons)
|
||||
|
||||
if patch_grubcfg:
|
||||
create_config_file()
|
||||
|
||||
# Patch grub-mkconfig so everytime it executes, it patches grub.cfg
|
||||
info(f"Begin {GRUB_MKCONFIG_PATH} patch")
|
||||
info(f"Clean old {GRUB_MKCONFIG_PATH} patch if any")
|
||||
|
||||
# cmd_icons = " ".join(user_args.icons)
|
||||
# seticons_call = f"{INSTALLER_DIR}/{INSTALLER_NAME} -so -i {cmd_icons} >&2"
|
||||
seticons_call = f"{INSTALLER_DIR}/{INSTALLER_NAME} --configicons >&2"
|
||||
new_grub_mkconfig = read_cleaned_grub_mkconfig()
|
||||
|
||||
# grub-mkconfig is called on upgrade, and on failure it halts.
|
||||
# A failure on our part should not halt an upgrade, let's temporarily
|
||||
# disable the stop-on-error functionality with set +e. See #67
|
||||
new_grub_mkconfig += (
|
||||
f"\n\n{BEGIN_THEME_OVERRIDES}\n"
|
||||
f"set +e\n"
|
||||
f"{seticons_call}\n"
|
||||
f"set -e\n"
|
||||
f"{END_THEME_OVERRIDES}\n\n"
|
||||
)
|
||||
|
||||
check_root_or_prompt()
|
||||
with open(GRUB_MKCONFIG_PATH, "w") as f:
|
||||
f.write(new_grub_mkconfig)
|
||||
|
||||
info(
|
||||
f"{GRUB_MKCONFIG_PATH} successfully patched, icons will now persist between grub updates."
|
||||
)
|
||||
|
||||
|
||||
def install_hookcheck():
|
||||
info(f"Create hook check script")
|
||||
with open(HOOKCHECK_TEMPLATE_PATH, "r", newline="") as f:
|
||||
template = f.read()
|
||||
|
||||
cmd_icons = " ".join(user_args.icons)
|
||||
# seticons_call = f"{INSTALLER_DIR}/{INSTALLER_NAME} -so -i {cmd_icons} >&2"
|
||||
seticons_call = f"{INSTALLER_DIR}/{INSTALLER_NAME} --configicons"
|
||||
|
||||
context = {
|
||||
"GRUB_MKCONFIG_PATH": GRUB_MKCONFIG_PATH,
|
||||
"THEME_NAME": THEME_NAME,
|
||||
"THEME_OVERRIDES_TITLE": THEME_OVERRIDES_TITLE,
|
||||
"BEGIN_THEME_OVERRIDES": BEGIN_THEME_OVERRIDES,
|
||||
"END_THEME_OVERRIDES": END_THEME_OVERRIDES,
|
||||
"SETICONS_CALL": seticons_call,
|
||||
}
|
||||
|
||||
parsed_script = template.format(**context)
|
||||
script_file_path = f"{GRUB_SCRIPTS_PATH}/99_matter"
|
||||
|
||||
with open(script_file_path, "w") as f:
|
||||
f.write(parsed_script)
|
||||
|
||||
# Make it executable by user, group and others
|
||||
st = os.stat(script_file_path)
|
||||
os.chmod(script_file_path, st.st_mode | 0o111)
|
||||
|
||||
|
||||
# Script arguments
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = ArgumentParser(
|
||||
description=THEME_DESCRIPTION,
|
||||
epilog=f"[Available colors] are: {', '.join(AVAILABLE_COLORS)}.\n"
|
||||
"You can specify your own hex colors as well (e.g. C0FFEE, FF00FF, etc).\n"
|
||||
f"[Available fonts] are: {', '.join(get_available_fonts())}\n"
|
||||
"You can always specify your own with the -ff argument\n"
|
||||
f"[Available icons] can be found at https://materialdesignicons.com/\n"
|
||||
"For requests open an issue on:\n"
|
||||
"https://github.com/mateosss/matter/issues",
|
||||
formatter_class=RawTextHelpFormatter,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--listentries", "-l", action="store_true", help=f"list grub entries",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--buildonly",
|
||||
"-b",
|
||||
action="store_true",
|
||||
help=f"prepare the theme but do not install it",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--test",
|
||||
"-t",
|
||||
action="store_true",
|
||||
help=f"test the generated theme with grub2-theme-preview",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--icons",
|
||||
"-i",
|
||||
type=str,
|
||||
nargs="*",
|
||||
help=f"specify icons for each grub entry listed with -l",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--seticons",
|
||||
"-si",
|
||||
action="store_true",
|
||||
help=f"set grub entries icons given by -i and patch grub-mkconfig for persistence",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--seticons_once",
|
||||
"-so",
|
||||
action="store_true",
|
||||
help=f"set grub entries icons given by -i, will be reverted on next grub update",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--uninstall", "-u", action="store_true", help=f"uninstall {THEME_NAME}",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--highlight",
|
||||
"-hl",
|
||||
type=str,
|
||||
help=f"selected text color",
|
||||
default=THEME_DEFAULT_HIGHLIGHT,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--foreground",
|
||||
"-fg",
|
||||
type=str,
|
||||
help=f"main text color",
|
||||
default=THEME_DEFAULT_FOREGROUND,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--background",
|
||||
"-bg",
|
||||
type=str,
|
||||
help=f"solid background color",
|
||||
default=None,
|
||||
# default will be set to THEME_DEFAULT_BACKGROUND
|
||||
)
|
||||
parser.add_argument(
|
||||
"--image",
|
||||
"-im",
|
||||
type=str,
|
||||
help=f"image file to use as background, supported extensions: PNG, JPG, JPEG, TGA",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--iconcolor",
|
||||
"-ic",
|
||||
type=str,
|
||||
help=f"icons fill color, by default same as foreground",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--font",
|
||||
"-f",
|
||||
type=str,
|
||||
help=f"theme font from already downloaded fonts",
|
||||
default=THEME_DEFAULT_FONT,
|
||||
choices=get_available_fonts(),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--fontfile", "-ff", type=str, help=f"import theme font from custom .ttf file"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--fontname",
|
||||
"-fn",
|
||||
type=str,
|
||||
nargs="*",
|
||||
help=f"specify the font name for the given font file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--fontsize",
|
||||
"-fs",
|
||||
type=int,
|
||||
help=f"theme font size",
|
||||
default=THEME_DEFAULT_FONT_SIZE,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--configicons",
|
||||
"-ci",
|
||||
action="store_true",
|
||||
help="set grub entries icons using config file. "
|
||||
)
|
||||
parser.add_argument(
|
||||
"--downloadbackground",
|
||||
"-dlbg",
|
||||
type=str,
|
||||
help=f"download the background image from the given url",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
check_python_version()
|
||||
user_args = parse_args()
|
||||
|
||||
if user_args.listentries:
|
||||
do_list_grub_cfg_entries()
|
||||
elif user_args.buildonly:
|
||||
prepare_source_dir()
|
||||
elif user_args.seticons_once:
|
||||
do_set_icons(patch_grubcfg=False)
|
||||
elif user_args.seticons:
|
||||
do_set_icons(patch_grubcfg=True)
|
||||
elif user_args.uninstall:
|
||||
do_uninstall()
|
||||
elif user_args.configicons:
|
||||
patch_from_config_file()
|
||||
elif user_args.icons is None:
|
||||
do_preinstall_hint()
|
||||
else:
|
||||
do_install()
|
||||
|
||||
if user_args.test:
|
||||
do_test()
|
||||
except KeyboardInterrupt:
|
||||
error("Stop. Script halted by user")
|
||||
sys.exit(1)
|
||||
117
matter/svg2png.py
Executable file
|
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
import xml.dom.minidom
|
||||
|
||||
# Local Matter modules
|
||||
from utils import sh, shout, error
|
||||
|
||||
|
||||
def inkscape_convert_svg2png(color, src_path, dst_path, whisper=False):
|
||||
# SVG_URI = "http://www.w3.org/2000/svg"
|
||||
FRAC = 0.6
|
||||
TEMPFILE = "temp.svg"
|
||||
|
||||
def parse_with_map(source):
|
||||
"""Parses file, returns a tuple containing the parsed ElementTree and a namespace map (dict).
|
||||
|
||||
The ElementTree object returned is the same as if parsed using xml.etree.ElementTree.parse. For
|
||||
some reason, ElementTree objects by the xml package will not provide a namespace map, unlike the
|
||||
lxml package.
|
||||
"""
|
||||
|
||||
root = None
|
||||
ns_map = []
|
||||
for event, node in ET.iterparse(source, events=["start-ns", "start"]):
|
||||
if event == "start-ns":
|
||||
ns_map.append(node)
|
||||
elif event == "start":
|
||||
if root is None:
|
||||
root = node
|
||||
return (ET.ElementTree(root), dict(ns_map))
|
||||
|
||||
def int_ignore_units(s):
|
||||
return int("".join(ch for ch in s if ch.isdigit()))
|
||||
|
||||
def prettify(xml_string):
|
||||
return "\n".join(
|
||||
line
|
||||
for line in xml.dom.minidom.parseString(xml_string)
|
||||
.toprettyxml(indent=" ")
|
||||
.splitlines()
|
||||
if not line.isspace() and line != ""
|
||||
)
|
||||
|
||||
# Fixes undefined namespace tags in output xml (not a big issue)
|
||||
dom, ns_map = parse_with_map(src_path)
|
||||
for key, value in ns_map.items():
|
||||
ET.register_namespace(key, value)
|
||||
|
||||
root = dom.getroot()
|
||||
_, _, width, height = map(int, filter(bool, re.split(r'[ ,]', root.attrib["viewBox"])))
|
||||
width_gap, height_gap = (1 - FRAC) * width / 2, (1 - FRAC) * height / 2
|
||||
|
||||
# Group all elements that are children of <svg> while changing their 'style' attributes
|
||||
elements = list(root)
|
||||
group = ET.SubElement(root, "g")
|
||||
for element in elements:
|
||||
# Don't group these special tags
|
||||
if any(map(element.tag.endswith, ["defs", "metadata"])):
|
||||
continue
|
||||
root.remove(element)
|
||||
# Changes all decendents (.iter will also include itself)
|
||||
for child in element.iter():
|
||||
if "style" in child.attrib:
|
||||
child.attrib["style"] = re.sub(
|
||||
r"(?<=fill:)\S+?(?=;)", color, child.attrib["style"]
|
||||
)
|
||||
else:
|
||||
child.attrib["style"] = f"fill:{color};"
|
||||
group.append(element)
|
||||
# Shrink the svg by a factor of FRAC for padding around icon
|
||||
group.attrib["transform"] = f"matrix({FRAC},0,0,{FRAC},{width_gap},{height_gap})"
|
||||
|
||||
xml_string = ET.tostring(root).decode()
|
||||
xml_string = prettify(xml_string)
|
||||
with open(TEMPFILE, "w") as f:
|
||||
f.write(xml_string)
|
||||
|
||||
# Check inkscape version
|
||||
version_string = shout("inkscape --version 2>/dev/null", silence=whisper)
|
||||
inkscape_major = re.search(r"(\d+)\.\d+(\.\d+)?", version_string).group(1)
|
||||
command = "inkscape "
|
||||
if inkscape_major == "1":
|
||||
command += f"--export-filename={dst_path} "
|
||||
elif inkscape_major == "0":
|
||||
command += f"--without-gui --export-png={dst_path} "
|
||||
else:
|
||||
error("Unsupported inkscape version")
|
||||
command += f"-w 72 {TEMPFILE}"
|
||||
if whisper:
|
||||
command += " 2>&1 | tail -1"
|
||||
exit_code = sh(command)
|
||||
|
||||
os.remove(TEMPFILE)
|
||||
return exit_code
|
||||
|
||||
|
||||
def magick_convert_svg2png(color, src_path, dst_path, whisper=None):
|
||||
cmd = (
|
||||
r"convert -trim -scale 36x36 -extent 72x72 -gravity center "
|
||||
r"-define png:color-type=6 -background none -colorspace sRGB -channel RGB "
|
||||
rf"-threshold -1 -density 300 -fill \{color} +opaque none "
|
||||
rf"{src_path} {dst_path}"
|
||||
)
|
||||
return os.system(cmd)
|
||||
|
||||
|
||||
# For demostration purposes
|
||||
if __name__ == "__main__":
|
||||
svg2png = inkscape_convert_svg2png
|
||||
# svg2png = magick_convert_svg2png
|
||||
for file in os.listdir("./icons"):
|
||||
basename, ext = os.path.splitext(file)
|
||||
if ext == ".svg":
|
||||
svg2png("#FFFFFF", f"icons/{basename}.svg", f"icons/{basename}.png")
|
||||
48
matter/theme.txt.template
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# If this file is called theme.txt then the theme template has been
|
||||
# already parsed and the comments below could not make too much sense.
|
||||
|
||||
# theme.txt.template represents a python string that gets format()-ed
|
||||
# Note: for escaping literal curly braces, double them like so: {{ or }}
|
||||
|
||||
# {theme_name} Theme File
|
||||
# Designed for any resolution
|
||||
|
||||
# Global Property
|
||||
title-text: ""
|
||||
# desktop-image: "{image_name}"
|
||||
desktop-color: "{background}"
|
||||
terminal-font: "Unifont Regular 16" # A smaller font for the console
|
||||
terminal-box: "terminal_box_*.png"
|
||||
terminal-left: "0"
|
||||
terminal-top: "0"
|
||||
terminal-width: "100%"
|
||||
terminal-height: "100%"
|
||||
terminal-border: "0"
|
||||
|
||||
# Show the boot menu
|
||||
+ boot_menu {{
|
||||
left = 36%
|
||||
top = 29%
|
||||
width = 28%
|
||||
height = 60%
|
||||
item_font = "{fontname}"
|
||||
item_color = "{foreground}"
|
||||
selected_item_color = "{highlight}"
|
||||
icon_width = 72
|
||||
icon_height = 72
|
||||
item_height = 72
|
||||
item_spacing = 36
|
||||
selected_item_pixmap_style = "select_*.png"
|
||||
}}
|
||||
|
||||
# Show a countdown message using the label component
|
||||
+ label {{
|
||||
top = 82%
|
||||
left = 35%
|
||||
width = 30%
|
||||
align = "center"
|
||||
id = "__timeout__"
|
||||
text = "Booting in %d seconds"
|
||||
color = "{foreground}"
|
||||
font = "{fontname}"
|
||||
}}
|
||||
61
matter/utils.py
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from subprocess import run, PIPE
|
||||
from shutil import which
|
||||
|
||||
# Logging utils
|
||||
|
||||
def color_string(string, fg=None):
|
||||
COLORS = { # List some colors that may be needed
|
||||
"red": "\033[31m",
|
||||
"pink": "\033[38;5;206m",
|
||||
"green": "\033[32m",
|
||||
"orange": "\033[33m",
|
||||
"blue": "\033[34m",
|
||||
"cyan": "\033[36m",
|
||||
"lightred": "\033[91m",
|
||||
"lightgreen": "\033[92m",
|
||||
"yellow": "\033[93m",
|
||||
"lightblue": "\033[94m",
|
||||
"lightcyan": "\033[96m",
|
||||
"brightwhite": "\u001b[37;1m",
|
||||
"brightmagenta": "\u001b[35;1m",
|
||||
}
|
||||
endcolor = "\033[0m"
|
||||
return f"{COLORS.get(fg, '')}{string}{endcolor}"
|
||||
|
||||
|
||||
def info(*lines):
|
||||
for line in lines:
|
||||
print(f"{color_string('[I] ', fg='cyan')}{line}")
|
||||
|
||||
|
||||
def error(*lines, should_exit=True):
|
||||
for line in lines:
|
||||
print(f"{color_string('[E] ', fg='lightred')}{line}")
|
||||
if should_exit:
|
||||
exit(1)
|
||||
|
||||
def warning(*lines):
|
||||
for line in lines:
|
||||
print(f"{color_string('[W] ', fg='yellow')}{line}")
|
||||
|
||||
|
||||
# Shell / external utils
|
||||
|
||||
|
||||
def sh(command):
|
||||
"Executes command in shell and returns its exit status"
|
||||
return run(command, shell=True).returncode
|
||||
|
||||
|
||||
def shout(command, silence=False):
|
||||
"Executes command in shell and returns its stdout"
|
||||
stdout = run(command, shell=True, stdout=PIPE).stdout.decode("utf-8")
|
||||
if not silence:
|
||||
print(stdout)
|
||||
return stdout
|
||||
|
||||
|
||||
def has_command(command):
|
||||
return which(command) is not None
|
||||