summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormono-b <monoblanco@DRAINERDOMAIN.localdomain>2022-12-26 04:08:53 -0300
committermono-b <monoblanco@DRAINERDOMAIN.localdomain>2022-12-26 04:08:53 -0300
commit8dc8f2d52338fd87e7763995e6732f5a295300e8 (patch)
tree56ea8a124b9a81e42251ffa1be92ad6475d7bef3
huh
-rw-r--r--X11/.xinitrc36
-rw-r--r--X11/xresources59
-rw-r--r--X11/xserverrc2
-rw-r--r--dunst/dunstrc473
-rw-r--r--i3/config221
-rw-r--r--lf/lfrc118
-rw-r--r--mpd/mpd.conf430
-rw-r--r--mpv/mpv.conf21
-rw-r--r--mpv/scripts/skip-intro.lua151
-rw-r--r--mpv/scripts/webm.lua2913
-rw-r--r--ncmpcpp/config76
m---------ncmpcpp/ncmpcpp-ueberzug0
-rw-r--r--neofetch/config.conf864
-rw-r--r--newsboat/config113
-rw-r--r--nvim/autoload/plug.vim2812
-rw-r--r--nvim/init.vim89
m---------nvim/plugged/coc.nvim0
m---------nvim/plugged/emmet-vim0
m---------nvim/plugged/goyo.vim0
m---------nvim/plugged/gruvbox0
m---------nvim/plugged/lightline.vim0
m---------nvim/plugged/nerdtree0
m---------nvim/plugged/vim-devicons0
m---------nvim/plugged/vim-nightfly-guicolors0
m---------nvim/plugged/wal.vim0
-rw-r--r--picom/picom.conf68
-rw-r--r--polybar/cuts/bars.ini542
-rw-r--r--polybar/cuts/colors.ini32
-rw-r--r--polybar/cuts/config.ini308
-rwxr-xr-xpolybar/cuts/launch.sh14
-rw-r--r--polybar/cuts/modules.ini1108
-rw-r--r--polybar/cuts/preview.ini323
-rwxr-xr-xpolybar/cuts/preview.sh14
-rwxr-xr-xpolybar/cuts/scripts/checkupdates117
-rwxr-xr-xpolybar/cuts/scripts/color-switch.sh55
-rwxr-xr-xpolybar/cuts/scripts/colors-dark.sh102
-rwxr-xr-xpolybar/cuts/scripts/colors-light.sh102
-rwxr-xr-xpolybar/cuts/scripts/launcher.sh3
-rwxr-xr-xpolybar/cuts/scripts/powermenu.sh94
-rwxr-xr-xpolybar/cuts/scripts/pywal.sh59
-rwxr-xr-xpolybar/cuts/scripts/random.sh91
-rw-r--r--polybar/cuts/scripts/rofi/colors.rasi10
-rw-r--r--polybar/cuts/scripts/rofi/confirm.rasi25
-rw-r--r--polybar/cuts/scripts/rofi/launcher.rasi115
-rw-r--r--polybar/cuts/scripts/rofi/message.rasi24
-rw-r--r--polybar/cuts/scripts/rofi/networkmenu.rasi123
-rw-r--r--polybar/cuts/scripts/rofi/powermenu.rasi123
-rw-r--r--polybar/cuts/scripts/rofi/styles.rasi123
-rwxr-xr-xpolybar/cuts/scripts/style-switch.sh20
-rwxr-xr-xpolybar/cuts/scripts/styles.sh89
-rwxr-xr-xpolybar/cuts/scripts/updates.sh45
-rw-r--r--polybar/cuts/user_modules.ini258
-rwxr-xr-xpolybar/launch.sh12
-rw-r--r--profanity/profrc0
-rw-r--r--rofi/config.rasi2
-rw-r--r--tmux/tmux.conf8
-rw-r--r--urlwview/.urlview29
-rw-r--r--yt-dlp/config1
-rw-r--r--zathura/zathurarc1
-rw-r--r--zsh/.zprofile7
m---------zsh/.zsh/zsh-autosuggestions0
-rw-r--r--zsh/.zshenv32
-rw-r--r--zsh/.zshrc78
63 files changed, 12535 insertions, 0 deletions
diff --git a/X11/.xinitrc b/X11/.xinitrc
new file mode 100644
index 0000000..3c270fd
--- /dev/null
+++ b/X11/.xinitrc
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+userresources=$HOME/.Xresources
+usermodmap=$HOME/.Xmodmap
+sysresources=/etc/X11/xinit/.Xresources
+sysmodmap=/etc/X11/xinit/.Xmodmap
+
+# merge in defaults and keymaps
+
+if [ -f $sysresources ]; then
+ xrdb -merge $sysresources
+fi
+
+if [ -f $sysmodmap ]; then
+ xmodmap $sysmodmap
+fi
+
+if [ -f "$userresources" ]; then
+ xrdb -merge "$userresources"
+fi
+
+if [ -f "$usermodmap" ]; then
+ xmodmap "$usermodmap"
+fi
+
+# start some nice programs
+
+if [ -d /etc/X11/xinit/xinitrc.d ] ; then
+ for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do
+ [ -x "$f" ] && . "$f"
+ done
+ unset f
+fi
+
+runsvdir $HOME/.config/sv &
+exec i3
diff --git a/X11/xresources b/X11/xresources
new file mode 100644
index 0000000..824918e
--- /dev/null
+++ b/X11/xresources
@@ -0,0 +1,59 @@
+! X colors.
+! Generated by 'wal'
+*foreground: #e5e5e8
+*background: #100f0e
+*.foreground: #e5e5e8
+*.background: #100f0e
+XTerm*foreground: #e5e5e8
+XTerm*background: #100f0e
+XTerm*cursorColor: #e5e5e8
+
+! Colors 0-15.
+*.color0: #100f0e
+*color0: #100f0e
+*.color1: #e56800
+*color1: #e56800
+*.color2: #fdb64e
+*color2: #fdb64e
+*.color3: #fecf41
+*color3: #fecf41
+*.color4: #7C838F
+*color4: #7C838F
+*.color5: #B8BAC5
+*color5: #B8BAC5
+*.color6: #CDCED6
+*color6: #CDCED6
+*.color7: #e5e5e8
+*color7: #e5e5e8
+*.color8: #a0a0a2
+*color8: #a0a0a2
+*.color9: #d27e3b
+*color9: #d27e3b
+*.color10: #fdb64e
+*color10: #fdb64e
+*.color11: #fecf41
+*color11: #fecf41
+*.color12: #7C838F
+*color12: #7C838F
+*.color13: #B8BAC5
+*color13: #B8BAC5
+*.color14: #CDCED6
+*color14: #CDCED6
+*.color15: #e5e5e8
+*color15: #e5e5e8
+
+! Black color that will not be affected by bold highlighting.
+*.color66: #100f0e
+*color66: #100f0e
+
+! Xclock colors.
+XClock*foreground: #e5e5e8
+XClock*background: #100f0e
+XClock*majorColor: rgba:e5/e5/e8/ff
+XClock*minorColor: rgba:e5/e5/e8/ff
+XClock*hourColor: rgba:e5/e5/e8/ff
+XClock*minuteColor: rgba:e5/e5/e8/ff
+XClock*secondColor: rgba:e5/e5/e8/ff
+
+! Set depth to make transparency work.
+URxvt*depth: 32
diff --git a/X11/xserverrc b/X11/xserverrc
new file mode 100644
index 0000000..d76ef8f
--- /dev/null
+++ b/X11/xserverrc
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/bin/Xorg -nolisten tcp "$@" vt$XDG_VTNR
diff --git a/dunst/dunstrc b/dunst/dunstrc
new file mode 100644
index 0000000..51766ec
--- /dev/null
+++ b/dunst/dunstrc
@@ -0,0 +1,473 @@
+[global]
+ ### Display ###
+
+ # Which monitor should the notifications be displayed on.
+ monitor = 0
+
+ # Display notification on focused monitor. Possible modes are:
+ # mouse: follow mouse pointer
+ # keyboard: follow window with keyboard focus
+ # none: don't follow anything
+ #
+ # "keyboard" needs a window manager that exports the
+ # _NET_ACTIVE_WINDOW property.
+ # This should be the case for almost all modern window managers.
+ #
+ # If this option is set to mouse or keyboard, the monitor option
+ # will be ignored.
+ follow = mouse
+
+ # The geometry of the window:
+ # [{width}]x{height}[+/-{x}+/-{y}]
+ # The geometry of the message window.
+ # The height is measured in number of notifications everything else
+ # in pixels. If the width is omitted but the height is given
+ # ("-geometry x2"), the message window expands over the whole screen
+ # (dmenu-like). If width is 0, the window expands to the longest
+ # message displayed. A positive x is measured from the left, a
+ # negative from the right side of the screen. Y is measured from
+ # the top and down respectively.
+ # The width can be negative. In this case the actual width is the
+ # screen width minus the width defined in within the geometry option.
+ geometry = "0x200-20+25"
+
+ # Turn on the progess bar
+ progress_bar = true
+
+ # Set the progress bar height. This includes the frame, so make sure
+ # it's at least twice as big as the frame width.
+ progress_bar_height = 0
+
+ # Set the frame width of the progress bar
+ progress_bar_frame_width = 0
+
+ # Set the minimum width for the progress bar
+ progress_bar_min_width = 150
+
+ # Set the maximum width for the progress bar
+ progress_bar_max_width = 300
+
+
+ # Show how many messages are currently hidden (because of geometry).
+ indicate_hidden = yes
+
+ # Shrink window if it's smaller than the width. Will be ignored if
+ # width is 0.
+ shrink = no
+
+ # The transparency of the window. Range: [0; 100].
+ # This option will only work if a compositing window manager is
+ # present (e.g. xcompmgr, compiz, etc.).
+ transparency = 10
+
+ # The height of the entire notification. If the height is smaller
+ # than the font height and padding combined, it will be raised
+ # to the font height and padding.
+ notification_height = 0
+
+ # Draw a line of "separator_height" pixel height between two
+ # notifications.
+ # Set to 0 to disable.
+ separator_height = 0
+
+ # Padding between text and separator.
+ padding = 8
+
+ # Horizontal padding.
+ horizontal_padding = 8
+
+ # Padding between text and icon.
+ text_icon_padding = 6
+
+ # Defines width in pixels of frame around the notification window.
+ # Set to 0 to disable.
+ frame_width = 1
+
+ # Defines color of the frame around the notification window.
+ frame_color = "#fff"
+
+ # Define a color for the separator.
+ # possible values are:
+ # * auto: dunst tries to find a color fitting to the background;
+ # * foreground: use the same color as the foreground;
+ # * frame: use the same color as the frame;
+ # * anything else will be interpreted as a X color.
+ separator_color = frame
+
+ # Sort messages by urgency.
+ sort = no
+
+ # Don't remove messages, if the user is idle (no mouse or keyboard input)
+ # for longer than idle_threshold seconds.
+ # Set to 0 to disable.
+ # A client can set the 'transient' hint to bypass this. See the rules
+ # section for how to disable this if necessary
+ idle_threshold = 120
+
+ ### Text ###
+
+ font = Iosevka 13
+
+ # The spacing between lines. If the height is smaller than the
+ # font height, it will get raised to the font height.
+ line_height = 1
+
+ # Possible values are:
+ # full: Allow a small subset of html markup in notifications:
+ # <b>bold</b>
+ # <i>italic</i>
+ # <s>strikethrough</s>
+ # <u>underline</u>
+ #
+ # For a complete reference see
+ # <https://developer.gnome.org/pango/stable/pango-Markup.html>.
+ #
+ # strip: This setting is provided for compatibility with some broken
+ # clients that send markup even though it's not enabled on the
+ # server. Dunst will try to strip the markup but the parsing is
+ # simplistic so using this option outside of matching rules for
+ # specific applications *IS GREATLY DISCOURAGED*.
+ #
+ # no: Disable markup parsing, incoming notifications will be treated as
+ # plain text. Dunst will not advertise that it has the body-markup
+ # capability if this is set as a global setting.
+ #
+ # It's important to note that markup inside the format option will be parsed
+ # regardless of what this is set to.
+ markup = full
+
+ # The format of the message. Possible variables are:
+ # %a appname
+ # %s summary
+ # %b body
+ # %i iconname (including its path)
+ # %I iconname (without its path)
+ # %p progress value if set ([ 0%] to [100%]) or nothing
+ # %n progress value if set without any extra characters
+ # %% Literal %
+ # Markup is allowed
+ format = "%s\n%b"
+
+ # Alignment of message text.
+ # Possible values are "left", "center" and "right".
+ alignment = center
+
+ # Vertical alignment of message text and icon.
+ # Possible values are "top", "center" and "bottom".
+ vertical_alignment = center
+
+ # Show age of message if message is older than show_age_threshold
+ # seconds.
+ # Set to -1 to disable.
+ show_age_threshold = 60
+
+ # Split notifications into multiple lines if they don't fit into
+ # geometry.
+ word_wrap = yes
+
+ # When word_wrap is set to no, specify where to make an ellipsis in long lines.
+ # Possible values are "start", "middle" and "end".
+ ellipsize = middle
+
+ # Ignore newlines '\n' in notifications.
+ ignore_newline = no
+
+ # Stack together notifications with the same content
+ stack_duplicates = true
+
+ # Hide the count of stacked notifications with the same content
+ hide_duplicate_count = false
+
+ # Display indicators for URLs (U) and actions (A).
+ show_indicators = yes
+
+ ### Icons ###
+
+ # Align icons left/right/off
+ icon_position = left
+
+ # Scale small icons up to this size, set to 0 to disable. Helpful
+ # for e.g. small files or high-dpi screens. In case of conflict,
+ # max_icon_size takes precedence over this.
+ min_icon_size = 0
+
+ # Scale larger icons down to this size, set to 0 to disable
+ max_icon_size = 32
+
+ # Paths to default icons.
+ #icon_path = /usr/share/icons/Adwaita/16x16/status/:/usr/share/icons/Adwaita/16x16/devices/:/usr/share/icons/Adwaita/16x16/legacy/
+
+ ### History ###
+
+ # Should a notification popped up from history be sticky or timeout
+ # as if it would normally do.
+ sticky_history = yes
+
+ # Maximum amount of notifications kept in history
+ history_length = 20
+
+ ### Misc/Advanced ###
+
+ # dmenu path.
+ dmenu = /usr/bin/dmenu -p dunst:
+
+ # Browser for opening urls in context menu.
+ browser = /usr/bin/brave -new-tab
+
+ # Always run rule-defined scripts, even if the notification is suppressed
+ always_run_script = true
+
+ # Define the title of the windows spawned by dunst
+ title = Dunst
+
+ # Define the class of the windows spawned by dunst
+ class = Dunst
+
+ # Print a notification on startup.
+ # This is mainly for error detection, since dbus (re-)starts dunst
+ # automatically after a crash.
+ startup_notification = false
+
+ # Manage dunst's desire for talking
+ # Can be one of the following values:
+ # crit: Critical features. Dunst aborts
+ # warn: Only non-fatal warnings
+ # mesg: Important Messages
+ # info: all unimportant stuff
+ # debug: all less than unimportant stuff
+ verbosity = mesg
+
+ # Define the corner radius of the notification window
+ # in pixel size. If the radius is 0, you have no rounded
+ # corners.
+ # The radius will be automatically lowered if it exceeds half of the
+ # notification height to avoid clipping text and/or icons.
+ corner_radius = 0
+
+ # Ignore the dbus closeNotification message.
+ # Useful to enforce the timeout set by dunst configuration. Without this
+ # parameter, an application may close the notification sent before the
+ # user defined timeout.
+ ignore_dbusclose = false
+
+ ### Wayland ###
+ # These settings are Wayland-specific. They have no effect when using X11
+
+ # Uncomment this if you want to let notications appear under fullscreen
+ # applications (default: overlay)
+ # layer = top
+
+ # Set this to true to use X11 output on Wayland.
+ force_xwayland = false
+
+ ### Legacy
+
+ # Use the Xinerama extension instead of RandR for multi-monitor support.
+ # This setting is provided for compatibility with older nVidia drivers that
+ # do not support RandR and using it on systems that support RandR is highly
+ # discouraged.
+ #
+ # By enabling this setting dunst will not be able to detect when a monitor
+ # is connected or disconnected which might break follow mode if the screen
+ # layout changes.
+ force_xinerama = false
+
+ ### mouse
+
+ # Defines list of actions for each mouse event
+ # Possible values are:
+ # * none: Don't do anything.
+ # * do_action: If the notification has exactly one action, or one is marked as default,
+ # invoke it. If there are multiple and no default, open the context menu.
+ # * close_current: Close current notification.
+ # * close_all: Close all notifications.
+ # These values can be strung together for each mouse event, and
+ # will be executed in sequence.
+ mouse_left_click = close_current
+ mouse_middle_click = do_action, close_current
+ mouse_right_click = close_all
+
+# Experimental features that may or may not work correctly. Do not expect them
+# to have a consistent behaviour across releases.
+[experimental]
+ # Calculate the dpi to use on a per-monitor basis.
+ # If this setting is enabled the Xft.dpi value will be ignored and instead
+ # dunst will attempt to calculate an appropriate dpi value for each monitor
+ # using the resolution and physical size. This might be useful in setups
+ # where there are multiple screens with very different dpi values.
+ per_monitor_dpi = false
+
+# The internal keyboard shortcut support in dunst is now considered deprecated
+# and should be replaced by dunstctl calls. You can use the configuration of your
+# WM or DE to bind these to shortcuts of your choice.
+# Check the dunstctl manual page for more info.
+[shortcuts]
+
+ # Shortcuts are specified as [modifier+][modifier+]...key
+ # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2",
+ # "mod3" and "mod4" (windows-key).
+ # Xev might be helpful to find names for keys.
+
+ # Close notification. Equivalent dunstctl command:
+ # dunstctl close
+ # close = ctrl+space
+
+ # Close all notifications. Equivalent dunstctl command:
+ # dunstctl close-all
+ close_all = ctrl+shift+x
+
+ # Redisplay last message(s). Equivalent dunstctl command:
+ # dunstctl history-pop
+ history = ctrl+shift+space
+
+ # Context menu. Equivalent dunstctl command:
+ # dunstctl context
+ context = ctrl+shift+c
+
+[urgency_low]
+ # IMPORTANT: colors have to be defined in quotation marks.
+ # Otherwise the "#" and following would be interpreted as a comment.
+ background = "#100f0e"
+ foreground = "#e5e5e8"
+ timeout = 10
+ # Icon for notifications with low urgency, uncomment to enable
+ #icon = /path/to/icon
+
+[urgency_normal]
+ background = "#100f0e"
+ foreground = "#e5e5e8"
+ timeout = 10
+ # Icon for notifications with normal urgency, uncomment to enable
+ #icon = /path/to/icon
+
+[urgency_critical]
+ background = "#900000"
+ foreground = "#ffffff"
+ frame_color = "#ff0000"
+ timeout = 0
+ # Icon for notifications with critical urgency, uncomment to enable
+ #icon = /path/to/icon
+
+#[maim]
+# appname = ~/Scripts/maimfull
+# background = "#44475A"
+# foreground = "#F8F8F2"
+# icon = ~/.config/dunst/screenshooter.png
+# timeout = 10
+
+# Every section that isn't one of the above is interpreted as a rules to
+# override settings for certain messages.
+#
+# Messages can be matched by
+# appname (discouraged, see desktop_entry)
+# body
+# category
+# desktop_entry
+# icon
+# match_transient
+# msg_urgency
+# stack_tag
+# summary
+#
+# and you can override the
+# background
+# foreground
+# format
+# frame_color
+# fullscreen
+# new_icon
+# set_stack_tag
+# set_transient
+# timeout
+# urgency
+#
+# Shell-like globbing will get expanded.
+#
+# Instead of the appname filter, it's recommended to use the desktop_entry filter.
+# GLib based applications export their desktop-entry name. In comparison to the appname,
+# the desktop-entry won't get localized.
+#
+# SCRIPTING
+# You can specify a script that gets run when the rule matches by
+# setting the "script" option.
+# The script will be called as follows:
+# script appname summary body icon urgency
+# where urgency can be "LOW", "NORMAL" or "CRITICAL".
+#
+# NOTE: if you don't want a notification to be displayed, set the format
+# to "".
+# NOTE: It might be helpful to run dunst -print in a terminal in order
+# to find fitting options for rules.
+
+# Disable the transient hint so that idle_threshold cannot be bypassed from the
+# client
+#[transient_disable]
+# match_transient = yes
+# set_transient = no
+#
+# Make the handling of transient notifications more strict by making them not
+# be placed in history.
+#[transient_history_ignore]
+# match_transient = yes
+# history_ignore = yes
+
+# fullscreen values
+# show: show the notifications, regardless if there is a fullscreen window opened
+# delay: displays the new notification, if there is no fullscreen window active
+# If the notification is already drawn, it won't get undrawn.
+# pushback: same as delay, but when switching into fullscreen, the notification will get
+# withdrawn from screen again and will get delayed like a new notification
+#[fullscreen_delay_everything]
+# fullscreen = delay
+#[fullscreen_show_critical]
+# msg_urgency = critical
+# fullscreen = show
+
+#[espeak]
+# summary = "*"
+# script = dunst_espeak.sh
+
+#[script-test]
+# summary = "*script*"
+# script = dunst_test.sh
+
+#[ignore]
+# # This notification will not be displayed
+# summary = "foobar"
+# format = ""
+
+#[history-ignore]
+# # This notification will not be saved in history
+# summary = "foobar"
+# history_ignore = yes
+
+#[skip-display]
+# # This notification will not be displayed, but will be included in the history
+# summary = "foobar"
+# skip_display = yes
+
+#[signed_on]
+# appname = Pidgin
+# summary = "*signed on*"
+# urgency = low
+#
+#[signed_off]
+# appname = Pidgin
+# summary = *signed off*
+# urgency = low
+#
+#[says]
+# appname = Pidgin
+# summary = *says*
+# urgency = critical
+#
+#[twitter]
+# appname = Pidgin
+# summary = *twitter.com*
+# urgency = normal
+#
+#[stack-volumes]
+# appname = "some_volume_notifiers"
+# set_stack_tag = "volume"
+#
+# vim: ft=cfg
diff --git a/i3/config b/i3/config
new file mode 100644
index 0000000..8c33961
--- /dev/null
+++ b/i3/config
@@ -0,0 +1,221 @@
+# Keyboard layout
+exec --no-startup-id setxkbmap -layout es
+
+# Font
+font pango:Iosevka 10
+
+# Master key
+set $mod Mod4
+
+# Mouse drag floating window
+floating_modifier $mod
+
+# Popup fullscreen
+
+popup_during_fullscreen smart
+
+# Start a terminal
+bindsym $mod+Return exec st
+
+# Kill focused window
+bindsym $mod+Shift+q kill
+
+# Start dmenu / rofi
+#bindsym $mod+d exec "dmenu_run -nf '#b4b4b9' -nb '#020221' -sb '#ff3600' -sf '#ffffff' -fn 'Hack-11'"
+bindsym $mod+d exec rofi -no-lazy-grab -show drun -modi drun -icon-theme "Papirus" -show-icons -font "Iosevka Nerd Font 12"
+
+# Change focus window
+bindsym $mod+Left focus left
+bindsym $mod+Down focus down
+bindsym $mod+Up focus up
+bindsym $mod+Right focus right
+
+# move focus window
+bindsym $mod+Shift+Left move left
+bindsym $mod+Shift+Down move down
+bindsym $mod+Shift+Up move up
+bindsym $mod+Shift+Right move right
+
+# Vim move focus window
+bindsym $mod+h focus left
+bindsym $mod+j focus down
+bindsym $mod+k focus up
+bindsym $mod+l focus right
+
+# Vim focus window
+bindsym $mod+Shift+h move left
+bindsym $mod+Shift+j move down
+bindsym $mod+Shift+k move up
+bindsym $mod+Shift+l move right
+
+# Split window
+bindsym $mod+ñ split h
+bindsym $mod+v split v
+
+# Fullscreen toggle
+bindsym $mod+f fullscreen toggle
+
+# Change container layout (stacked, tabbed, toggle split)
+bindsym $mod+s layout stacking
+bindsym $mod+w layout tabbed
+bindsym $mod+e layout toggle split
+
+# Toggle tiling / floating
+bindsym $mod+Shift+space floating toggle
+
+# Focus the parent container
+bindsym $mod+a focus parent
+
+# Focus the child container
+#bindsym $mod+d focus child
+
+# Workspace variables
+set $ws1 "1"
+set $ws2 "2"
+set $ws3 "3"
+set $ws4 "4"
+set $ws5 "5"
+set $ws6 "6"
+set $ws7 "7"
+set $ws8 "8"
+set $ws9 "9"
+set $ws10 "10"
+
+# Switch to workspace
+bindsym $mod+1 workspace number $ws1
+bindsym $mod+2 workspace number $ws2
+bindsym $mod+3 workspace number $ws3
+bindsym $mod+4 workspace number $ws4
+bindsym $mod+5 workspace number $ws5
+bindsym $mod+6 workspace number $ws6
+bindsym $mod+7 workspace number $ws7
+bindsym $mod+8 workspace number $ws8
+bindsym $mod+9 workspace number $ws9
+bindsym $mod+0 workspace number $ws10
+
+# Move focused container to workspace
+bindsym $mod+Shift+1 move container to workspace number $ws1
+bindsym $mod+Shift+2 move container to workspace number $ws2
+bindsym $mod+Shift+3 move container to workspace number $ws3
+bindsym $mod+Shift+4 move container to workspace number $ws4
+bindsym $mod+Shift+5 move container to workspace number $ws5
+bindsym $mod+Shift+6 move container to workspace number $ws6
+bindsym $mod+Shift+7 move container to workspace number $ws7
+bindsym $mod+Shift+8 move container to workspace number $ws9
+bindsym $mod+Shift+9 move container to workspace number $ws9
+bindsym $mod+Shift+0 move container to workspace number $ws10
+
+# Reload the configuration file
+#
+bindsym $mod+Shift+c reload
+# Restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
+bindsym $mod+Shift+r restart
+# Exit i3 (logs you out of your X session)
+bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"
+
+# Resize window (you can also use the mouse for that)
+mode "resize" {
+
+ bindsym Left resize shrink width 10 px or 10 ppt
+ bindsym Down resize grow height 10 px or 10 ppt
+ bindsym Up resize shrink height 10 px or 10 ppt
+ bindsym Right resize grow width 10 px or 10 ppt
+
+ # back to normal: Enter or Escape or $mod+r
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+ bindsym $mod+r mode "default"
+}
+
+bindsym $mod+r mode "resize"
+
+# Polybar
+exec_always --no-startup-id $HOME/.config/polybar/launch.sh
+
+# Shortcuts
+bindsym $mod+Shift+o exec libreoffice
+bindsym $mod+t exec dino
+bindsym $mod+n exec initnews.sh
+bindsym $mod+Shift+g exec krita
+bindsym $mod+Shift+Ctrl+l exec rofibooks.sh
+bindsym $mod+g exec rofigames.sh
+bindsym $mod+y exec invidious_search.sh
+bindsym $mod+F8 exec newsboatreload.sh
+#bindsym $mod+F9 exec screenzug.sh
+bindsym $mod+F9 exec st -n ncmpzug -e ncmpcpp-ueberzug
+bindsym $mod+F10 exec firefox
+bindsym $mod+F11 exec discord
+bindsym $mod+F12 exec steam
+
+# Take screenshots
+bindsym $mod+Insert exec screenshots.sh
+
+# Record video
+bindsym $mod+Shift+Ctrl+r exec screenrec.sh
+bindsym $mod+Shift+Ctrl+s exec killffmpeg.sh
+
+# Disable window titlebars
+
+for_window [class=".*"] border pixel 2
+gaps inner 5
+gaps outer 5
+
+# HDMI
+workspace "10" output HDMI-1
+
+# Wallpaper
+exec --no-startup-id exec bash $HOME/.config/feh/.fehbg
+
+# Graphic compositor
+exec dbus-launch picom --config ~/.config/picom.conf
+
+# Set colors from Xresources
+# Change 'color7' and 'color2' to whatever colors you want i3 to use
+# from the generated scheme.
+# NOTE: The '#f0f0f0' in the lines below is the color i3 will use if
+# it fails to get colors from Xresources.
+set_from_resource $fg i3wm.color15 #fff
+set_from_resource $bg i3wm.color14 #fff
+
+# class border backgr. text indicator child_border
+client.focused $fg $bg $fg $fg $fg
+client.focused_inactive $bg $bg $fg $bg $bg
+client.unfocused $bg $bg $fg $bg $bg
+client.urgent $bg $bg $fg $bg $bg
+client.placeholder $bg $bg $fg $bg $bg
+
+client.background $bg
+
+# Assigning and manipulating windows
+#for_window [instance="newsboatfs"] move container to workspace $ws10
+for_window [instance="mpvfloat"] floating enable, resize set 960 540, move container position center
+for_window [instance="ncmpzug"] floating enable, resize set 585 184, move position 683 572
+
+# Start on refresh
+exec_always dunst
+
+# Start newsboat
+exec newsboat
+
+# Mpc controls
+bindsym $mod+Shift+F2 exec mpc volume -5
+bindsym $mod+Shift+F3 exec mpc volume +5
+bindsym $mod+F5 exec mpc prev
+bindsym $mod+Shift+F5 exec mpc seekthrough -00:00:02
+bindsym $mod+F6 exec mpc toggle
+bindsym $mod+Shift+F6 exec mpc stop
+bindsym $mod+F7 exec mpc next
+bindsym $mod+Shift+F7 exec mpc seekthrough +00:00:02
+bindsym $mod+Shift+F8 exec mpc update
+
+# Applets
+exec --no-startup-id nm-applet
+exec --no-startup-id pasystray
+
+# Audio
+exec --no-startup-id pipewire
+exec --no-startup-id pipewire-pulse
+exec --no-startup-id wireplumber
+
+# Xresources
+exec xrdb -merge ~/.config/X11/xresources
diff --git a/lf/lfrc b/lf/lfrc
new file mode 100644
index 0000000..20f643d
--- /dev/null
+++ b/lf/lfrc
@@ -0,0 +1,118 @@
+# interpreter for shell commands
+set shell sh
+
+# preview
+
+set previewer ctpv
+set cleaner ctpvclear
+&ctpv -s $id
+&ctpvquit $id
+
+# set '-eu' options for shell commands
+# These options are used to have safer shell commands. Option '-e' is used to
+# exit on error and option '-u' is used to give error for unset variables.
+# Option '-f' disables pathname expansion which can be useful when $f, $fs, and
+# $fx variables contain names with '*' or '?' characters. However, this option
+# is used selectively within individual commands as it can be limiting at
+# times.
+set shellopts '-eu'
+
+# set internal field separator (IFS) to "\n" for shell commands
+# This is useful to automatically split file names in $fs and $fx properly
+# since default file separator used in these variables (i.e. 'filesep' option)
+# is newline. You need to consider the values of these options and create your
+# commands accordingly.
+set ifs "\n"
+
+# leave some space at the top and the bottom of the screen
+set scrolloff 10
+
+# use enter for shell commands
+map <enter> shell
+
+# execute current file (must be executable)
+map x $$f
+map X !$f
+
+# dedicated keys for file opener actions
+map o &mimeopen $f
+map O $mimeopen --ask $f
+
+# define a custom 'open' command
+# This command is called when current file is not a directory. You may want to
+# use either file extensions and/or mime types here. Below uses an editor for
+# text files and a file opener for the rest.
+cmd open &{{
+ case $(file --mime-type -Lb $f) in
+ text/*) lf -remote "send $id \$$EDITOR \$fx";;
+ *) for f in $fx; do $OPENER $f > /dev/null 2> /dev/null & done;;
+ esac
+}}
+
+# define a custom 'rename' command without prompt for overwrite
+# cmd rename %[ -e $1 ] && printf "file exists" || mv $f $1
+# map r push :rename<space>
+
+# make sure trash folder exists
+# %mkdir -p ~/.trash
+
+# move current file or selected files to trash folder
+# (also see 'man mv' for backup/overwrite options)
+cmd trash %set -f; mv $fx ~/.trash
+
+# define a custom 'delete' command
+# cmd delete ${{
+# set -f
+# printf "$fx\n"
+# printf "delete?[y/n]"
+# read ans
+# [ "$ans" = "y" ] && rm -rf $fx
+# }}
+
+# use '<delete>' key for either 'trash' or 'delete' command
+# map <delete> trash
+# map <delete> delete
+
+# extract the current file with the right command
+# (xkcd link: https://xkcd.com/1168/)
+cmd extract ${{
+ set -f
+ case $f in
+ *.tar.bz|*.tar.bz2|*.tbz|*.tbz2) tar xjvf $f;;
+ *.tar.gz|*.tgz) tar xzvf $f;;
+ *.tar.xz|*.txz) tar xJvf $f;;
+ *.zip) unzip $f;;
+ *.rar) unrar x $f;;
+ *.7z) 7z x $f;;
+ esac
+}}
+
+# compress current file or selected files with tar and gunzip
+cmd tar ${{
+ set -f
+ mkdir $1
+ cp -r $fx $1
+ tar czf $1.tar.gz $1
+ rm -rf $1
+}}
+
+# compress current file or selected files with zip
+cmd zip ${{
+ set -f
+ mkdir $1
+ cp -r $fx $1
+ zip -r $1.zip $1
+ rm -rf $1
+}}
+
+set drawbox
+
+# Copy to sys clipboard
+cmd yank-path $printf '%s' "$fx" | xclip -i -selection clipboard
+map Y yank-path
+
+# 2 cols only
+
+${{
+ lf -remote "send $id set ratios 1:2"
+}}
diff --git a/mpd/mpd.conf b/mpd/mpd.conf
new file mode 100644
index 0000000..3f31c7c
--- /dev/null
+++ b/mpd/mpd.conf
@@ -0,0 +1,430 @@
+# An example configuration file for MPD.
+# Read the user manual for documentation: http://www.musicpd.org/doc/user/
+
+
+# Files and directories #######################################################
+#
+# This setting controls the top directory which MPD will search to discover the
+# available audio files and add them to the daemon's online database. This
+# setting defaults to the XDG directory, otherwise the music directory will be
+# be disabled and audio files will only be accepted over ipc socket (using
+# file:// protocol) or streaming files over an accepted protocol.
+#
+music_directory "~/stf/music"
+#
+# This setting sets the MPD internal playlist directory. The purpose of this
+# directory is storage for playlists created by MPD. The server will use
+# playlist files not created by the server but only if they are in the MPD
+# format. This setting defaults to playlist saving being disabled.
+#
+playlist_directory "~/.config/mpd/playlists"
+#
+# This setting sets the location of the MPD database. This file is used to
+# load the database at server start up and store the database while the
+# server is not up. This setting defaults to disabled which will allow
+# MPD to accept files over ipc socket (using file:// protocol) or streaming
+# files over an accepted protocol.
+#
+db_file "~/.config/mpd/database"
+#
+# These settings are the locations for the daemon log files for the daemon.
+# These logs are great for troubleshooting, depending on your log_level
+# settings.
+#
+# The special value "syslog" makes MPD use the local syslog daemon. This
+# setting defaults to logging to syslog.
+#
+log_file "~/.config/mpd/log"
+#
+# This setting sets the location of the file which stores the process ID
+# for use of mpd --kill and some init scripts. This setting is disabled by
+# default and the pid file will not be stored.
+#
+pid_file "~/.config/mpd/pid"
+#
+# This setting sets the location of the file which contains information about
+# most variables to get MPD back into the same general shape it was in before
+# it was brought down. This setting is disabled by default and the server
+# state will be reset on server start up.
+#
+state_file "~/.config/mpd/state"
+#
+# The location of the sticker database. This is a database which
+# manages dynamic information attached to songs.
+#
+sticker_file "~/.config/mpd/sticker.sql"
+#
+###############################################################################
+
+
+# General music daemon options ################################################
+#
+# This setting specifies the user that MPD will run as. MPD should never run as
+# root and you may use this setting to make MPD change its user ID after
+# initialization. This setting is disabled by default and MPD is run as the
+# current user.
+#
+#user "nobody"
+#
+# This setting specifies the group that MPD will run as. If not specified
+# primary group of user specified with "user" setting will be used (if set).
+# This is useful if MPD needs to be a member of group such as "audio" to
+# have permission to use sound card.
+#
+#group "nogroup"
+#
+# This setting sets the address for the daemon to listen on. Careful attention
+# should be paid if this is assigned to anything other than the default, any.
+# This setting can deny access to control of the daemon. Not effective if
+# systemd socket activiation is in use.
+#
+# For network
+bind_to_address "localhost"
+#
+# And for Unix Socket
+#bind_to_address "~/.mpd/socket"
+#
+# This setting is the TCP port that is desired for the daemon to get assigned
+# to.
+#
+port "6600"
+#
+# Suppress all messages below the given threshold. Use "verbose" for
+# troubleshooting. Available setting arguments are "notice", "info", "verbose",
+# "warning" and "error".
+#
+#log_level "notice"
+#
+# Setting "restore_paused" to "yes" puts MPD into pause mode instead
+# of starting playback after startup.
+#
+#restore_paused "no"
+#
+# This setting enables MPD to create playlists in a format usable by other
+# music players.
+#
+save_absolute_paths_in_playlists "yes"
+#
+# This setting defines a list of tag types that will be extracted during the
+# audio file discovery process. The complete list of possible values can be
+# found in the user manual.
+#metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc"
+#
+# This example just enables the "comment" tag without disabling all
+# the other supported tags:
+#metadata_to_use "+comment"
+#
+# This setting enables automatic update of MPD's database when files in
+# music_directory are changed.
+#
+auto_update "yes"
+#
+# Limit the depth of the directories being watched, 0 means only watch
+# the music directory itself. There is no limit by default.
+#
+#auto_update_depth "3"
+#
+###############################################################################
+
+
+# Symbolic link behavior ######################################################
+#
+# If this setting is set to "yes", MPD will discover audio files by following
+# symbolic links outside of the configured music_directory.
+#
+#follow_outside_symlinks "yes"
+#
+# If this setting is set to "yes", MPD will discover audio files by following
+# symbolic links inside of the configured music_directory.
+#
+#follow_inside_symlinks "yes"
+#
+###############################################################################
+
+
+# Zeroconf / Avahi Service Discovery ##########################################
+#
+# If this setting is set to "yes", service information will be published with
+# Zeroconf / Avahi.
+#
+#zeroconf_enabled "yes"
+#
+# The argument to this setting will be the Zeroconf / Avahi unique name for
+# this MPD server on the network. %h will be replaced with the hostname.
+#
+#zeroconf_name "Music Player @ %h"
+#
+###############################################################################
+
+
+# Permissions #################################################################
+#
+# If this setting is set, MPD will require password authorization. The password
+# setting can be specified multiple times for different password profiles.
+#
+#password "password@read,add,control,admin"
+#
+# This setting specifies the permissions a user has who has not yet logged in.
+#
+#default_permissions "read,add,control,admin"
+#
+###############################################################################
+
+
+# Database #######################################################################
+#
+# An example of a database section instead of the old 'db_file' setting.
+# It enables mounting other storages into the music directory.
+#
+#database {
+# plugin "simple"
+# path "~/.local/share/mpd/db
+# cache_directory "~/.local/share/mpd/cache"
+#}
+#
+# An example of database config for a sattelite setup
+#
+#music_directory "nfs://fileserver.local/srv/mp3"
+#database {
+# plugin "proxy"
+# host "other.mpd.host"
+# port "6600"
+#}
+
+# Input #######################################################################
+#
+input {
+ plugin "curl"
+# proxy "proxy.isp.com:8080"
+# proxy_user "user"
+# proxy_password "password"
+}
+
+#
+###############################################################################
+
+# Audio Output ################################################################
+#
+# MPD supports various audio output types, as well as playing through multiple
+# audio outputs at the same time, through multiple audio_output settings
+# blocks. Setting this block is optional, though the server will only attempt
+# autodetection for one sound card.
+#
+# An example of an ALSA output:
+#
+#audio_output {
+# type "alsa"
+# name "My ALSA Device"
+## device "hw:0,0" # optional
+ mixer_type "software" # optional
+## mixer_device "default" # optional
+## mixer_control "PCM" # optional
+## mixer_index "0" # optional
+#}
+#
+# An example of an OSS output:
+#
+#audio_output {
+# type "oss"
+# name "My OSS Device"
+## device "/dev/dsp" # optional
+## mixer_type "hardware" # optional
+## mixer_device "/dev/mixer" # optional
+## mixer_control "PCM" # optional
+#}
+#
+# An example of a shout output (for streaming to Icecast):
+#
+#audio_output {
+# type "shout"
+# encoder "vorbis" # optional
+# name "My Shout Stream"
+# host "localhost"
+# port "8000"
+# mount "/mpd.ogg"
+# password "hackme"
+# quality "5.0"
+# bitrate "128"
+# format "44100:16:1"
+## protocol "icecast2" # optional
+## user "source" # optional
+## description "My Stream Description" # optional
+## url "http://example.com" # optional
+## genre "jazz" # optional
+## public "no" # optional
+## timeout "2" # optional
+## mixer_type "software" # optional
+#}
+#
+# An example of a recorder output:
+#
+#audio_output {
+# type "recorder"
+# name "My recorder"
+# encoder "vorbis" # optional, vorbis or lame
+# path "/var/lib/mpd/recorder/mpd.ogg"
+## quality "5.0" # do not define if bitrate is defined
+# bitrate "128" # do not define if quality is defined
+# format "44100:16:1"
+#}
+#
+# An example of a httpd output (built-in HTTP streaming server):
+#
+#audio_output {
+# type "httpd"
+# name "My HTTP Stream"
+# encoder "vorbis" # optional, vorbis or lame
+# port "8000"
+# bind_to_address "0.0.0.0" # optional, IPv4 or IPv6
+## quality "5.0" # do not define if bitrate is defined
+# bitrate "128" # do not define if quality is defined
+# format "44100:16:1"
+# max_clients "0" # optional 0=no limit
+#}
+#
+# An example of a pulseaudio output (streaming to a remote pulseaudio server)
+#
+#audio_output {
+# type "pulse"
+# name "My Pulse Output"
+## server "remote_server" # optional
+## sink "remote_server_sink" # optional
+## media_role "media_role" #optional
+#}
+#
+# An example of a winmm output (Windows multimedia API).
+#
+#audio_output {
+# type "winmm"
+# name "My WinMM output"
+## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional
+# or
+## device "0" # optional
+## mixer_type "hardware" # optional
+#}
+#
+# An example of a wasapi output (Windows multimedia API).
+#
+#audio_output {
+# type "wasapi"
+# name "My WASAPI output"
+## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional
+# or
+## device "0" # optional
+## Exclusive mode blocks all other audio source, and get best audio quality without resampling.
+## exclusive "no" # optional
+## Enumerate all devices in log.
+## enumerate "no" # optional
+#}
+#
+# An example of an openal output.
+#
+#audio_output {
+# type "openal"
+# name "My OpenAL output"
+## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional
+#}
+#
+# An example of an sndio output.
+#
+#audio_output {
+# type "sndio"
+# name "sndio output"
+# mixer_type "hardware"
+#}
+#
+# An example of an OS X output:
+#
+#audio_output {
+# type "osx"
+# name "My OS X Device"
+## device "Built-in Output" # optional
+## channel_map "-1,-1,0,1" # optional
+#}
+#
+## Example "pipe" output:
+#
+#audio_output {
+# type "pipe"
+# name "my pipe"
+# command "aplay -f cd 2>/dev/null"
+## Or if you're want to use AudioCompress
+# command "AudioCompress -m | aplay -f cd 2>/dev/null"
+## Or to send raw PCM stream through PCM:
+# command "nc example.org 8765"
+# format "44100:16:2"
+#}
+#
+## An example of a null output (for no audio output):
+#
+#audio_output {
+# type "null"
+# name "My Null Output"
+# mixer_type "none" # optional
+#}
+#
+###############################################################################
+
+
+# Normalization automatic volume adjustments ##################################
+#
+# This setting specifies the type of ReplayGain to use. This setting can have
+# the argument "off", "album", "track" or "auto". "auto" is a special mode that
+# chooses between "track" and "album" depending on the current state of
+# random playback. If random playback is enabled then "track" mode is used.
+# See <https://wiki.hydrogenaud.io/index.php?title=Replaygain> for
+# more details about ReplayGain.
+# This setting is off by default.
+#
+#replaygain "album"
+#
+# This setting sets the pre-amp used for files that have ReplayGain tags. By
+# default this setting is disabled.
+#
+#replaygain_preamp "0"
+#
+# This setting sets the pre-amp used for files that do NOT have ReplayGain tags.
+# By default this setting is disabled.
+#
+#replaygain_missing_preamp "0"
+#
+# This setting enables or disables ReplayGain limiting.
+# MPD calculates actual amplification based on the ReplayGain tags
+# and replaygain_preamp / replaygain_missing_preamp setting.
+# If replaygain_limit is enabled MPD will never amplify audio signal
+# above its original level. If replaygain_limit is disabled such amplification
+# might occur. By default this setting is enabled.
+#
+#replaygain_limit "yes"
+#
+# This setting enables on-the-fly normalization volume adjustment. This will
+# result in the volume of all playing audio to be adjusted so the output has
+# equal "loudness". This setting is disabled by default.
+#
+#volume_normalization "no"
+#
+###############################################################################
+
+# Character Encoding ##########################################################
+#
+# If file or directory names do not display correctly for your locale then you
+# may need to modify this setting.
+#
+filesystem_charset "UTF-8"
+#
+###############################################################################
+
+audio_output {
+ type "alsa"
+ name "ALSA sound card"
+ # Optional
+ # #device "iec958:CARD=Intel,DEV=0"
+ # #mixer_control "PCM"
+ }
+
+audio_output {
+ type "fifo"
+ name "my_fifo"
+ path "/tmp/mpd.fifo"
+ format "44100:16:2"
+}
diff --git a/mpv/mpv.conf b/mpv/mpv.conf
new file mode 100644
index 0000000..b26b92e
--- /dev/null
+++ b/mpv/mpv.conf
@@ -0,0 +1,21 @@
+# Cache
+
+cache=yes
+--stream-buffer-size=8MiB
+
+# Quality stream
+
+ytdl-format=bestvideo[height<=?720]+bestaudio/best
+
+# Yt-dlp hook
+
+script-opts-append=ytdl_hook-ytdl_path=yt-dlp
+
+# Subs
+
+sub-auto=fuzzy
+sub-bold=yes
+
+# High Quality Configurations
+
+profile=gpu-hq
diff --git a/mpv/scripts/skip-intro.lua b/mpv/scripts/skip-intro.lua
new file mode 100644
index 0000000..9dcd7b4
--- /dev/null
+++ b/mpv/scripts/skip-intro.lua
@@ -0,0 +1,151 @@
+MAX_SPEED = 100
+NORMAL_SPEED = 1
+ONE_SECOND = 1
+skip = false
+-- Max noise (dB) and min silence duration (s) to trigger
+opts = { quietness = -30, duration = 0.5 }
+
+
+function setOptions()
+ local options = require 'mp.options'
+ options.read_options(opts)
+end
+
+function setTime(time)
+ mp.set_property_number('time-pos', time)
+end
+
+function getTime()
+ return mp.get_property_native('time-pos')
+end
+
+function setSpeed(speed)
+ mp.set_property('speed', speed)
+end
+
+function setPause(state)
+ mp.set_property_bool('pause', state)
+end
+
+function setMute(state)
+ mp.set_property_bool('mute', state)
+end
+
+function initAudioFilter()
+ local af_table = mp.get_property_native('af')
+ af_table[#af_table + 1] = {
+ enabled = false,
+ label = 'silencedetect',
+ name = 'lavfi',
+ params = { graph = 'silencedetect=noise=' .. opts.quietness .. 'dB:d=' .. opts.duration }
+ }
+ mp.set_property_native('af', af_table)
+end
+
+function initVideoFilter()
+ local vf_table = mp.get_property_native('vf')
+ vf_table[#vf_table + 1] = {
+ enabled = false,
+ label = 'blackout',
+ name = 'lavfi',
+ params = { graph = '' }
+ }
+ mp.set_property_native('vf', vf_table)
+end
+
+function setAudioFilter(state)
+ local af_table = mp.get_property_native('af')
+ if #af_table > 0 then
+ for i = #af_table, 1, -1 do
+ if af_table[i].label == 'silencedetect' then
+ af_table[i].enabled = state
+ mp.set_property_native('af', af_table)
+ break
+ end
+ end
+ end
+end
+
+function dim(state)
+ local dim = { width = 0, height = 0 }
+ if state == true then
+ dim.width = mp.get_property_native('width')
+ dim.height = mp.get_property_native('height')
+ end
+ return dim.width .. 'x' .. dim.height
+end
+
+function setVideoFilter(state)
+ local vf_table = mp.get_property_native('vf')
+ if #vf_table > 0 then
+ for i = #vf_table, 1, -1 do
+ if vf_table[i].label == 'blackout' then
+ vf_table[i].enabled = state
+ vf_table[i].params = { graph = 'nullsink,color=c=black:s=' .. dim(state) }
+ mp.set_property_native('vf', vf_table)
+ break
+ end
+ end
+ end
+end
+
+function silenceTrigger(name, value)
+ if value == '{}' or value == nil then
+ return
+ end
+
+ local skipTime = tonumber(string.match(value, '%d+%.?%d+'))
+ local currTime = getTime()
+
+ if skipTime == nil or skipTime < currTime + ONE_SECOND then
+ return
+ end
+
+ stopSkip()
+ setTime(skipTime)
+ skip = false
+end
+
+function setAudioTrigger(state)
+ if state == true then
+ mp.observe_property('af-metadata/silencedetect', 'string', silenceTrigger)
+ else
+ mp.unobserve_property(silenceTrigger)
+ end
+end
+
+function startSkip()
+ startTime = getTime()
+ -- This audio filter detects moments of silence
+ setAudioFilter(true)
+ -- This video filter makes fast-forward faster
+ setVideoFilter(true)
+ setAudioTrigger(true)
+ setPause(false)
+ setMute(true)
+ setSpeed(MAX_SPEED)
+end
+
+function stopSkip()
+ setAudioFilter(false)
+ setVideoFilter(false)
+ setAudioTrigger(false)
+ setMute(false)
+ setSpeed(NORMAL_SPEED)
+end
+
+function keypress()
+ skip = not skip
+ if skip then
+ startSkip()
+ else
+ stopSkip()
+ setTime(startTime)
+ end
+end
+
+setOptions(opts)
+initAudioFilter()
+initVideoFilter()
+
+mp.add_key_binding('Tab', 'skip-key', keypress)
diff --git a/mpv/scripts/webm.lua b/mpv/scripts/webm.lua
new file mode 100644
index 0000000..f92d707
--- /dev/null
+++ b/mpv/scripts/webm.lua
@@ -0,0 +1,2913 @@
+local mp = require("mp")
+local assdraw = require("mp.assdraw")
+local msg = require("mp.msg")
+local utils = require("mp.utils")
+local mpopts = require("mp.options")
+local options = {
+ -- Defaults to shift+w
+ keybind = "W",
+ -- If empty, saves on the same directory of the playing video.
+ -- A starting "~" will be replaced by the home dir.
+ -- This field is delimited by double-square-brackets - [[ and ]] - instead of
+ -- quotes, because Windows users might run into a issue when using
+ -- backslashes as a path separator. Examples of valid inputs for this field
+ -- would be: [[]] (the default, empty value), [[C:\Users\John]] (on Windows),
+ -- and [[/home/john]] (on Unix-like systems eg. Linux).
+ -- The [[]] delimiter is not needed when using from a configuration file
+ -- in the script-opts folder.
+ output_directory = [[/home/monoblanco/stf/vids/clipsmpv]],
+ run_detached = false,
+ -- Template string for the output file
+ -- %f - Filename, with extension
+ -- %F - Filename, without extension
+ -- %T - Media title, if it exists, or filename, with extension (useful for some streams, such as YouTube).
+ -- %s, %e - Start and end time, with milliseconds
+ -- %S, %E - Start and end time, without milliseconds
+ -- %M - "-audio", if audio is enabled, empty otherwise
+ -- %R - "-(height)p", where height is the video's height, or scale_height, if it's enabled.
+ -- More specifiers are supported, see https://mpv.io/manual/master/#options-screenshot-template
+ -- Property expansion is supported (with %{} at top level, ${} when nested), see https://mpv.io/manual/master/#property-expansion
+ output_template = "%f",
+ -- Scale video to a certain height, keeping the aspect ratio. -1 disables it.
+ scale_height = -1,
+ -- Change the FPS of the output video, dropping or duplicating frames as needed.
+ -- -1 means the FPS will be unchanged from the source.
+ fps = -1,
+ -- Target filesize, in kB. This will be used to calculate the bitrate
+ -- used on the encode. If this is set to <= 0, the video bitrate will be set
+ -- to 0, which might enable constant quality modes, depending on the
+ -- video codec that's used (VP8 and VP9, for example).
+ target_filesize = 2500,
+ -- If true, will use stricter flags to ensure the resulting file doesn't
+ -- overshoot the target filesize. Not recommended, as constrained quality
+ -- mode should work well, unless you're really having trouble hitting
+ -- the target size.
+ strict_filesize_constraint = false,
+ strict_bitrate_multiplier = 0.95,
+ -- In kilobits.
+ strict_audio_bitrate = 64,
+ -- Sets the output format, from a few predefined ones.
+ -- Currently we have:
+ -- webm-vp8 (libvpx/libvorbis)
+ -- webm-vp9 (libvpx-vp9/libopus)
+ -- mp4 (h264/AAC)
+ -- mp4-nvenc (h264-NVENC/AAC)
+ -- raw (rawvideo/pcm_s16le).
+ -- mp3 (libmp3lame)
+ -- and gif
+ output_format = "webm-vp8",
+ twopass = true,
+ -- If set, applies the video filters currently used on the playback to the encode.
+ apply_current_filters = true,
+ -- If set, writes the video's filename to the "Title" field on the metadata.
+ write_filename_on_metadata = false,
+ -- Set the number of encoding threads, for codecs libvpx and libvpx-vp9
+ libvpx_threads = 4,
+ additional_flags = "",
+ -- Constant Rate Factor (CRF). The value meaning and limits may change,
+ -- from codec to codec. Set to -1 to disable.
+ crf = 10,
+ -- Useful for flags that may impact output filesize, such as qmin, qmax etc
+ -- Won't be applied when strict_filesize_constraint is on.
+ non_strict_additional_flags = "",
+ -- Display the encode progress, in %. Requires run_detached to be disabled.
+ -- On Windows, it shows a cmd popup. "auto" will display progress on non-Windows platforms.
+ display_progress = "auto",
+ -- The font size used in the menu. Isn't used for the notifications (started encode, finished encode etc)
+ font_size = 28,
+ margin = 10,
+ message_duration = 5,
+ -- gif dither mode, 0-5 for bayer w/ bayer_scale 0-5, 6 for paletteuse default (sierra2_4a)
+ gif_dither = 2,
+ -- Force square pixels on output video
+ -- Some players like recent Firefox versions display videos with non-square pixels with wrong aspect ratio
+ force_square_pixels = false,
+}
+
+mpopts.read_options(options)
+local base64_chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+
+-- encoding
+function base64_encode(data)
+ return ((data:gsub('.', function(x)
+ local r,b='',x:byte()
+ for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
+ return r;
+ end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
+ if (#x < 6) then return '' end
+ local c=0
+ for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
+ return base64_chars:sub(c+1,c+1)
+ end)..({ '', '==', '=' })[#data%3+1])
+end
+
+-- decoding
+function base64_decode(data)
+ data = string.gsub(data, '[^'..base64_chars..'=]', '')
+ return (data:gsub('.', function(x)
+ if (x == '=') then return '' end
+ local r,f='',(base64_chars:find(x)-1)
+ for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
+ return r;
+ end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
+ if (#x ~= 8) then return '' end
+ local c=0
+ for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
+ return string.char(c)
+ end))
+end
+local emit_event
+emit_event = function(event_name, ...)
+ return mp.commandv("script-message", "webm-" .. tostring(event_name), ...)
+end
+local test_set_options
+test_set_options = function(new_options_json)
+ local new_options = utils.parse_json(new_options_json)
+ for k, v in pairs(new_options) do
+ options[k] = v
+ end
+end
+mp.register_script_message("mpv-webm-set-options", test_set_options)
+local bold
+bold = function(text)
+ return "{\\b1}" .. tostring(text) .. "{\\b0}"
+end
+local message
+message = function(text, duration)
+ local ass = mp.get_property_osd("osd-ass-cc/0")
+ ass = ass .. text
+ return mp.osd_message(ass, duration or options.message_duration)
+end
+local append
+append = function(a, b)
+ for _, val in ipairs(b) do
+ a[#a + 1] = val
+ end
+ return a
+end
+local seconds_to_time_string
+seconds_to_time_string = function(seconds, no_ms, full)
+ if seconds < 0 then
+ return "unknown"
+ end
+ local ret = ""
+ if not (no_ms) then
+ ret = string.format(".%03d", seconds * 1000 % 1000)
+ end
+ ret = string.format("%02d:%02d%s", math.floor(seconds / 60) % 60, math.floor(seconds) % 60, ret)
+ if full or seconds > 3600 then
+ ret = string.format("%d:%s", math.floor(seconds / 3600), ret)
+ end
+ return ret
+end
+local seconds_to_path_element
+seconds_to_path_element = function(seconds, no_ms, full)
+ local time_string = seconds_to_time_string(seconds, no_ms, full)
+ local _
+ time_string, _ = time_string:gsub(":", ".")
+ return time_string
+end
+local file_exists
+file_exists = function(name)
+ local info, err = utils.file_info(name)
+ if info ~= nil then
+ return true
+ end
+ return false
+end
+local expand_properties
+expand_properties = function(text, magic)
+ if magic == nil then
+ magic = "$"
+ end
+ for prefix, raw, prop, colon, fallback, closing in text:gmatch("%" .. magic .. "{([?!]?)(=?)([^}:]*)(:?)([^}]*)(}*)}") do
+ local err
+ local prop_value
+ local compare_value
+ local original_prop = prop
+ local get_property = mp.get_property_osd
+ if raw == "=" then
+ get_property = mp.get_property
+ end
+ if prefix ~= "" then
+ for actual_prop, compare in prop:gmatch("(.-)==(.*)") do
+ prop = actual_prop
+ compare_value = compare
+ end
+ end
+ if colon == ":" then
+ prop_value, err = get_property(prop, fallback)
+ else
+ prop_value, err = get_property(prop, "(error)")
+ end
+ prop_value = tostring(prop_value)
+ if prefix == "?" then
+ if compare_value == nil then
+ prop_value = err == nil and fallback .. closing or ""
+ else
+ prop_value = prop_value == compare_value and fallback .. closing or ""
+ end
+ prefix = "%" .. prefix
+ elseif prefix == "!" then
+ if compare_value == nil then
+ prop_value = err ~= nil and fallback .. closing or ""
+ else
+ prop_value = prop_value ~= compare_value and fallback .. closing or ""
+ end
+ else
+ prop_value = prop_value .. closing
+ end
+ if colon == ":" then
+ local _
+ text, _ = text:gsub("%" .. magic .. "{" .. prefix .. raw .. original_prop:gsub("%W", "%%%1") .. ":" .. fallback:gsub("%W", "%%%1") .. closing .. "}", expand_properties(prop_value))
+ else
+ local _
+ text, _ = text:gsub("%" .. magic .. "{" .. prefix .. raw .. original_prop:gsub("%W", "%%%1") .. closing .. "}", prop_value)
+ end
+ end
+ return text
+end
+local format_filename
+format_filename = function(startTime, endTime, videoFormat)
+ local hasAudioCodec = videoFormat.audioCodec ~= ""
+ local replaceFirst = {
+ ["%%mp"] = "%%mH.%%mM.%%mS",
+ ["%%mP"] = "%%mH.%%mM.%%mS.%%mT",
+ ["%%p"] = "%%wH.%%wM.%%wS",
+ ["%%P"] = "%%wH.%%wM.%%wS.%%wT"
+ }
+ local replaceTable = {
+ ["%%wH"] = string.format("%02d", math.floor(startTime / (60 * 60))),
+ ["%%wh"] = string.format("%d", math.floor(startTime / (60 * 60))),
+ ["%%wM"] = string.format("%02d", math.floor(startTime / 60 % 60)),
+ ["%%wm"] = string.format("%d", math.floor(startTime / 60)),
+ ["%%wS"] = string.format("%02d", math.floor(startTime % 60)),
+ ["%%ws"] = string.format("%d", math.floor(startTime)),
+ ["%%wf"] = string.format("%s", startTime),
+ ["%%wT"] = string.sub(string.format("%.3f", startTime % 1), 3),
+ ["%%mH"] = string.format("%02d", math.floor(endTime / (60 * 60))),
+ ["%%mh"] = string.format("%d", math.floor(endTime / (60 * 60))),
+ ["%%mM"] = string.format("%02d", math.floor(endTime / 60 % 60)),
+ ["%%mm"] = string.format("%d", math.floor(endTime / 60)),
+ ["%%mS"] = string.format("%02d", math.floor(endTime % 60)),
+ ["%%ms"] = string.format("%d", math.floor(endTime)),
+ ["%%mf"] = string.format("%s", endTime),
+ ["%%mT"] = string.sub(string.format("%.3f", endTime % 1), 3),
+ ["%%f"] = mp.get_property("filename"),
+ ["%%F"] = mp.get_property("filename/no-ext"),
+ ["%%s"] = seconds_to_path_element(startTime),
+ ["%%S"] = seconds_to_path_element(startTime, true),
+ ["%%e"] = seconds_to_path_element(endTime),
+ ["%%E"] = seconds_to_path_element(endTime, true),
+ ["%%T"] = mp.get_property("media-title"),
+ ["%%M"] = (mp.get_property_native('aid') and not mp.get_property_native('mute') and hasAudioCodec) and '-audio' or '',
+ ["%%R"] = (options.scale_height ~= -1) and "-" .. tostring(options.scale_height) .. "p" or "-" .. tostring(mp.get_property_native('height')) .. "p",
+ ["%%t%%"] = "%%"
+ }
+ local filename = options.output_template
+ for format, value in pairs(replaceFirst) do
+ local _
+ filename, _ = filename:gsub(format, value)
+ end
+ for format, value in pairs(replaceTable) do
+ local _
+ filename, _ = filename:gsub(format, value)
+ end
+ if mp.get_property_bool("demuxer-via-network", false) then
+ local _
+ filename, _ = filename:gsub("%%X{([^}]*)}", "%1")
+ filename, _ = filename:gsub("%%x", "")
+ else
+ local x = string.gsub(mp.get_property("stream-open-filename", ""), string.gsub(mp.get_property("filename", ""), "%W", "%%%1") .. "$", "")
+ local _
+ filename, _ = filename:gsub("%%X{[^}]*}", x)
+ filename, _ = filename:gsub("%%x", x)
+ end
+ filename = expand_properties(filename, "%")
+ for format in filename:gmatch("%%t([aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ])") do
+ local _
+ filename, _ = filename:gsub("%%t" .. format, os.date("%" .. format))
+ end
+ local _
+ filename, _ = filename:gsub("[<>:\"/\\|?*]", "")
+ return tostring(filename) .. "." .. tostring(videoFormat.outputExtension)
+end
+local parse_directory
+parse_directory = function(dir)
+ local home_dir = os.getenv("HOME")
+ if not home_dir then
+ home_dir = os.getenv("USERPROFILE")
+ end
+ if not home_dir then
+ local drive = os.getenv("HOMEDRIVE")
+ local path = os.getenv("HOMEPATH")
+ if drive and path then
+ home_dir = utils.join_path(drive, path)
+ else
+ msg.warn("Couldn't find home dir.")
+ home_dir = ""
+ end
+ end
+ local _
+ dir, _ = dir:gsub("^~", home_dir)
+ return dir
+end
+local is_windows = type(package) == "table" and type(package.config) == "string" and package.config:sub(1, 1) == "\\"
+local trim
+trim = function(s)
+ return s:match("^%s*(.-)%s*$")
+end
+local get_null_path
+get_null_path = function()
+ if file_exists("/dev/null") then
+ return "/dev/null"
+ end
+ return "NUL"
+end
+local run_subprocess
+run_subprocess = function(params)
+ local res = utils.subprocess(params)
+ msg.verbose("Command stdout: ")
+ msg.verbose(res.stdout)
+ if res.status ~= 0 then
+ msg.verbose("Command failed! Reason: ", res.error, " Killed by us? ", res.killed_by_us and "yes" or "no")
+ return false
+ end
+ return true
+end
+local shell_escape
+shell_escape = function(args)
+ local ret = { }
+ for i, a in ipairs(args) do
+ local s = tostring(a)
+ if string.match(s, "[^A-Za-z0-9_/:=-]") then
+ if is_windows then
+ s = '"' .. string.gsub(s, '"', '"\\""') .. '"'
+ else
+ s = "'" .. string.gsub(s, "'", "'\\''") .. "'"
+ end
+ end
+ table.insert(ret, s)
+ end
+ local concat = table.concat(ret, " ")
+ if is_windows then
+ concat = '"' .. concat .. '"'
+ end
+ return concat
+end
+local run_subprocess_popen
+run_subprocess_popen = function(command_line)
+ local command_line_string = shell_escape(command_line)
+ command_line_string = command_line_string .. " 2>&1"
+ msg.verbose("run_subprocess_popen: running " .. tostring(command_line_string))
+ return io.popen(command_line_string)
+end
+local calculate_scale_factor
+calculate_scale_factor = function()
+ local baseResY = 720
+ local osd_w, osd_h = mp.get_osd_size()
+ return osd_h / baseResY
+end
+local should_display_progress
+should_display_progress = function()
+ if options.display_progress == "auto" then
+ return not is_windows
+ end
+ return options.display_progress
+end
+local reverse
+reverse = function(list)
+ local _accum_0 = { }
+ local _len_0 = 1
+ local _max_0 = 1
+ for _index_0 = #list, _max_0 < 0 and #list + _max_0 or _max_0, -1 do
+ local element = list[_index_0]
+ _accum_0[_len_0] = element
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+end
+local get_pass_logfile_path
+get_pass_logfile_path = function(encode_out_path)
+ return tostring(encode_out_path) .. "-video-pass1.log"
+end
+local dimensions_changed = true
+local _video_dimensions = { }
+local get_video_dimensions
+get_video_dimensions = function()
+ if not (dimensions_changed) then
+ return _video_dimensions
+ end
+ local video_params = mp.get_property_native("video-out-params")
+ if not video_params then
+ return nil
+ end
+ dimensions_changed = false
+ local keep_aspect = mp.get_property_bool("keepaspect")
+ local w = video_params["w"]
+ local h = video_params["h"]
+ local dw = video_params["dw"]
+ local dh = video_params["dh"]
+ if mp.get_property_number("video-rotate") % 180 == 90 then
+ w, h = h, w
+ dw, dh = dh, dw
+ end
+ _video_dimensions = {
+ top_left = { },
+ bottom_right = { },
+ ratios = { }
+ }
+ local window_w, window_h = mp.get_osd_size()
+ if keep_aspect then
+ local unscaled = mp.get_property_native("video-unscaled")
+ local panscan = mp.get_property_number("panscan")
+ local fwidth = window_w
+ local fheight = math.floor(window_w / dw * dh)
+ if fheight > window_h or fheight < h then
+ local tmpw = math.floor(window_h / dh * dw)
+ if tmpw <= window_w then
+ fheight = window_h
+ fwidth = tmpw
+ end
+ end
+ local vo_panscan_area = window_h - fheight
+ local f_w = fwidth / fheight
+ local f_h = 1
+ if vo_panscan_area == 0 then
+ vo_panscan_area = window_h - fwidth
+ f_w = 1
+ f_h = fheight / fwidth
+ end
+ if unscaled or unscaled == "downscale-big" then
+ vo_panscan_area = 0
+ if unscaled or (dw <= window_w and dh <= window_h) then
+ fwidth = dw
+ fheight = dh
+ end
+ end
+ local scaled_width = fwidth + math.floor(vo_panscan_area * panscan * f_w)
+ local scaled_height = fheight + math.floor(vo_panscan_area * panscan * f_h)
+ local split_scaling
+ split_scaling = function(dst_size, scaled_src_size, zoom, align, pan)
+ scaled_src_size = math.floor(scaled_src_size * 2 ^ zoom)
+ align = (align + 1) / 2
+ local dst_start = math.floor((dst_size - scaled_src_size) * align + pan * scaled_src_size)
+ if dst_start < 0 then
+ dst_start = dst_start + 1
+ end
+ local dst_end = dst_start + scaled_src_size
+ if dst_start >= dst_end then
+ dst_start = 0
+ dst_end = 1
+ end
+ return dst_start, dst_end
+ end
+ local zoom = mp.get_property_number("video-zoom")
+ local align_x = mp.get_property_number("video-align-x")
+ local pan_x = mp.get_property_number("video-pan-x")
+ _video_dimensions.top_left.x, _video_dimensions.bottom_right.x = split_scaling(window_w, scaled_width, zoom, align_x, pan_x)
+ local align_y = mp.get_property_number("video-align-y")
+ local pan_y = mp.get_property_number("video-pan-y")
+ _video_dimensions.top_left.y, _video_dimensions.bottom_right.y = split_scaling(window_h, scaled_height, zoom, align_y, pan_y)
+ else
+ _video_dimensions.top_left.x = 0
+ _video_dimensions.bottom_right.x = window_w
+ _video_dimensions.top_left.y = 0
+ _video_dimensions.bottom_right.y = window_h
+ end
+ _video_dimensions.ratios.w = w / (_video_dimensions.bottom_right.x - _video_dimensions.top_left.x)
+ _video_dimensions.ratios.h = h / (_video_dimensions.bottom_right.y - _video_dimensions.top_left.y)
+ return _video_dimensions
+end
+local set_dimensions_changed
+set_dimensions_changed = function()
+ dimensions_changed = true
+end
+local monitor_dimensions
+monitor_dimensions = function()
+ local properties = {
+ "keepaspect",
+ "video-out-params",
+ "video-unscaled",
+ "panscan",
+ "video-zoom",
+ "video-align-x",
+ "video-pan-x",
+ "video-align-y",
+ "video-pan-y",
+ "osd-width",
+ "osd-height"
+ }
+ for _, p in ipairs(properties) do
+ mp.observe_property(p, "native", set_dimensions_changed)
+ end
+end
+local clamp
+clamp = function(min, val, max)
+ if val <= min then
+ return min
+ end
+ if val >= max then
+ return max
+ end
+ return val
+end
+local clamp_point
+clamp_point = function(top_left, point, bottom_right)
+ return {
+ x = clamp(top_left.x, point.x, bottom_right.x),
+ y = clamp(top_left.y, point.y, bottom_right.y)
+ }
+end
+local VideoPoint
+do
+ local _class_0
+ local _base_0 = {
+ set_from_screen = function(self, sx, sy)
+ local d = get_video_dimensions()
+ local point = clamp_point(d.top_left, {
+ x = sx,
+ y = sy
+ }, d.bottom_right)
+ self.x = math.floor(d.ratios.w * (point.x - d.top_left.x) + 0.5)
+ self.y = math.floor(d.ratios.h * (point.y - d.top_left.y) + 0.5)
+ end,
+ to_screen = function(self)
+ local d = get_video_dimensions()
+ return {
+ x = math.floor(self.x / d.ratios.w + d.top_left.x + 0.5),
+ y = math.floor(self.y / d.ratios.h + d.top_left.y + 0.5)
+ }
+ end
+ }
+ _base_0.__index = _base_0
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.x = -1
+ self.y = -1
+ end,
+ __base = _base_0,
+ __name = "VideoPoint"
+ }, {
+ __index = _base_0,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ VideoPoint = _class_0
+end
+local Region
+do
+ local _class_0
+ local _base_0 = {
+ is_valid = function(self)
+ return self.x > -1 and self.y > -1 and self.w > -1 and self.h > -1
+ end,
+ set_from_points = function(self, p1, p2)
+ self.x = math.min(p1.x, p2.x)
+ self.y = math.min(p1.y, p2.y)
+ self.w = math.abs(p1.x - p2.x)
+ self.h = math.abs(p1.y - p2.y)
+ end
+ }
+ _base_0.__index = _base_0
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.x = -1
+ self.y = -1
+ self.w = -1
+ self.h = -1
+ end,
+ __base = _base_0,
+ __name = "Region"
+ }, {
+ __index = _base_0,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ Region = _class_0
+end
+local make_fullscreen_region
+make_fullscreen_region = function()
+ local r = Region()
+ local d = get_video_dimensions()
+ local a = VideoPoint()
+ local b = VideoPoint()
+ local xa, ya
+ do
+ local _obj_0 = d.top_left
+ xa, ya = _obj_0.x, _obj_0.y
+ end
+ a:set_from_screen(xa, ya)
+ local xb, yb
+ do
+ local _obj_0 = d.bottom_right
+ xb, yb = _obj_0.x, _obj_0.y
+ end
+ b:set_from_screen(xb, yb)
+ r:set_from_points(a, b)
+ return r
+end
+local read_double
+read_double = function(bytes)
+ local sign = 1
+ local mantissa = bytes[2] % 2 ^ 4
+ for i = 3, 8 do
+ mantissa = mantissa * 256 + bytes[i]
+ end
+ if bytes[1] > 127 then
+ sign = -1
+ end
+ local exponent = (bytes[1] % 128) * 2 ^ 4 + math.floor(bytes[2] / 2 ^ 4)
+ if exponent == 0 then
+ return 0
+ end
+ mantissa = (math.ldexp(mantissa, -52) + 1) * sign
+ return math.ldexp(mantissa, exponent - 1023)
+end
+local write_double
+write_double = function(num)
+ local bytes = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ }
+ if num == 0 then
+ return bytes
+ end
+ local anum = math.abs(num)
+ local mantissa, exponent = math.frexp(anum)
+ exponent = exponent - 1
+ mantissa = mantissa * 2 - 1
+ local sign = num ~= anum and 128 or 0
+ exponent = exponent + 1023
+ bytes[1] = sign + math.floor(exponent / 2 ^ 4)
+ mantissa = mantissa * 2 ^ 4
+ local currentmantissa = math.floor(mantissa)
+ mantissa = mantissa - currentmantissa
+ bytes[2] = (exponent % 2 ^ 4) * 2 ^ 4 + currentmantissa
+ for i = 3, 8 do
+ mantissa = mantissa * 2 ^ 8
+ currentmantissa = math.floor(mantissa)
+ mantissa = mantissa - currentmantissa
+ bytes[i] = currentmantissa
+ end
+ return bytes
+end
+local FirstpassStats
+do
+ local _class_0
+ local duration_multiplier, fields_before_duration, fields_after_duration
+ local _base_0 = {
+ get_duration = function(self)
+ local big_endian_binary_duration = reverse(self.binary_duration)
+ return read_double(reversed_binary_duration) / duration_multiplier
+ end,
+ set_duration = function(self, duration)
+ local big_endian_binary_duration = write_double(duration * duration_multiplier)
+ self.binary_duration = reverse(big_endian_binary_duration)
+ end,
+ _bytes_to_string = function(self, bytes)
+ return string.char(unpack(bytes))
+ end,
+ as_binary_string = function(self)
+ local before_duration_string = self:_bytes_to_string(self.binary_data_before_duration)
+ local duration_string = self:_bytes_to_string(self.binary_duration)
+ local after_duration_string = self:_bytes_to_string(self.binary_data_after_duration)
+ return before_duration_string .. duration_string .. after_duration_string
+ end
+ }
+ _base_0.__index = _base_0
+ _class_0 = setmetatable({
+ __init = function(self, before_duration, duration, after_duration)
+ self.binary_data_before_duration = before_duration
+ self.binary_duration = duration
+ self.binary_data_after_duration = after_duration
+ end,
+ __base = _base_0,
+ __name = "FirstpassStats"
+ }, {
+ __index = _base_0,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ local self = _class_0
+ duration_multiplier = 10000000.0
+ fields_before_duration = 16
+ fields_after_duration = 1
+ self.data_before_duration_size = function(self)
+ return fields_before_duration * 8
+ end
+ self.data_after_duration_size = function(self)
+ return fields_after_duration * 8
+ end
+ self.size = function(self)
+ return (fields_before_duration + 1 + fields_after_duration) * 8
+ end
+ self.from_bytes = function(self, bytes)
+ local before_duration
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ local _max_0 = self:data_before_duration_size()
+ for _index_0 = 1, _max_0 < 0 and #bytes + _max_0 or _max_0 do
+ local b = bytes[_index_0]
+ _accum_0[_len_0] = b
+ _len_0 = _len_0 + 1
+ end
+ before_duration = _accum_0
+ end
+ local duration
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ local _max_0 = self:data_before_duration_size() + 8
+ for _index_0 = self:data_before_duration_size() + 1, _max_0 < 0 and #bytes + _max_0 or _max_0 do
+ local b = bytes[_index_0]
+ _accum_0[_len_0] = b
+ _len_0 = _len_0 + 1
+ end
+ duration = _accum_0
+ end
+ local after_duration
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = self:data_before_duration_size() + 8 + 1, #bytes do
+ local b = bytes[_index_0]
+ _accum_0[_len_0] = b
+ _len_0 = _len_0 + 1
+ end
+ after_duration = _accum_0
+ end
+ return self(before_duration, duration, after_duration)
+ end
+ FirstpassStats = _class_0
+end
+local read_logfile_into_stats_array
+read_logfile_into_stats_array = function(logfile_path)
+ local file = assert(io.open(logfile_path, "rb"))
+ local logfile_string = base64_decode(file:read())
+ file:close()
+ local stats_size = FirstpassStats:size()
+ assert(logfile_string:len() % stats_size == 0)
+ local stats = { }
+ for offset = 1, #logfile_string, stats_size do
+ local bytes = {
+ logfile_string:byte(offset, offset + stats_size - 1)
+ }
+ assert(#bytes == stats_size)
+ stats[#stats + 1] = FirstpassStats:from_bytes(bytes)
+ end
+ return stats
+end
+local write_stats_array_to_logfile
+write_stats_array_to_logfile = function(stats_array, logfile_path)
+ local file = assert(io.open(logfile_path, "wb"))
+ local logfile_string = ""
+ for _index_0 = 1, #stats_array do
+ local stat = stats_array[_index_0]
+ logfile_string = logfile_string .. stat:as_binary_string()
+ end
+ file:write(base64_encode(logfile_string))
+ return file:close()
+end
+local vp8_patch_logfile
+vp8_patch_logfile = function(logfile_path, encode_total_duration)
+ local stats_array = read_logfile_into_stats_array(logfile_path)
+ local average_duration = encode_total_duration / (#stats_array - 1)
+ for i = 1, #stats_array - 1 do
+ stats_array[i]:set_duration(average_duration)
+ end
+ stats_array[#stats_array]:set_duration(encode_total_duration)
+ return write_stats_array_to_logfile(stats_array, logfile_path)
+end
+local formats = { }
+local Format
+do
+ local _class_0
+ local _base_0 = {
+ getPreFilters = function(self)
+ return { }
+ end,
+ getPostFilters = function(self)
+ return { }
+ end,
+ getFlags = function(self)
+ return { }
+ end,
+ getCodecFlags = function(self)
+ local codecs = { }
+ if self.videoCodec ~= "" then
+ codecs[#codecs + 1] = "--ovc=" .. tostring(self.videoCodec)
+ end
+ if self.audioCodec ~= "" then
+ codecs[#codecs + 1] = "--oac=" .. tostring(self.audioCodec)
+ end
+ return codecs
+ end,
+ postCommandModifier = function(self, command, region, startTime, endTime)
+ return command
+ end
+ }
+ _base_0.__index = _base_0
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "Basic"
+ self.supportsTwopass = true
+ self.videoCodec = ""
+ self.audioCodec = ""
+ self.outputExtension = ""
+ self.acceptsBitrate = true
+ end,
+ __base = _base_0,
+ __name = "Format"
+ }, {
+ __index = _base_0,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ Format = _class_0
+end
+local RawVideo
+do
+ local _class_0
+ local _parent_0 = Format
+ local _base_0 = {
+ getColorspace = function(self)
+ local csp = mp.get_property("colormatrix")
+ local _exp_0 = csp
+ if "bt.601" == _exp_0 then
+ return "bt601"
+ elseif "bt.709" == _exp_0 then
+ return "bt709"
+ elseif "bt.2020" == _exp_0 then
+ return "bt2020"
+ elseif "smpte-240m" == _exp_0 then
+ return "smpte240m"
+ else
+ msg.info("Warning, unknown colorspace " .. tostring(csp) .. " detected, using bt.601.")
+ return "bt601"
+ end
+ end,
+ getPostFilters = function(self)
+ return {
+ "format=yuv444p16",
+ "lavfi-scale=in_color_matrix=" .. self:getColorspace(),
+ "format=bgr24"
+ }
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "Raw"
+ self.supportsTwopass = false
+ self.videoCodec = "rawvideo"
+ self.audioCodec = "pcm_s16le"
+ self.outputExtension = "avi"
+ self.acceptsBitrate = false
+ end,
+ __base = _base_0,
+ __name = "RawVideo",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ RawVideo = _class_0
+end
+formats["raw"] = RawVideo()
+local WebmVP8
+do
+ local _class_0
+ local _parent_0 = Format
+ local _base_0 = {
+ getPreFilters = function(self)
+ local colormatrixFilter = {
+ ["bt.709"] = "bt709",
+ ["bt.2020"] = "bt2020",
+ ["smpte-240m"] = "smpte240m"
+ }
+ local ret = { }
+ local colormatrix = mp.get_property_native("video-params/colormatrix")
+ if colormatrixFilter[colormatrix] then
+ append(ret, {
+ "lavfi-colormatrix=" .. tostring(colormatrixFilter[colormatrix]) .. ":bt601"
+ })
+ end
+ return ret
+ end,
+ getFlags = function(self)
+ return {
+ "--ovcopts-add=threads=" .. tostring(options.libvpx_threads),
+ "--ovcopts-add=auto-alt-ref=1",
+ "--ovcopts-add=lag-in-frames=25",
+ "--ovcopts-add=quality=good",
+ "--ovcopts-add=cpu-used=0"
+ }
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "WebM"
+ self.supportsTwopass = true
+ self.videoCodec = "libvpx"
+ self.audioCodec = "libvorbis"
+ self.outputExtension = "webm"
+ self.acceptsBitrate = true
+ end,
+ __base = _base_0,
+ __name = "WebmVP8",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ WebmVP8 = _class_0
+end
+formats["webm-vp8"] = WebmVP8()
+local WebmVP9
+do
+ local _class_0
+ local _parent_0 = Format
+ local _base_0 = {
+ getFlags = function(self)
+ return {
+ "--ovcopts-add=threads=" .. tostring(options.libvpx_threads)
+ }
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "WebM (VP9)"
+ self.supportsTwopass = false
+ self.videoCodec = "libvpx-vp9"
+ self.audioCodec = "libopus"
+ self.outputExtension = "webm"
+ self.acceptsBitrate = true
+ end,
+ __base = _base_0,
+ __name = "WebmVP9",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ WebmVP9 = _class_0
+end
+formats["webm-vp9"] = WebmVP9()
+local MP4
+do
+ local _class_0
+ local _parent_0 = Format
+ local _base_0 = { }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "MP4 (h264/AAC)"
+ self.supportsTwopass = true
+ self.videoCodec = "libx264"
+ self.audioCodec = "aac"
+ self.outputExtension = "mp4"
+ self.acceptsBitrate = true
+ end,
+ __base = _base_0,
+ __name = "MP4",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ MP4 = _class_0
+end
+formats["mp4"] = MP4()
+local MP4NVENC
+do
+ local _class_0
+ local _parent_0 = Format
+ local _base_0 = { }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "MP4 (h264-NVENC/AAC)"
+ self.supportsTwopass = true
+ self.videoCodec = "h264_nvenc"
+ self.audioCodec = "aac"
+ self.outputExtension = "mp4"
+ self.acceptsBitrate = true
+ end,
+ __base = _base_0,
+ __name = "MP4NVENC",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ MP4NVENC = _class_0
+end
+formats["mp4-nvenc"] = MP4NVENC()
+local MP3
+do
+ local _class_0
+ local _parent_0 = Format
+ local _base_0 = { }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "MP3 (libmp3lame)"
+ self.supportsTwopass = false
+ self.videoCodec = ""
+ self.audioCodec = "libmp3lame"
+ self.outputExtension = "mp3"
+ self.acceptsBitrate = true
+ end,
+ __base = _base_0,
+ __name = "MP3",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ MP3 = _class_0
+end
+formats["mp3"] = MP3()
+local GIF
+do
+ local _class_0
+ local _parent_0 = Format
+ local _base_0 = {
+ postCommandModifier = function(self, command, region, startTime, endTime)
+ local new_command = { }
+ local start_ts = seconds_to_time_string(startTime, false, true)
+ local end_ts = seconds_to_time_string(endTime, false, true)
+ start_ts = start_ts:gsub(":", "\\\\:")
+ end_ts = end_ts:gsub(":", "\\\\:")
+ local cfilter = "[vid1]trim=start=" .. tostring(start_ts) .. ":end=" .. tostring(end_ts) .. "[vidtmp];"
+ if mp.get_property("deinterlace") == "yes" then
+ cfilter = cfilter .. "[vidtmp]yadif=mode=1[vidtmp];"
+ end
+ for _, v in ipairs(command) do
+ local _continue_0 = false
+ repeat
+ if v:match("^%-%-vf%-add=lavfi%-scale") or v:match("^%-%-vf%-add=lavfi%-crop") or v:match("^%-%-vf%-add=fps") or v:match("^%-%-vf%-add=lavfi%-eq") then
+ local n = v:gsub("^%-%-vf%-add=", ""):gsub("^lavfi%-", "")
+ cfilter = cfilter .. "[vidtmp]" .. tostring(n) .. "[vidtmp];"
+ else
+ if v:match("^%-%-video%-rotate=90") then
+ cfilter = cfilter .. "[vidtmp]transpose=1[vidtmp];"
+ else
+ if v:match("^%-%-video%-rotate=270") then
+ cfilter = cfilter .. "[vidtmp]transpose=2[vidtmp];"
+ else
+ if v:match("^%-%-video%-rotate=180") then
+ cfilter = cfilter .. "[vidtmp]transpose=1[vidtmp];[vidtmp]transpose=1[vidtmp];"
+ else
+ if v:match("^%-%-deinterlace=") then
+ _continue_0 = true
+ break
+ else
+ append(new_command, {
+ v
+ })
+ _continue_0 = true
+ break
+ end
+ end
+ end
+ end
+ end
+ _continue_0 = true
+ until true
+ if not _continue_0 then
+ break
+ end
+ end
+ cfilter = cfilter .. "[vidtmp]split[topal][vidf];"
+ cfilter = cfilter .. "[topal]palettegen[pal];"
+ cfilter = cfilter .. "[vidf]fifo[vidf];"
+ if options.gif_dither == 6 then
+ cfilter = cfilter .. "[vidf][pal]paletteuse[vo]"
+ else
+ cfilter = cfilter .. "[vidf][pal]paletteuse=dither=bayer:bayer_scale=" .. tostring(options.gif_dither) .. ":diff_mode=rectangle[vo]"
+ end
+ append(new_command, {
+ "--lavfi-complex=" .. tostring(cfilter)
+ })
+ return new_command
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.displayName = "GIF"
+ self.supportsTwopass = false
+ self.videoCodec = "gif"
+ self.audioCodec = ""
+ self.outputExtension = "gif"
+ self.acceptsBitrate = false
+ end,
+ __base = _base_0,
+ __name = "GIF",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ GIF = _class_0
+end
+formats["gif"] = GIF()
+local Page
+do
+ local _class_0
+ local _base_0 = {
+ add_keybinds = function(self)
+ if not self.keybinds then
+ return
+ end
+ for key, func in pairs(self.keybinds) do
+ mp.add_forced_key_binding(key, key, func, {
+ repeatable = true
+ })
+ end
+ end,
+ remove_keybinds = function(self)
+ if not self.keybinds then
+ return
+ end
+ for key, _ in pairs(self.keybinds) do
+ mp.remove_key_binding(key)
+ end
+ end,
+ observe_properties = function(self)
+ self.sizeCallback = function()
+ return self:draw()
+ end
+ local properties = {
+ "keepaspect",
+ "video-out-params",
+ "video-unscaled",
+ "panscan",
+ "video-zoom",
+ "video-align-x",
+ "video-pan-x",
+ "video-align-y",
+ "video-pan-y",
+ "osd-width",
+ "osd-height"
+ }
+ for _index_0 = 1, #properties do
+ local p = properties[_index_0]
+ mp.observe_property(p, "native", self.sizeCallback)
+ end
+ end,
+ unobserve_properties = function(self)
+ if self.sizeCallback then
+ mp.unobserve_property(self.sizeCallback)
+ self.sizeCallback = nil
+ end
+ end,
+ clear = function(self)
+ local window_w, window_h = mp.get_osd_size()
+ mp.set_osd_ass(window_w, window_h, "")
+ return mp.osd_message("", 0)
+ end,
+ prepare = function(self)
+ return nil
+ end,
+ dispose = function(self)
+ return nil
+ end,
+ show = function(self)
+ if self.visible then
+ return
+ end
+ self.visible = true
+ self:observe_properties()
+ self:add_keybinds()
+ self:prepare()
+ self:clear()
+ return self:draw()
+ end,
+ hide = function(self)
+ if not self.visible then
+ return
+ end
+ self.visible = false
+ self:unobserve_properties()
+ self:remove_keybinds()
+ self:clear()
+ return self:dispose()
+ end,
+ setup_text = function(self, ass)
+ local scale = calculate_scale_factor()
+ local margin = options.margin * scale
+ ass:append("{\\an7}")
+ ass:pos(margin, margin)
+ return ass:append("{\\fs" .. tostring(options.font_size * scale) .. "}")
+ end
+ }
+ _base_0.__index = _base_0
+ _class_0 = setmetatable({
+ __init = function() end,
+ __base = _base_0,
+ __name = "Page"
+ }, {
+ __index = _base_0,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ Page = _class_0
+end
+local EncodeWithProgress
+do
+ local _class_0
+ local _parent_0 = Page
+ local _base_0 = {
+ draw = function(self)
+ local progress = 100 * ((self.currentTime - self.startTime) / self.duration)
+ local progressText = string.format("%d%%", progress)
+ local window_w, window_h = mp.get_osd_size()
+ local ass = assdraw.ass_new()
+ ass:new_event()
+ self:setup_text(ass)
+ ass:append("Encoding (" .. tostring(bold(progressText)) .. ")\\N")
+ return mp.set_osd_ass(window_w, window_h, ass.text)
+ end,
+ parseLine = function(self, line)
+ local matchTime = string.match(line, "Encode time[-]pos: ([0-9.]+)")
+ local matchExit = string.match(line, "Exiting... [(]([%a ]+)[)]")
+ if matchTime == nil and matchExit == nil then
+ return
+ end
+ if matchTime ~= nil and tonumber(matchTime) > self.currentTime then
+ self.currentTime = tonumber(matchTime)
+ end
+ if matchExit ~= nil then
+ self.finished = true
+ self.finishedReason = matchExit
+ end
+ end,
+ startEncode = function(self, command_line)
+ local copy_command_line
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #command_line do
+ local arg = command_line[_index_0]
+ _accum_0[_len_0] = arg
+ _len_0 = _len_0 + 1
+ end
+ copy_command_line = _accum_0
+ end
+ append(copy_command_line, {
+ '--term-status-msg=Encode time-pos: ${=time-pos}\\n'
+ })
+ self:show()
+ local processFd = run_subprocess_popen(copy_command_line)
+ for line in processFd:lines() do
+ msg.verbose(string.format('%q', line))
+ self:parseLine(line)
+ self:draw()
+ end
+ processFd:close()
+ self:hide()
+ if self.finishedReason == "End of file" then
+ return true
+ end
+ return false
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self, startTime, endTime)
+ self.startTime = startTime
+ self.endTime = endTime
+ self.duration = endTime - startTime
+ self.currentTime = startTime
+ end,
+ __base = _base_0,
+ __name = "EncodeWithProgress",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ EncodeWithProgress = _class_0
+end
+local get_active_tracks
+get_active_tracks = function()
+ local accepted = {
+ video = true,
+ audio = not mp.get_property_bool("mute"),
+ sub = mp.get_property_bool("sub-visibility")
+ }
+ local active = {
+ video = { },
+ audio = { },
+ sub = { }
+ }
+ for _, track in ipairs(mp.get_property_native("track-list")) do
+ if track["selected"] and accepted[track["type"]] then
+ local count = #active[track["type"]]
+ active[track["type"]][count + 1] = track
+ end
+ end
+ return active
+end
+local filter_tracks_supported_by_format
+filter_tracks_supported_by_format = function(active_tracks, format)
+ local has_video_codec = format.videoCodec ~= ""
+ local has_audio_codec = format.audioCodec ~= ""
+ local supported = {
+ video = has_video_codec and active_tracks["video"] or { },
+ audio = has_audio_codec and active_tracks["audio"] or { },
+ sub = has_video_codec and active_tracks["sub"] or { }
+ }
+ return supported
+end
+local append_track
+append_track = function(out, track)
+ local external_flag = {
+ ["audio"] = "audio-file",
+ ["sub"] = "sub-file"
+ }
+ local internal_flag = {
+ ["video"] = "vid",
+ ["audio"] = "aid",
+ ["sub"] = "sid"
+ }
+ if track['external'] and string.len(track['external-filename']) <= 2048 then
+ return append(out, {
+ "--" .. tostring(external_flag[track['type']]) .. "=" .. tostring(track['external-filename'])
+ })
+ else
+ return append(out, {
+ "--" .. tostring(internal_flag[track['type']]) .. "=" .. tostring(track['id'])
+ })
+ end
+end
+local append_audio_tracks
+append_audio_tracks = function(out, tracks)
+ local internal_tracks = { }
+ for _index_0 = 1, #tracks do
+ local track = tracks[_index_0]
+ if track['external'] then
+ append_track(out, track)
+ else
+ append(internal_tracks, {
+ track
+ })
+ end
+ end
+ if #internal_tracks > 1 then
+ local filter_string = ""
+ for _index_0 = 1, #internal_tracks do
+ local track = internal_tracks[_index_0]
+ filter_string = filter_string .. "[aid" .. tostring(track['id']) .. "]"
+ end
+ filter_string = filter_string .. "amix[ao]"
+ return append(out, {
+ "--lavfi-complex=" .. tostring(filter_string)
+ })
+ else
+ if #internal_tracks == 1 then
+ return append_track(out, internal_tracks[1])
+ end
+ end
+end
+local get_scale_filters
+get_scale_filters = function()
+ local filters = { }
+ if options.force_square_pixels then
+ append(filters, {
+ "lavfi-scale=iw*sar:ih"
+ })
+ end
+ if options.scale_height > 0 then
+ append(filters, {
+ "lavfi-scale=-2:" .. tostring(options.scale_height)
+ })
+ end
+ return filters
+end
+local get_fps_filters
+get_fps_filters = function()
+ if options.fps > 0 then
+ return {
+ "fps=" .. tostring(options.fps)
+ }
+ end
+ return { }
+end
+local get_contrast_brightness_and_saturation_filters
+get_contrast_brightness_and_saturation_filters = function()
+ local mpv_brightness = mp.get_property("brightness")
+ local mpv_contrast = mp.get_property("contrast")
+ local mpv_saturation = mp.get_property("saturation")
+ if mpv_brightness == 0 and mpv_contrast == 0 and mpv_saturation == 0 then
+ return { }
+ end
+ local eq_saturation = (mpv_saturation + 100) / 100.0
+ local eq_contrast = (mpv_contrast + 100) / 100.0
+ local eq_brightness = (mpv_brightness / 50.0 + eq_contrast - 1) / 2.0
+ return {
+ "lavfi-eq=contrast=" .. tostring(eq_contrast) .. ":saturation=" .. tostring(eq_saturation) .. ":brightness=" .. tostring(eq_brightness)
+ }
+end
+local append_property
+append_property = function(out, property_name, option_name)
+ option_name = option_name or property_name
+ local prop = mp.get_property(property_name)
+ if prop and prop ~= "" then
+ return append(out, {
+ "--" .. tostring(option_name) .. "=" .. tostring(prop)
+ })
+ end
+end
+local append_list_options
+append_list_options = function(out, property_name, option_prefix)
+ option_prefix = option_prefix or property_name
+ local prop = mp.get_property_native(property_name)
+ if prop then
+ for _index_0 = 1, #prop do
+ local value = prop[_index_0]
+ append(out, {
+ "--" .. tostring(option_prefix) .. "-append=" .. tostring(value)
+ })
+ end
+ end
+end
+local get_playback_options
+get_playback_options = function()
+ local ret = { }
+ append_property(ret, "sub-ass-override")
+ append_property(ret, "sub-ass-force-style")
+ append_property(ret, "sub-ass-vsfilter-aspect-compat")
+ append_property(ret, "sub-auto")
+ append_property(ret, "sub-delay")
+ append_property(ret, "video-rotate")
+ append_property(ret, "ytdl-format")
+ append_property(ret, "deinterlace")
+ return ret
+end
+local get_speed_flags
+get_speed_flags = function()
+ local ret = { }
+ local speed = mp.get_property_native("speed")
+ if speed ~= 1 then
+ append(ret, {
+ "--vf-add=setpts=PTS/" .. tostring(speed),
+ "--af-add=atempo=" .. tostring(speed),
+ "--sub-speed=1/" .. tostring(speed)
+ })
+ end
+ return ret
+end
+local get_metadata_flags
+get_metadata_flags = function()
+ local title = mp.get_property("filename/no-ext")
+ return {
+ "--oset-metadata=title=%" .. tostring(string.len(title)) .. "%" .. tostring(title)
+ }
+end
+local apply_current_filters
+apply_current_filters = function(filters)
+ local vf = mp.get_property_native("vf")
+ msg.verbose("apply_current_filters: got " .. tostring(#vf) .. " currently applied.")
+ for _index_0 = 1, #vf do
+ local _continue_0 = false
+ repeat
+ local filter = vf[_index_0]
+ msg.verbose("apply_current_filters: filter name: " .. tostring(filter['name']))
+ if filter["enabled"] == false then
+ _continue_0 = true
+ break
+ end
+ local str = filter["name"]
+ local params = filter["params"] or { }
+ for k, v in pairs(params) do
+ str = str .. ":" .. tostring(k) .. "=%" .. tostring(string.len(v)) .. "%" .. tostring(v)
+ end
+ append(filters, {
+ str
+ })
+ _continue_0 = true
+ until true
+ if not _continue_0 then
+ break
+ end
+ end
+end
+local get_video_filters
+get_video_filters = function(format, region)
+ local filters = { }
+ append(filters, format:getPreFilters())
+ if options.apply_current_filters then
+ apply_current_filters(filters)
+ end
+ if region and region:is_valid() then
+ append(filters, {
+ "lavfi-crop=" .. tostring(region.w) .. ":" .. tostring(region.h) .. ":" .. tostring(region.x) .. ":" .. tostring(region.y)
+ })
+ end
+ append(filters, get_scale_filters())
+ append(filters, get_fps_filters())
+ append(filters, get_contrast_brightness_and_saturation_filters())
+ append(filters, format:getPostFilters())
+ return filters
+end
+local get_video_encode_flags
+get_video_encode_flags = function(format, region)
+ local flags = { }
+ append(flags, get_playback_options())
+ local filters = get_video_filters(format, region)
+ for _index_0 = 1, #filters do
+ local f = filters[_index_0]
+ append(flags, {
+ "--vf-add=" .. tostring(f)
+ })
+ end
+ append(flags, get_speed_flags())
+ return flags
+end
+local calculate_bitrate
+calculate_bitrate = function(active_tracks, format, length)
+ if format.videoCodec == "" then
+ return nil, options.target_filesize * 8 / length
+ end
+ local video_kilobits = options.target_filesize * 8
+ local audio_kilobits = nil
+ local has_audio_track = #active_tracks["audio"] > 0
+ if options.strict_filesize_constraint and has_audio_track then
+ audio_kilobits = length * options.strict_audio_bitrate
+ video_kilobits = video_kilobits - audio_kilobits
+ end
+ local video_bitrate = math.floor(video_kilobits / length)
+ local audio_bitrate = audio_kilobits and math.floor(audio_kilobits / length) or nil
+ return video_bitrate, audio_bitrate
+end
+local find_path
+find_path = function(startTime, endTime)
+ local path = mp.get_property('path')
+ if not path then
+ return nil, nil, nil, nil, nil
+ end
+ local is_stream = not file_exists(path)
+ local is_temporary = false
+ if is_stream then
+ if mp.get_property('file-format') == 'hls' then
+ path = utils.join_path(parse_directory('~'), 'cache_dump.ts')
+ mp.command_native({
+ 'dump_cache',
+ seconds_to_time_string(startTime, false, true),
+ seconds_to_time_string(endTime + 5, false, true),
+ path
+ })
+ endTime = endTime - startTime
+ startTime = 0
+ is_temporary = true
+ end
+ end
+ return path, is_stream, is_temporary, startTime, endTime
+end
+local encode
+encode = function(region, startTime, endTime)
+ local format = formats[options.output_format]
+ local originalStartTime = startTime
+ local originalEndTime = endTime
+ local path, is_stream, is_temporary
+ path, is_stream, is_temporary, startTime, endTime = find_path(startTime, endTime)
+ if not path then
+ message("No file is being played")
+ return
+ end
+ local command = {
+ "mpv",
+ path,
+ "--start=" .. seconds_to_time_string(startTime, false, true),
+ "--end=" .. seconds_to_time_string(endTime, false, true),
+ "--loop-file=no",
+ "--no-pause"
+ }
+ append(command, format:getCodecFlags())
+ local active_tracks = get_active_tracks()
+ local supported_active_tracks = filter_tracks_supported_by_format(active_tracks, format)
+ for track_type, tracks in pairs(supported_active_tracks) do
+ if track_type == "audio" then
+ append_audio_tracks(command, tracks)
+ else
+ for _index_0 = 1, #tracks do
+ local track = tracks[_index_0]
+ append_track(command, track)
+ end
+ end
+ end
+ for track_type, tracks in pairs(supported_active_tracks) do
+ local _continue_0 = false
+ repeat
+ if #tracks > 0 then
+ _continue_0 = true
+ break
+ end
+ local _exp_0 = track_type
+ if "video" == _exp_0 then
+ append(command, {
+ "--vid=no"
+ })
+ elseif "audio" == _exp_0 then
+ append(command, {
+ "--aid=no"
+ })
+ elseif "sub" == _exp_0 then
+ append(command, {
+ "--sid=no"
+ })
+ end
+ _continue_0 = true
+ until true
+ if not _continue_0 then
+ break
+ end
+ end
+ if format.videoCodec ~= "" then
+ append(command, get_video_encode_flags(format, region))
+ end
+ append(command, format:getFlags())
+ if options.write_filename_on_metadata then
+ append(command, get_metadata_flags())
+ end
+ if format.acceptsBitrate then
+ if options.target_filesize > 0 then
+ local length = endTime - startTime
+ local video_bitrate, audio_bitrate = calculate_bitrate(supported_active_tracks, format, length)
+ if video_bitrate then
+ append(command, {
+ "--ovcopts-add=b=" .. tostring(video_bitrate) .. "k"
+ })
+ end
+ if audio_bitrate then
+ append(command, {
+ "--oacopts-add=b=" .. tostring(audio_bitrate) .. "k"
+ })
+ end
+ if options.strict_filesize_constraint then
+ local type = format.videoCodec ~= "" and "ovc" or "oac"
+ append(command, {
+ "--" .. tostring(type) .. "opts-add=minrate=" .. tostring(bitrate) .. "k",
+ "--" .. tostring(type) .. "opts-add=maxrate=" .. tostring(bitrate) .. "k"
+ })
+ end
+ else
+ local type = format.videoCodec ~= "" and "ovc" or "oac"
+ append(command, {
+ "--" .. tostring(type) .. "opts-add=b=0"
+ })
+ end
+ end
+ for token in string.gmatch(options.additional_flags, "[^%s]+") do
+ command[#command + 1] = token
+ end
+ if not options.strict_filesize_constraint then
+ for token in string.gmatch(options.non_strict_additional_flags, "[^%s]+") do
+ command[#command + 1] = token
+ end
+ if options.crf >= 0 then
+ append(command, {
+ "--ovcopts-add=crf=" .. tostring(options.crf)
+ })
+ end
+ end
+ local dir = ""
+ if is_stream then
+ dir = parse_directory("~")
+ else
+ local _
+ dir, _ = utils.split_path(path)
+ end
+ if options.output_directory ~= "" then
+ dir = parse_directory(options.output_directory)
+ end
+ local formatted_filename = format_filename(originalStartTime, originalEndTime, format)
+ local out_path = utils.join_path(dir, formatted_filename)
+ append(command, {
+ "--o=" .. tostring(out_path)
+ })
+ emit_event("encode-started")
+ if options.twopass and format.supportsTwopass and not is_stream then
+ local first_pass_cmdline
+ do
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #command do
+ local arg = command[_index_0]
+ _accum_0[_len_0] = arg
+ _len_0 = _len_0 + 1
+ end
+ first_pass_cmdline = _accum_0
+ end
+ append(first_pass_cmdline, {
+ "--ovcopts-add=flags=+pass1"
+ })
+ message("Starting first pass...")
+ msg.verbose("First-pass command line: ", table.concat(first_pass_cmdline, " "))
+ local res = run_subprocess({
+ args = first_pass_cmdline,
+ cancellable = false
+ })
+ if not res then
+ message("First pass failed! Check the logs for details.")
+ emit_event("encode-finished", "fail")
+ return
+ end
+ append(command, {
+ "--ovcopts-add=flags=+pass2"
+ })
+ if format.videoCodec == "libvpx" then
+ msg.verbose("Patching libvpx pass log file...")
+ vp8_patch_logfile(get_pass_logfile_path(out_path), endTime - startTime)
+ end
+ end
+ command = format:postCommandModifier(command, region, startTime, endTime)
+ msg.info("Encoding to", out_path)
+ msg.verbose("Command line:", table.concat(command, " "))
+ if options.run_detached then
+ message("Started encode, process was detached.")
+ return utils.subprocess_detached({
+ args = command
+ })
+ else
+ local res = false
+ if not should_display_progress() then
+ message("Started encode...")
+ res = run_subprocess({
+ args = command,
+ cancellable = false
+ })
+ else
+ local ewp = EncodeWithProgress(startTime, endTime)
+ res = ewp:startEncode(command)
+ end
+ if res then
+ message("Encoded successfully! Saved to\\N" .. tostring(bold(out_path)))
+ emit_event("encode-finished", "success")
+ else
+ message("Encode failed! Check the logs for details.")
+ emit_event("encode-finished", "fail")
+ end
+ os.remove(get_pass_logfile_path(out_path))
+ if is_temporary then
+ return os.remove(path)
+ end
+ end
+end
+local CropPage
+do
+ local _class_0
+ local _parent_0 = Page
+ local _base_0 = {
+ reset = function(self)
+ local dimensions = get_video_dimensions()
+ local xa, ya
+ do
+ local _obj_0 = dimensions.top_left
+ xa, ya = _obj_0.x, _obj_0.y
+ end
+ self.pointA:set_from_screen(xa, ya)
+ local xb, yb
+ do
+ local _obj_0 = dimensions.bottom_right
+ xb, yb = _obj_0.x, _obj_0.y
+ end
+ self.pointB:set_from_screen(xb, yb)
+ if self.visible then
+ return self:draw()
+ end
+ end,
+ setPointA = function(self)
+ local posX, posY = mp.get_mouse_pos()
+ self.pointA:set_from_screen(posX, posY)
+ if self.visible then
+ return self:draw()
+ end
+ end,
+ setPointB = function(self)
+ local posX, posY = mp.get_mouse_pos()
+ self.pointB:set_from_screen(posX, posY)
+ if self.visible then
+ return self:draw()
+ end
+ end,
+ cancel = function(self)
+ self:hide()
+ return self.callback(false, nil)
+ end,
+ finish = function(self)
+ local region = Region()
+ region:set_from_points(self.pointA, self.pointB)
+ self:hide()
+ return self.callback(true, region)
+ end,
+ draw_box = function(self, ass)
+ local region = Region()
+ region:set_from_points(self.pointA:to_screen(), self.pointB:to_screen())
+ local d = get_video_dimensions()
+ ass:new_event()
+ ass:append("{\\an7}")
+ ass:pos(0, 0)
+ ass:append('{\\bord0}')
+ ass:append('{\\shad0}')
+ ass:append('{\\c&H000000&}')
+ ass:append('{\\alpha&H77}')
+ ass:draw_start()
+ ass:rect_cw(d.top_left.x, d.top_left.y, region.x, region.y + region.h)
+ ass:rect_cw(region.x, d.top_left.y, d.bottom_right.x, region.y)
+ ass:rect_cw(d.top_left.x, region.y + region.h, region.x + region.w, d.bottom_right.y)
+ ass:rect_cw(region.x + region.w, region.y, d.bottom_right.x, d.bottom_right.y)
+ return ass:draw_stop()
+ end,
+ draw = function(self)
+ local window = { }
+ window.w, window.h = mp.get_osd_size()
+ local ass = assdraw.ass_new()
+ self:draw_box(ass)
+ ass:new_event()
+ self:setup_text(ass)
+ ass:append(tostring(bold('Crop:')) .. "\\N")
+ ass:append(tostring(bold('1:')) .. " change point A (" .. tostring(self.pointA.x) .. ", " .. tostring(self.pointA.y) .. ")\\N")
+ ass:append(tostring(bold('2:')) .. " change point B (" .. tostring(self.pointB.x) .. ", " .. tostring(self.pointB.y) .. ")\\N")
+ ass:append(tostring(bold('r:')) .. " reset to whole screen\\N")
+ ass:append(tostring(bold('ESC:')) .. " cancel crop\\N")
+ local width, height = math.abs(self.pointA.x - self.pointB.x), math.abs(self.pointA.y - self.pointB.y)
+ ass:append(tostring(bold('ENTER:')) .. " confirm crop (" .. tostring(width) .. "x" .. tostring(height) .. ")\\N")
+ return mp.set_osd_ass(window.w, window.h, ass.text)
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self, callback, region)
+ self.pointA = VideoPoint()
+ self.pointB = VideoPoint()
+ self.keybinds = {
+ ["1"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.setPointA
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["2"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.setPointB
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["r"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.reset
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["ESC"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.cancel
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["ENTER"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.finish
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)()
+ }
+ self:reset()
+ self.callback = callback
+ if region and region:is_valid() then
+ self.pointA.x = region.x
+ self.pointA.y = region.y
+ self.pointB.x = region.x + region.w
+ self.pointB.y = region.y + region.h
+ end
+ end,
+ __base = _base_0,
+ __name = "CropPage",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ CropPage = _class_0
+end
+local Option
+do
+ local _class_0
+ local _base_0 = {
+ hasPrevious = function(self)
+ local _exp_0 = self.optType
+ if "bool" == _exp_0 then
+ return true
+ elseif "int" == _exp_0 then
+ if self.opts.min then
+ return self.value > self.opts.min
+ else
+ return true
+ end
+ elseif "list" == _exp_0 then
+ return self.value > 1
+ end
+ end,
+ hasNext = function(self)
+ local _exp_0 = self.optType
+ if "bool" == _exp_0 then
+ return true
+ elseif "int" == _exp_0 then
+ if self.opts.max then
+ return self.value < self.opts.max
+ else
+ return true
+ end
+ elseif "list" == _exp_0 then
+ return self.value < #self.opts.possibleValues
+ end
+ end,
+ leftKey = function(self)
+ local _exp_0 = self.optType
+ if "bool" == _exp_0 then
+ self.value = not self.value
+ elseif "int" == _exp_0 then
+ self.value = self.value - self.opts.step
+ if self.opts.min and self.opts.min > self.value then
+ self.value = self.opts.min
+ end
+ elseif "list" == _exp_0 then
+ if self.value > 1 then
+ self.value = self.value - 1
+ end
+ end
+ end,
+ rightKey = function(self)
+ local _exp_0 = self.optType
+ if "bool" == _exp_0 then
+ self.value = not self.value
+ elseif "int" == _exp_0 then
+ self.value = self.value + self.opts.step
+ if self.opts.max and self.opts.max < self.value then
+ self.value = self.opts.max
+ end
+ elseif "list" == _exp_0 then
+ if self.value < #self.opts.possibleValues then
+ self.value = self.value + 1
+ end
+ end
+ end,
+ getValue = function(self)
+ local _exp_0 = self.optType
+ if "bool" == _exp_0 then
+ return self.value
+ elseif "int" == _exp_0 then
+ return self.value
+ elseif "list" == _exp_0 then
+ local value, _
+ do
+ local _obj_0 = self.opts.possibleValues[self.value]
+ value, _ = _obj_0[1], _obj_0[2]
+ end
+ return value
+ end
+ end,
+ setValue = function(self, value)
+ local _exp_0 = self.optType
+ if "bool" == _exp_0 then
+ self.value = value
+ elseif "int" == _exp_0 then
+ self.value = value
+ elseif "list" == _exp_0 then
+ local set = false
+ for i, possiblePair in ipairs(self.opts.possibleValues) do
+ local possibleValue, _
+ possibleValue, _ = possiblePair[1], possiblePair[2]
+ if possibleValue == value then
+ set = true
+ self.value = i
+ break
+ end
+ end
+ if not set then
+ return msg.warn("Tried to set invalid value " .. tostring(value) .. " to " .. tostring(self.displayText) .. " option.")
+ end
+ end
+ end,
+ getDisplayValue = function(self)
+ local _exp_0 = self.optType
+ if "bool" == _exp_0 then
+ return self.value and "yes" or "no"
+ elseif "int" == _exp_0 then
+ if self.opts.altDisplayNames and self.opts.altDisplayNames[self.value] then
+ return self.opts.altDisplayNames[self.value]
+ else
+ return tostring(self.value)
+ end
+ elseif "list" == _exp_0 then
+ local value, displayValue
+ do
+ local _obj_0 = self.opts.possibleValues[self.value]
+ value, displayValue = _obj_0[1], _obj_0[2]
+ end
+ return displayValue or value
+ end
+ end,
+ draw = function(self, ass, selected)
+ if selected then
+ ass:append(tostring(bold(self.displayText)) .. ": ")
+ else
+ ass:append(tostring(self.displayText) .. ": ")
+ end
+ if self:hasPrevious() then
+ ass:append("◀ ")
+ end
+ ass:append(self:getDisplayValue())
+ if self:hasNext() then
+ ass:append(" ▶")
+ end
+ return ass:append("\\N")
+ end,
+ optVisible = function(self)
+ if self.visibleCheckFn == nil then
+ return true
+ else
+ return self.visibleCheckFn()
+ end
+ end
+ }
+ _base_0.__index = _base_0
+ _class_0 = setmetatable({
+ __init = function(self, optType, displayText, value, opts, visibleCheckFn)
+ self.optType = optType
+ self.displayText = displayText
+ self.opts = opts
+ self.value = 1
+ self.visibleCheckFn = visibleCheckFn
+ return self:setValue(value)
+ end,
+ __base = _base_0,
+ __name = "Option"
+ }, {
+ __index = _base_0,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ Option = _class_0
+end
+local EncodeOptionsPage
+do
+ local _class_0
+ local _parent_0 = Page
+ local _base_0 = {
+ getCurrentOption = function(self)
+ return self.options[self.currentOption][2]
+ end,
+ leftKey = function(self)
+ (self:getCurrentOption()):leftKey()
+ return self:draw()
+ end,
+ rightKey = function(self)
+ (self:getCurrentOption()):rightKey()
+ return self:draw()
+ end,
+ prevOpt = function(self)
+ for i = self.currentOption - 1, 1, -1 do
+ if self.options[i][2]:optVisible() then
+ self.currentOption = i
+ break
+ end
+ end
+ return self:draw()
+ end,
+ nextOpt = function(self)
+ for i = self.currentOption + 1, #self.options do
+ if self.options[i][2]:optVisible() then
+ self.currentOption = i
+ break
+ end
+ end
+ return self:draw()
+ end,
+ confirmOpts = function(self)
+ for _, optPair in ipairs(self.options) do
+ local optName, opt
+ optName, opt = optPair[1], optPair[2]
+ options[optName] = opt:getValue()
+ end
+ self:hide()
+ return self.callback(true)
+ end,
+ cancelOpts = function(self)
+ self:hide()
+ return self.callback(false)
+ end,
+ draw = function(self)
+ local window_w, window_h = mp.get_osd_size()
+ local ass = assdraw.ass_new()
+ ass:new_event()
+ self:setup_text(ass)
+ ass:append(tostring(bold('Options:')) .. "\\N\\N")
+ for i, optPair in ipairs(self.options) do
+ local opt = optPair[2]
+ if opt:optVisible() then
+ opt:draw(ass, self.currentOption == i)
+ end
+ end
+ ass:append("\\N▲ / ▼: navigate\\N")
+ ass:append(tostring(bold('ENTER:')) .. " confirm options\\N")
+ ass:append(tostring(bold('ESC:')) .. " cancel\\N")
+ return mp.set_osd_ass(window_w, window_h, ass.text)
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self, callback)
+ self.callback = callback
+ self.currentOption = 1
+ local scaleHeightOpts = {
+ possibleValues = {
+ {
+ -1,
+ "no"
+ },
+ {
+ 144
+ },
+ {
+ 240
+ },
+ {
+ 360
+ },
+ {
+ 480
+ },
+ {
+ 540
+ },
+ {
+ 720
+ },
+ {
+ 1080
+ },
+ {
+ 1440
+ },
+ {
+ 2160
+ }
+ }
+ }
+ local filesizeOpts = {
+ step = 250,
+ min = 0,
+ altDisplayNames = {
+ [0] = "0 (constant quality)"
+ }
+ }
+ local crfOpts = {
+ step = 1,
+ min = -1,
+ altDisplayNames = {
+ [-1] = "disabled"
+ }
+ }
+ local fpsOpts = {
+ possibleValues = {
+ {
+ -1,
+ "source"
+ },
+ {
+ 15
+ },
+ {
+ 24
+ },
+ {
+ 30
+ },
+ {
+ 48
+ },
+ {
+ 50
+ },
+ {
+ 60
+ },
+ {
+ 120
+ },
+ {
+ 240
+ }
+ }
+ }
+ local formatIds = {
+ "webm-vp8",
+ "webm-vp9",
+ "mp4",
+ "mp4-nvenc",
+ "raw",
+ "mp3",
+ "gif"
+ }
+ local formatOpts = {
+ possibleValues = (function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #formatIds do
+ local fId = formatIds[_index_0]
+ _accum_0[_len_0] = {
+ fId,
+ formats[fId].displayName
+ }
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)()
+ }
+ local gifDitherOpts = {
+ possibleValues = {
+ {
+ 0,
+ "bayer_scale 0"
+ },
+ {
+ 1,
+ "bayer_scale 1"
+ },
+ {
+ 2,
+ "bayer_scale 2"
+ },
+ {
+ 3,
+ "bayer_scale 3"
+ },
+ {
+ 4,
+ "bayer_scale 4"
+ },
+ {
+ 5,
+ "bayer_scale 5"
+ },
+ {
+ 6,
+ "sierra2_4a"
+ }
+ }
+ }
+ self.options = {
+ {
+ "output_format",
+ Option("list", "Output Format", options.output_format, formatOpts)
+ },
+ {
+ "twopass",
+ Option("bool", "Two Pass", options.twopass)
+ },
+ {
+ "apply_current_filters",
+ Option("bool", "Apply Current Video Filters", options.apply_current_filters)
+ },
+ {
+ "scale_height",
+ Option("list", "Scale Height", options.scale_height, scaleHeightOpts)
+ },
+ {
+ "strict_filesize_constraint",
+ Option("bool", "Strict Filesize Constraint", options.strict_filesize_constraint)
+ },
+ {
+ "write_filename_on_metadata",
+ Option("bool", "Write Filename on Metadata", options.write_filename_on_metadata)
+ },
+ {
+ "target_filesize",
+ Option("int", "Target Filesize", options.target_filesize, filesizeOpts)
+ },
+ {
+ "crf",
+ Option("int", "CRF", options.crf, crfOpts)
+ },
+ {
+ "fps",
+ Option("list", "FPS", options.fps, fpsOpts)
+ },
+ {
+ "gif_dither",
+ Option("list", "GIF Dither Type", options.gif_dither, gifDitherOpts, function()
+ return self.options[1][2]:getValue() == "gif"
+ end)
+ },
+ {
+ "force_square_pixels",
+ Option("bool", "Force Square Pixels", options.force_square_pixels)
+ }
+ }
+ self.keybinds = {
+ ["LEFT"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.leftKey
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["RIGHT"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.rightKey
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["UP"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.prevOpt
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["DOWN"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.nextOpt
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["ENTER"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.confirmOpts
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["ESC"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.cancelOpts
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)()
+ }
+ end,
+ __base = _base_0,
+ __name = "EncodeOptionsPage",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ EncodeOptionsPage = _class_0
+end
+local PreviewPage
+do
+ local _class_0
+ local _parent_0 = Page
+ local _base_0 = {
+ prepare = function(self)
+ local vf = mp.get_property_native("vf")
+ vf[#vf + 1] = {
+ name = "sub"
+ }
+ if self.region:is_valid() then
+ vf[#vf + 1] = {
+ name = "crop",
+ params = {
+ w = tostring(self.region.w),
+ h = tostring(self.region.h),
+ x = tostring(self.region.x),
+ y = tostring(self.region.y)
+ }
+ }
+ end
+ mp.set_property_native("vf", vf)
+ if self.startTime > -1 and self.endTime > -1 then
+ mp.set_property_native("ab-loop-a", self.startTime)
+ mp.set_property_native("ab-loop-b", self.endTime)
+ mp.set_property_native("time-pos", self.startTime)
+ end
+ return mp.set_property_native("pause", false)
+ end,
+ dispose = function(self)
+ mp.set_property("ab-loop-a", "no")
+ mp.set_property("ab-loop-b", "no")
+ for prop, value in pairs(self.originalProperties) do
+ mp.set_property_native(prop, value)
+ end
+ end,
+ draw = function(self)
+ local window_w, window_h = mp.get_osd_size()
+ local ass = assdraw.ass_new()
+ ass:new_event()
+ self:setup_text(ass)
+ ass:append("Press " .. tostring(bold('ESC')) .. " to exit preview.\\N")
+ return mp.set_osd_ass(window_w, window_h, ass.text)
+ end,
+ cancel = function(self)
+ self:hide()
+ return self.callback()
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self, callback, region, startTime, endTime)
+ self.callback = callback
+ self.originalProperties = {
+ ["vf"] = mp.get_property_native("vf"),
+ ["time-pos"] = mp.get_property_native("time-pos"),
+ ["pause"] = mp.get_property_native("pause")
+ }
+ self.keybinds = {
+ ["ESC"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.cancel
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)()
+ }
+ self.region = region
+ self.startTime = startTime
+ self.endTime = endTime
+ self.isLoop = false
+ end,
+ __base = _base_0,
+ __name = "PreviewPage",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ PreviewPage = _class_0
+end
+local MainPage
+do
+ local _class_0
+ local _parent_0 = Page
+ local _base_0 = {
+ setStartTime = function(self)
+ self.startTime = mp.get_property_number("time-pos")
+ if self.visible then
+ self:clear()
+ return self:draw()
+ end
+ end,
+ setEndTime = function(self)
+ self.endTime = mp.get_property_number("time-pos")
+ if self.visible then
+ self:clear()
+ return self:draw()
+ end
+ end,
+ setupStartAndEndTimes = function(self)
+ if mp.get_property_native("duration") then
+ self.startTime = 0
+ self.endTime = mp.get_property_native("duration")
+ else
+ self.startTime = -1
+ self.endTime = -1
+ end
+ if self.visible then
+ self:clear()
+ return self:draw()
+ end
+ end,
+ draw = function(self)
+ local window_w, window_h = mp.get_osd_size()
+ local ass = assdraw.ass_new()
+ ass:new_event()
+ self:setup_text(ass)
+ ass:append(tostring(bold('WebM maker')) .. "\\N\\N")
+ ass:append(tostring(bold('c:')) .. " crop\\N")
+ ass:append(tostring(bold('1:')) .. " set start time (current is " .. tostring(seconds_to_time_string(self.startTime)) .. ")\\N")
+ ass:append(tostring(bold('2:')) .. " set end time (current is " .. tostring(seconds_to_time_string(self.endTime)) .. ")\\N")
+ ass:append(tostring(bold('o:')) .. " change encode options\\N")
+ ass:append(tostring(bold('p:')) .. " preview\\N")
+ ass:append(tostring(bold('e:')) .. " encode\\N\\N")
+ ass:append(tostring(bold('ESC:')) .. " close\\N")
+ return mp.set_osd_ass(window_w, window_h, ass.text)
+ end,
+ show = function(self)
+ _class_0.__parent.show(self)
+ return emit_event("show-main-page")
+ end,
+ onUpdateCropRegion = function(self, updated, newRegion)
+ if updated then
+ self.region = newRegion
+ end
+ return self:show()
+ end,
+ crop = function(self)
+ self:hide()
+ local cropPage = CropPage((function()
+ local _base_1 = self
+ local _fn_0 = _base_1.onUpdateCropRegion
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(), self.region)
+ return cropPage:show()
+ end,
+ onOptionsChanged = function(self, updated)
+ return self:show()
+ end,
+ changeOptions = function(self)
+ self:hide()
+ local encodeOptsPage = EncodeOptionsPage((function()
+ local _base_1 = self
+ local _fn_0 = _base_1.onOptionsChanged
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)())
+ return encodeOptsPage:show()
+ end,
+ onPreviewEnded = function(self)
+ return self:show()
+ end,
+ preview = function(self)
+ self:hide()
+ local previewPage = PreviewPage((function()
+ local _base_1 = self
+ local _fn_0 = _base_1.onPreviewEnded
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(), self.region, self.startTime, self.endTime)
+ return previewPage:show()
+ end,
+ encode = function(self)
+ self:hide()
+ if self.startTime < 0 then
+ message("No start time, aborting")
+ return
+ end
+ if self.endTime < 0 then
+ message("No end time, aborting")
+ return
+ end
+ if self.startTime >= self.endTime then
+ message("Start time is ahead of end time, aborting")
+ return
+ end
+ return encode(self.region, self.startTime, self.endTime)
+ end
+ }
+ _base_0.__index = _base_0
+ setmetatable(_base_0, _parent_0.__base)
+ _class_0 = setmetatable({
+ __init = function(self)
+ self.keybinds = {
+ ["c"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.crop
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["1"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.setStartTime
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["2"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.setEndTime
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["o"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.changeOptions
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["p"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.preview
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["e"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.encode
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)(),
+ ["ESC"] = (function()
+ local _base_1 = self
+ local _fn_0 = _base_1.hide
+ return function(...)
+ return _fn_0(_base_1, ...)
+ end
+ end)()
+ }
+ self.startTime = -1
+ self.endTime = -1
+ self.region = Region()
+ end,
+ __base = _base_0,
+ __name = "MainPage",
+ __parent = _parent_0
+ }, {
+ __index = function(cls, name)
+ local val = rawget(_base_0, name)
+ if val == nil then
+ local parent = rawget(cls, "__parent")
+ if parent then
+ return parent[name]
+ end
+ else
+ return val
+ end
+ end,
+ __call = function(cls, ...)
+ local _self_0 = setmetatable({}, _base_0)
+ cls.__init(_self_0, ...)
+ return _self_0
+ end
+ })
+ _base_0.__class = _class_0
+ if _parent_0.__inherited then
+ _parent_0.__inherited(_parent_0, _class_0)
+ end
+ MainPage = _class_0
+end
+monitor_dimensions()
+local mainPage = MainPage()
+mp.add_key_binding(options.keybind, "display-webm-encoder", (function()
+ local _base_0 = mainPage
+ local _fn_0 = _base_0.show
+ return function(...)
+ return _fn_0(_base_0, ...)
+ end
+end)(), {
+ repeatable = false
+})
+mp.register_event("file-loaded", (function()
+ local _base_0 = mainPage
+ local _fn_0 = _base_0.setupStartAndEndTimes
+ return function(...)
+ return _fn_0(_base_0, ...)
+ end
+end)())
+msg.verbose("Loaded mpv-webm script!")
+return emit_event("script-loaded")
diff --git a/ncmpcpp/config b/ncmpcpp/config
new file mode 100644
index 0000000..e143cc8
--- /dev/null
+++ b/ncmpcpp/config
@@ -0,0 +1,76 @@
+[mpd]
+ncmpcpp_directory = ~/.config/ncmpcpp
+lyrics_directory = ~/.config/ncmpcpp/lyrics
+mpd_host = localhost
+mpd_port = 6600
+mpd_music_dir = /home/monoblanco/stf/music
+mpd_crossfade_time = "10"
+system_encoding = "utf8"
+
+visualizer_look = " "
+startup_screen = visualizer
+startup_slave_screen = playlist
+startup_slave_screen_focus = yes
+locked_screen_width_part = 30
+
+[playlist]
+playlist_display_mode = "classic" (classic/columns)
+song_list_format = {{%a - %t}|{%f}}{$R%l}
+song_columns_list_format = "$L (30)[]{t} (30)[]{a} (5)[]{l} "
+
+playlist_show_remaining_time = "no"
+playlist_shorten_total_times = no
+playlist_show_mpd_host = no
+header_visibility = no
+
+[statusbar]
+progressbar_look = "─░─"
+progressbar_color = yellow:b
+statusbar_visibility = no
+statusbar_color = default
+song_status_format = {{%a{ "%b"{ (%y)}} - }{%t}}|{%f}
+
+[library]
+#song_library_format = {%n - }{%t}|{%f}
+song_library_format = "{{%a - %t}|{%f}}{$R%l}"
+
+empty_tag_color = cyan
+alternative_header_first_line_format = $b$7$aqqu$/a$9 {%t}|{%f} $7$atqq$/a$9$/b
+alternative_header_second_line_format = {{$7$b%a$/b$9}{ - $5%b$9}{ ($4%y$9)}}|{%D}
+current_item_inactive_column_prefix = $(white)$r
+current_item_inactive_column_suffix = $/r$(end)
+browser_playlist_prefix = "$2playlist$9 "
+selected_item_prefix = $1
+selected_item_suffix = $1
+modified_item_prefix = $3> $9
+
+now_playing_prefix = "$b$2$7 "
+now_playing_suffix = " $/b$8"
+current_item_prefix = "$b$7$/b$3 "
+current_item_suffix = " $8"
+
+
+[global]
+colors_enabled = yes
+main_window_color = cyan
+header_window_color = default
+volume_color = default
+state_line_color = default
+state_flags_color = default:b
+color1 = white
+color2 = white
+progressbar_elapsed_color = yellow
+statusbar_time_color = default:b
+player_state_color = cyan
+alternative_ui_separator_color = black
+window_border_color = cyan
+active_window_border = red
+execute_on_song_change="~/.config/ncmpcpp/ncmpcpp-ueberzug/ncmpcpp_cover_art.sh"
+display_volume_level = "yes"
+user_interface = "classic" (classic/alternative)
+cyclic_scrolling = "yes"
+mouse_support = "yes"
+mouse_list_scroll_whole_page = "yes"
+lines_scrolled = "1"
+message_delay_time = "1"
+titles_visibility = no
diff --git a/ncmpcpp/ncmpcpp-ueberzug b/ncmpcpp/ncmpcpp-ueberzug
new file mode 160000
+Subproject 9bd9121d9ba0ac49106b34f792c3445a07643a1
diff --git a/neofetch/config.conf b/neofetch/config.conf
new file mode 100644
index 0000000..6edce9a
--- /dev/null
+++ b/neofetch/config.conf
@@ -0,0 +1,864 @@
+# See this wiki page for more info:
+# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
+print_info() {
+ #info title
+ info underline
+
+ info "OS" distro
+ info "Host" model
+ info "Kernel" kernel
+ info "Uptime" uptime
+ info "Packages" packages
+ info "Shell" shell
+ info "Resolution" resolution
+ info "DE" de
+ info "WM" wm
+ info "WM Theme" wm_theme
+ #info "Theme" theme
+ #info "Icons" icons
+ info "Terminal" term
+ info "Terminal Font" term_font
+ info "CPU" cpu
+ info "GPU" gpu
+ info "Memory" memory
+
+ # info "GPU Driver" gpu_driver # Linux/macOS only
+ # info "CPU Usage" cpu_usage
+ # info "Disk" disk
+ # info "Battery" battery
+ # info "Font" font
+ # info "Song" song
+ # [[ "$player" ]] && prin "Music Player" "$player"
+ # info "Local IP" local_ip
+ # info "Public IP" public_ip
+ # info "Users" users
+ # info "Locale" locale # This only works on glibc systems.
+
+ info cols
+}
+
+# Title
+
+
+# Hide/Show Fully qualified domain name.
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --title_fqdn
+title_fqdn="off"
+
+
+# Kernel
+
+
+# Shorten the output of the kernel function.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --kernel_shorthand
+# Supports: Everything except *BSDs (except PacBSD and PC-BSD)
+#
+# Example:
+# on: '4.8.9-1-ARCH'
+# off: 'Linux 4.8.9-1-ARCH'
+kernel_shorthand="on"
+
+
+# Distro
+
+
+# Shorten the output of the distro function
+#
+# Default: 'off'
+# Values: 'on', 'tiny', 'off'
+# Flag: --distro_shorthand
+# Supports: Everything except Windows and Haiku
+distro_shorthand="off"
+
+# Show/Hide OS Architecture.
+# Show 'x86_64', 'x86' and etc in 'Distro:' output.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --os_arch
+#
+# Example:
+# on: 'Arch Linux x86_64'
+# off: 'Arch Linux'
+os_arch="on"
+
+
+# Uptime
+
+
+# Shorten the output of the uptime function
+#
+# Default: 'on'
+# Values: 'on', 'tiny', 'off'
+# Flag: --uptime_shorthand
+#
+# Example:
+# on: '2 days, 10 hours, 3 mins'
+# tiny: '2d 10h 3m'
+# off: '2 days, 10 hours, 3 minutes'
+uptime_shorthand="on"
+
+
+# Memory
+
+
+# Show memory pecentage in output.
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --memory_percent
+#
+# Example:
+# on: '1801MiB / 7881MiB (22%)'
+# off: '1801MiB / 7881MiB'
+memory_percent="off"
+
+# Change memory output unit.
+#
+# Default: 'mib'
+# Values: 'kib', 'mib', 'gib'
+# Flag: --memory_unit
+#
+# Example:
+# kib '1020928KiB / 7117824KiB'
+# mib '1042MiB / 6951MiB'
+# gib: ' 0.98GiB / 6.79GiB'
+memory_unit="mib"
+
+
+# Packages
+
+
+# Show/Hide Package Manager names.
+#
+# Default: 'tiny'
+# Values: 'on', 'tiny' 'off'
+# Flag: --package_managers
+#
+# Example:
+# on: '998 (pacman), 8 (flatpak), 4 (snap)'
+# tiny: '908 (pacman, flatpak, snap)'
+# off: '908'
+package_managers="on"
+
+
+# Shell
+
+
+# Show the path to $SHELL
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --shell_path
+#
+# Example:
+# on: '/bin/bash'
+# off: 'bash'
+shell_path="off"
+
+# Show $SHELL version
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --shell_version
+#
+# Example:
+# on: 'bash 4.4.5'
+# off: 'bash'
+shell_version="on"
+
+
+# CPU
+
+
+# CPU speed type
+#
+# Default: 'bios_limit'
+# Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'.
+# Flag: --speed_type
+# Supports: Linux with 'cpufreq'
+# NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value.
+speed_type="bios_limit"
+
+# CPU speed shorthand
+#
+# Default: 'off'
+# Values: 'on', 'off'.
+# Flag: --speed_shorthand
+# NOTE: This flag is not supported in systems with CPU speed less than 1 GHz
+#
+# Example:
+# on: 'i7-6500U (4) @ 3.1GHz'
+# off: 'i7-6500U (4) @ 3.100GHz'
+speed_shorthand="off"
+
+# Enable/Disable CPU brand in output.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --cpu_brand
+#
+# Example:
+# on: 'Intel i7-6500U'
+# off: 'i7-6500U (4)'
+cpu_brand="on"
+
+# CPU Speed
+# Hide/Show CPU speed.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --cpu_speed
+#
+# Example:
+# on: 'Intel i7-6500U (4) @ 3.1GHz'
+# off: 'Intel i7-6500U (4)'
+cpu_speed="on"
+
+# CPU Cores
+# Display CPU cores in output
+#
+# Default: 'logical'
+# Values: 'logical', 'physical', 'off'
+# Flag: --cpu_cores
+# Support: 'physical' doesn't work on BSD.
+#
+# Example:
+# logical: 'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores)
+# physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores)
+# off: 'Intel i7-6500U @ 3.1GHz'
+cpu_cores="off"
+
+# CPU Temperature
+# Hide/Show CPU temperature.
+# Note the temperature is added to the regular CPU function.
+#
+# Default: 'off'
+# Values: 'C', 'F', 'off'
+# Flag: --cpu_temp
+# Supports: Linux, BSD
+# NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable
+# coretemp kernel module. This only supports newer Intel processors.
+#
+# Example:
+# C: 'Intel i7-6500U (4) @ 3.1GHz [27.2°C]'
+# F: 'Intel i7-6500U (4) @ 3.1GHz [82.0°F]'
+# off: 'Intel i7-6500U (4) @ 3.1GHz'
+cpu_temp="off"
+
+
+# GPU
+
+
+# Enable/Disable GPU Brand
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --gpu_brand
+#
+# Example:
+# on: 'AMD HD 7950'
+# off: 'HD 7950'
+gpu_brand="off"
+
+# Which GPU to display
+#
+# Default: 'all'
+# Values: 'all', 'dedicated', 'integrated'
+# Flag: --gpu_type
+# Supports: Linux
+#
+# Example:
+# all:
+# GPU1: AMD HD 7950
+# GPU2: Intel Integrated Graphics
+#
+# dedicated:
+# GPU1: AMD HD 7950
+#
+# integrated:
+# GPU1: Intel Integrated Graphics
+gpu_type="all"
+
+
+# Resolution
+
+
+# Display refresh rate next to each monitor
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --refresh_rate
+# Supports: Doesn't work on Windows.
+#
+# Example:
+# on: '1920x1080 @ 60Hz'
+# off: '1920x1080'
+refresh_rate="off"
+
+
+# Gtk Theme / Icons / Font
+
+
+# Shorten output of GTK Theme / Icons / Font
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --gtk_shorthand
+#
+# Example:
+# on: 'Numix, Adwaita'
+# off: 'Numix [GTK2], Adwaita [GTK3]'
+gtk_shorthand="off"
+
+
+# Enable/Disable gtk2 Theme / Icons / Font
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --gtk2
+#
+# Example:
+# on: 'Numix [GTK2], Adwaita [GTK3]'
+# off: 'Adwaita [GTK3]'
+gtk2="on"
+
+# Enable/Disable gtk3 Theme / Icons / Font
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --gtk3
+#
+# Example:
+# on: 'Numix [GTK2], Adwaita [GTK3]'
+# off: 'Numix [GTK2]'
+gtk3="on"
+
+
+# IP Address
+
+
+# Website to ping for the public IP
+#
+# Default: 'http://ident.me'
+# Values: 'url'
+# Flag: --ip_host
+public_ip_host="http://ident.me"
+
+# Public IP timeout.
+#
+# Default: '2'
+# Values: 'int'
+# Flag: --ip_timeout
+public_ip_timeout=2
+
+
+# Desktop Environment
+
+
+# Show Desktop Environment version
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --de_version
+de_version="on"
+
+
+# Disk
+
+
+# Which disks to display.
+# The values can be any /dev/sdXX, mount point or directory.
+# NOTE: By default we only show the disk info for '/'.
+#
+# Default: '/'
+# Values: '/', '/dev/sdXX', '/path/to/drive'.
+# Flag: --disk_show
+#
+# Example:
+# disk_show=('/' '/dev/sdb1'):
+# 'Disk (/): 74G / 118G (66%)'
+# 'Disk (/mnt/Videos): 823G / 893G (93%)'
+#
+# disk_show=('/'):
+# 'Disk (/): 74G / 118G (66%)'
+#
+disk_show=('/')
+
+# Disk subtitle.
+# What to append to the Disk subtitle.
+#
+# Default: 'mount'
+# Values: 'mount', 'name', 'dir', 'none'
+# Flag: --disk_subtitle
+#
+# Example:
+# name: 'Disk (/dev/sda1): 74G / 118G (66%)'
+# 'Disk (/dev/sdb2): 74G / 118G (66%)'
+#
+# mount: 'Disk (/): 74G / 118G (66%)'
+# 'Disk (/mnt/Local Disk): 74G / 118G (66%)'
+# 'Disk (/mnt/Videos): 74G / 118G (66%)'
+#
+# dir: 'Disk (/): 74G / 118G (66%)'
+# 'Disk (Local Disk): 74G / 118G (66%)'
+# 'Disk (Videos): 74G / 118G (66%)'
+#
+# none: 'Disk: 74G / 118G (66%)'
+# 'Disk: 74G / 118G (66%)'
+# 'Disk: 74G / 118G (66%)'
+disk_subtitle="mount"
+
+# Disk percent.
+# Show/Hide disk percent.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --disk_percent
+#
+# Example:
+# on: 'Disk (/): 74G / 118G (66%)'
+# off: 'Disk (/): 74G / 118G'
+disk_percent="on"
+
+
+# Song
+
+
+# Manually specify a music player.
+#
+# Default: 'auto'
+# Values: 'auto', 'player-name'
+# Flag: --music_player
+#
+# Available values for 'player-name':
+#
+# amarok
+# audacious
+# banshee
+# bluemindo
+# clementine
+# cmus
+# deadbeef
+# deepin-music
+# dragon
+# elisa
+# exaile
+# gnome-music
+# gmusicbrowser
+# gogglesmm
+# guayadeque
+# io.elementary.music
+# iTunes
+# juk
+# lollypop
+# mocp
+# mopidy
+# mpd
+# muine
+# netease-cloud-music
+# olivia
+# playerctl
+# pogo
+# pragha
+# qmmp
+# quodlibet
+# rhythmbox
+# sayonara
+# smplayer
+# spotify
+# strawberry
+# tauonmb
+# tomahawk
+# vlc
+# xmms2d
+# xnoise
+# yarock
+music_player="auto"
+
+# Format to display song information.
+#
+# Default: '%artist% - %album% - %title%'
+# Values: '%artist%', '%album%', '%title%'
+# Flag: --song_format
+#
+# Example:
+# default: 'Song: Jet - Get Born - Sgt Major'
+song_format="%artist% - %album% - %title%"
+
+# Print the Artist, Album and Title on separate lines
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --song_shorthand
+#
+# Example:
+# on: 'Artist: The Fratellis'
+# 'Album: Costello Music'
+# 'Song: Chelsea Dagger'
+#
+# off: 'Song: The Fratellis - Costello Music - Chelsea Dagger'
+song_shorthand="off"
+
+# 'mpc' arguments (specify a host, password etc).
+#
+# Default: ''
+# Example: mpc_args=(-h HOST -P PASSWORD)
+mpc_args=()
+
+
+# Text Colors
+
+
+# Text Colors
+#
+# Default: 'distro'
+# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
+# Flag: --colors
+#
+# Each number represents a different part of the text in
+# this order: 'title', '@', 'underline', 'subtitle', 'colon', 'info'
+#
+# Example:
+# colors=(distro) - Text is colored based on Distro colors.
+# colors=(4 6 1 8 8 6) - Text is colored in the order above.
+colors=(distro)
+
+
+# Text Options
+
+
+# Toggle bold text
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --bold
+bold="on"
+
+# Enable/Disable Underline
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --underline
+underline_enabled="on"
+
+# Underline character
+#
+# Default: '-'
+# Values: 'string'
+# Flag: --underline_char
+underline_char="-"
+
+
+# Info Separator
+# Replace the default separator with the specified string.
+#
+# Default: ':'
+# Flag: --separator
+#
+# Example:
+# separator="->": 'Shell-> bash'
+# separator=" =": 'WM = dwm'
+separator=":"
+
+
+# Color Blocks
+
+
+# Color block range
+# The range of colors to print.
+#
+# Default: '0', '15'
+# Values: 'num'
+# Flag: --block_range
+#
+# Example:
+#
+# Display colors 0-7 in the blocks. (8 colors)
+# neofetch --block_range 0 7
+#
+# Display colors 0-15 in the blocks. (16 colors)
+# neofetch --block_range 0 15
+block_range=(0 15)
+
+# Toggle color blocks
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --color_blocks
+color_blocks="on"
+
+# Color block width in spaces
+#
+# Default: '3'
+# Values: 'num'
+# Flag: --block_width
+block_width=3
+
+# Color block height in lines
+#
+# Default: '1'
+# Values: 'num'
+# Flag: --block_height
+block_height=1
+
+# Color Alignment
+#
+# Default: 'auto'
+# Values: 'auto', 'num'
+# Flag: --col_offset
+#
+# Number specifies how far from the left side of the terminal (in spaces) to
+# begin printing the columns, in case you want to e.g. center them under your
+# text.
+# Example:
+# col_offset="auto" - Default behavior of neofetch
+# col_offset=7 - Leave 7 spaces then print the colors
+col_offset="auto"
+
+# Progress Bars
+
+
+# Bar characters
+#
+# Default: '-', '='
+# Values: 'string', 'string'
+# Flag: --bar_char
+#
+# Example:
+# neofetch --bar_char 'elapsed' 'total'
+# neofetch --bar_char '-' '='
+bar_char_elapsed="-"
+bar_char_total="="
+
+# Toggle Bar border
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --bar_border
+bar_border="on"
+
+# Progress bar length in spaces
+# Number of chars long to make the progress bars.
+#
+# Default: '15'
+# Values: 'num'
+# Flag: --bar_length
+bar_length=15
+
+# Progress bar colors
+# When set to distro, uses your distro's logo colors.
+#
+# Default: 'distro', 'distro'
+# Values: 'distro', 'num'
+# Flag: --bar_colors
+#
+# Example:
+# neofetch --bar_colors 3 4
+# neofetch --bar_colors distro 5
+bar_color_elapsed="distro"
+bar_color_total="distro"
+
+
+# Info display
+# Display a bar with the info.
+#
+# Default: 'off'
+# Values: 'bar', 'infobar', 'barinfo', 'off'
+# Flags: --cpu_display
+# --memory_display
+# --battery_display
+# --disk_display
+#
+# Example:
+# bar: '[---=======]'
+# infobar: 'info [---=======]'
+# barinfo: '[---=======] info'
+# off: 'info'
+cpu_display="off"
+memory_display="off"
+battery_display="off"
+disk_display="off"
+
+
+# Backend Settings
+
+
+# Image backend.
+#
+# Default: 'ascii'
+# Values: 'ascii', 'caca', 'chafa', 'jp2a', 'iterm2', 'off',
+# 'pot', 'termpix', 'pixterm', 'tycat', 'w3m', 'kitty'
+# Flag: --backend
+image_backend="ascii"
+
+# Image Source
+#
+# Which image or ascii file to display.
+#
+# Default: 'auto'
+# Values: 'auto', 'ascii', 'wallpaper', '/path/to/img', '/path/to/ascii', '/path/to/dir/'
+# 'command output (neofetch --ascii "$(fortune | cowsay -W 30)")'
+# Flag: --source
+#
+# NOTE: 'auto' will pick the best image source for whatever image backend is used.
+# In ascii mode, distro ascii art will be used and in an image mode, your
+# wallpaper will be used.
+image_source="$HOME/cabin.png"
+
+
+# Ascii Options
+
+
+# Ascii distro
+# Which distro's ascii art to display.
+#
+# Default: 'auto'
+# Values: 'auto', 'distro_name'
+# Flag: --ascii_distro
+# NOTE: AIX, Alpine, Anarchy, Android, Antergos, antiX, "AOSC OS",
+# "AOSC OS/Retro", Apricity, ArcoLinux, ArchBox, ARCHlabs,
+# ArchStrike, XFerience, ArchMerge, Arch, Artix, Arya, Bedrock,
+# Bitrig, BlackArch, BLAG, BlankOn, BlueLight, bonsai, BSD,
+# BunsenLabs, Calculate, Carbs, CentOS, Chakra, ChaletOS,
+# Chapeau, Chrom*, Cleanjaro, ClearOS, Clear_Linux, Clover,
+# Condres, Container_Linux, CRUX, Cucumber, Debian, Deepin,
+# DesaOS, Devuan, DracOS, DarkOs, DragonFly, Drauger, Elementary,
+# EndeavourOS, Endless, EuroLinux, Exherbo, Fedora, Feren, FreeBSD,
+# FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, Gentoo, Pentoo,
+# gNewSense, GNOME, GNU, GoboLinux, Grombyang, Guix, Haiku, Huayra,
+# Hyperbola, janus, Kali, KaOS, KDE_neon, Kibojoe, Kogaion,
+# Korora, KSLinux, Kubuntu, LEDE, LFS, Linux_Lite,
+# LMDE, Lubuntu, Lunar, macos, Mageia, MagpieOS, Mandriva,
+# Manjaro, Maui, Mer, Minix, LinuxMint, MX_Linux, Namib,
+# Neptune, NetBSD, Netrunner, Nitrux, NixOS, Nurunner,
+# NuTyX, OBRevenge, OpenBSD, openEuler, OpenIndiana, openmamba,
+# OpenMandriva, OpenStage, OpenWrt, osmc, Oracle, OS Elbrus, PacBSD,
+# Parabola, Pardus, Parrot, Parsix, TrueOS, PCLinuxOS, Peppermint,
+# popos, Porteus, PostMarketOS, Proxmox, Puppy, PureOS, Qubes, Radix,
+# Raspbian, Reborn_OS, Redstar, Redcore, Redhat, Refracted_Devuan,
+# Regata, Rosa, sabotage, Sabayon, Sailfish, SalentOS, Scientific,
+# Septor, SereneLinux, SharkLinux, Siduction, Slackware, SliTaz,
+# SmartOS, Solus, Source_Mage, Sparky, Star, SteamOS, SunOS,
+# openSUSE_Leap, openSUSE_Tumbleweed, openSUSE, SwagArch, Tails,
+# Trisquel, Ubuntu-Budgie, Ubuntu-GNOME, Ubuntu-MATE, Ubuntu-Studio,
+# Ubuntu, Venom, Void, Obarun, windows10, Windows7, Xubuntu, Zorin,
+# and IRIX have ascii logos
+# NOTE: Arch, Ubuntu, Redhat, and Dragonfly have 'old' logo variants.
+# Use '{distro name}_old' to use the old logos.
+# NOTE: Ubuntu has flavor variants.
+# Change this to Lubuntu, Kubuntu, Xubuntu, Ubuntu-GNOME,
+# Ubuntu-Studio, Ubuntu-Mate or Ubuntu-Budgie to use the flavors.
+# NOTE: Arcolinux, Dragonfly, Fedora, Alpine, Arch, Ubuntu,
+# CRUX, Debian, Gentoo, FreeBSD, Mac, NixOS, OpenBSD, android,
+# Antrix, CentOS, Cleanjaro, ElementaryOS, GUIX, Hyperbola,
+# Manjaro, MXLinux, NetBSD, Parabola, POP_OS, PureOS,
+# Slackware, SunOS, LinuxLite, OpenSUSE, Raspbian,
+# postmarketOS, and Void have a smaller logo variant.
+# Use '{distro name}_small' to use the small variants.
+ascii_distro="auto"
+
+# Ascii Colors
+#
+# Default: 'distro'
+# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
+# Flag: --ascii_colors
+#
+# Example:
+# ascii_colors=(distro) - Ascii is colored based on Distro colors.
+# ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors.
+ascii_colors=(distro)
+
+# Bold ascii logo
+# Whether or not to bold the ascii logo.
+#
+# Default: 'on'
+# Values: 'on', 'off'
+# Flag: --ascii_bold
+ascii_bold="on"
+
+
+# Image Options
+
+
+# Image loop
+# Setting this to on will make neofetch redraw the image constantly until
+# Ctrl+C is pressed. This fixes display issues in some terminal emulators.
+#
+# Default: 'off'
+# Values: 'on', 'off'
+# Flag: --loop
+image_loop="on"
+
+# Thumbnail directory
+#
+# Default: '~/.cache/thumbnails/neofetch'
+# Values: 'dir'
+thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch"
+
+# Crop mode
+#
+# Default: 'normal'
+# Values: 'normal', 'fit', 'fill'
+# Flag: --crop_mode
+#
+# See this wiki page to learn about the fit and fill options.
+# https://github.com/dylanaraps/neofetch/wiki/What-is-Waifu-Crop%3F
+crop_mode="normal"
+
+# Crop offset
+# Note: Only affects 'normal' crop mode.
+#
+# Default: 'center'
+# Values: 'northwest', 'north', 'northeast', 'west', 'center'
+# 'east', 'southwest', 'south', 'southeast'
+# Flag: --crop_offset
+crop_offset="center"
+
+# Image size
+# The image is half the terminal width by default.
+#
+# Default: 'auto'
+# Values: 'auto', '00px', '00%', 'none'
+# Flags: --image_size
+# --size
+image_size="auto"
+
+# Gap between image and text
+#
+# Default: '3'
+# Values: 'num', '-num'
+# Flag: --gap
+gap=3
+
+# Image offsets
+# Only works with the w3m backend.
+#
+# Default: '0'
+# Values: 'px'
+# Flags: --xoffset
+# --yoffset
+yoffset=0
+xoffset=0
+
+# Image background color
+# Only works with the w3m backend.
+#
+# Default: ''
+# Values: 'color', 'blue'
+# Flag: --bg_color
+background_color=
+
+
+# Misc Options
+
+# Stdout mode
+# Turn off all colors and disables image backend (ASCII/Image).
+# Useful for piping into another command.
+# Default: 'off'
+# Values: 'on', 'off'
+stdout="off"
diff --git a/newsboat/config b/newsboat/config
new file mode 100644
index 0000000..19d4c1a
--- /dev/null
+++ b/newsboat/config
@@ -0,0 +1,113 @@
+# GENERAL #
+
+reload-time 30
+auto-reload yes
+browser "setsid -f $BROWSER --new-tab %u > /dev/null 2>&1"
+cleanup-on-quit yes
+history-limit 2000
+show-keymap-hint no
+goto-next-feed no
+error-log ".config/newsboat/error.log"
+prepopulate-query-feeds yes
+suppress-first-reload yes
+
+# MACROS #
+
+# Queue videos
+macro a set browser "echo %u >> ~/.config/newsboat/queue" ; open-in-browser ; set browser "$BROWSER %u"
+
+# Clear queue
+macro c set browser "rm $HOME/.config/newsboat/queue > /dev/null 2>&1" ; open-in-browser ; set browser "$BROWSER %u"
+
+# Play queued videos
+macro p set browser "kill $(pidof mpv) ; setsid -f mpv --playlist=$HOME/.config/newsboat/queue > /dev/null 2>&1" ; open-in-browser ; set browser "$BROWSER %u"
+
+# Play queued videos fullscreen second monitor
+macro P set browser "kill $(pidof mpv) ; setsid -f mpv --x11-name=newsboatfs --fullscreen=yes --playlist=$HOME/.config/newsboat/queue > /dev/null 2>&1" ; open-in-browser ; set browser "$BROWSER %u"
+
+# Play video
+macro v set browser "kill $(pidof mpv) ; setsid -f mpv %u > /dev/null 2>&1" ; open-in-browser-and-mark-read ; set browser "$BROWSER %u"
+
+# Play audio only
+macro A set browser "kill $(pidof mpv) ; setsid -f mpv %u --no-video > /dev/null 2>&1" ; open-in-browser-and-mark-read ; set browser "$BROWSER %u"
+
+# Play video floating mode
+macro i set browser "kill $(pidof mpv) ; setsid -f mpv --x11-name=mpvfloat %u > /dev/null 2>&1" ; open-in-browser-and-mark-read ; set browser "$BROWSER %u"
+
+# Play fullscreen so i3 sends it to second monitor
+macro f set browser "kill $(pidof mpv) ; setsid -f mpv --x11-name=newsboatfs --fullscreen=yes %u > /dev/null 2>&1" ; open-in-browser ; set browser "$BROWSER %u"
+
+# Download video
+macro y set browser "yt-dlp %u -o $HOME/stf/vids/newsboat" ; open-in-browser ; set browser "$BROWSER %u"
+
+# Open in default browser
+macro o open-in-browser
+
+
+# NOTIFICATIONS #
+
+notify-always no
+notify-program "/usr/bin/dunstify"
+notify-format "Newsboat: %d new articles"
+
+# COLORS #
+
+color listnormal color245 default
+color listfocus color58 default
+color listnormal_unread white default bold
+color listfocus_unread color220 default bold
+color info black black bold
+color article default default
+
+highlight article "^Feed:.*" magenta default
+highlight article "^Title:.*" yellow default bold
+highlight article "^Author:.*" green default
+highlight article "^Date:.*" color223 default
+highlight article "^Link:.*" blue default
+highlight article "^Flags:.*" color9 default
+highlight article "\\[[0-9][0-9]*\\]" color66 default bold
+highlight article "\\[image [0-9][0-9]*\\]" color109 default bold
+highlight article "\\[embedded flash: [0-9][0-9]*\\]" color66 default bold
+
+highlight feedlist "[││]" color245 default bold
+highlight feedlist "├─.*" color245 default bold
+
+# Sorting feedlist
+
+highlight feedlist "\\❮Unsorted\\❯" color220
+highlight feedlist "\\❮Politics\/Philosophy\\❯" color214
+highlight feedlist "\\❮MDE\\❯" color221
+highlight feedlist "\\❮Schizophrenics Online\\❯" color214
+highlight feedlist "\\❮Tech\/Linux\/Coding\\❯" color221
+highlight feedlist "\\❮Shitpost\/Meme\\❯" color214
+highlight feedlist "\\❮Cooking\\❯" color221
+highlight feedlist "\\❮Text\/Blog\\❯" color221
+highlight feedlist "\\❮Nitter\\❯" color221
+
+feedlist-format "%?T?│ %9u ❮%T❯ %t &├─────────────────────────────────────────────────────────────────────────%t?"
+
+feedlist-title-format "┌───────────────────────────────NEWSBOAT────────────────────────────────────┐"
+
+# Destroying titles
+
+articlelist-title-format ""
+searchresult-title-format ""
+filebrowser-title-format ""
+dirbrowser-title-format ""
+help-title-format ""
+selecttag-title-format ""
+selectfilter-title-format ""
+urlview-title-format ""
+dialogs-title-format ""
+itemview-title-format ""
+
+# Vim keybindings
+
+unbind-key j
+unbind-key k
+unbind-key ENTER
+unbind-key o
+
+bind-key o open
+bind-key k up
+bind-key j down
diff --git a/nvim/autoload/plug.vim b/nvim/autoload/plug.vim
new file mode 100644
index 0000000..652caa8
--- /dev/null
+++ b/nvim/autoload/plug.vim
@@ -0,0 +1,2812 @@
+" vim-plug: Vim plugin manager
+" ============================
+"
+" Download plug.vim and put it in ~/.vim/autoload
+"
+" curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
+" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
+"
+" Edit your .vimrc
+"
+" call plug#begin('~/.vim/plugged')
+"
+" " Make sure you use single quotes
+"
+" " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align
+" Plug 'junegunn/vim-easy-align'
+"
+" " Any valid git URL is allowed
+" Plug 'https://github.com/junegunn/vim-github-dashboard.git'
+"
+" " Multiple Plug commands can be written in a single line using | separators
+" Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'
+"
+" " On-demand loading
+" Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
+" Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
+"
+" " Using a non-default branch
+" Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
+"
+" " Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
+" Plug 'fatih/vim-go', { 'tag': '*' }
+"
+" " Plugin options
+" Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }
+"
+" " Plugin outside ~/.vim/plugged with post-update hook
+" Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
+"
+" " Unmanaged plugin (manually installed and updated)
+" Plug '~/my-prototype-plugin'
+"
+" " Initialize plugin system
+" call plug#end()
+"
+" Then reload .vimrc and :PlugInstall to install plugins.
+"
+" Plug options:
+"
+"| Option | Description |
+"| ----------------------- | ------------------------------------------------ |
+"| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use |
+"| `rtp` | Subdirectory that contains Vim plugin |
+"| `dir` | Custom directory for the plugin |
+"| `as` | Use different name for the plugin |
+"| `do` | Post-update hook (string or funcref) |
+"| `on` | On-demand loading: Commands or `<Plug>`-mappings |
+"| `for` | On-demand loading: File types |
+"| `frozen` | Do not update unless explicitly specified |
+"
+" More information: https://github.com/junegunn/vim-plug
+"
+"
+" Copyright (c) 2017 Junegunn Choi
+"
+" MIT License
+"
+" Permission is hereby granted, free of charge, to any person obtaining
+" a copy of this software and associated documentation files (the
+" "Software"), to deal in the Software without restriction, including
+" without limitation the rights to use, copy, modify, merge, publish,
+" distribute, sublicense, and/or sell copies of the Software, and to
+" permit persons to whom the Software is furnished to do so, subject to
+" the following conditions:
+"
+" The above copyright notice and this permission notice shall be
+" included in all copies or substantial portions of the Software.
+"
+" 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 AND
+" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if exists('g:loaded_plug')
+ finish
+endif
+let g:loaded_plug = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+let s:plug_src = 'https://github.com/junegunn/vim-plug.git'
+let s:plug_tab = get(s:, 'plug_tab', -1)
+let s:plug_buf = get(s:, 'plug_buf', -1)
+let s:mac_gui = has('gui_macvim') && has('gui_running')
+let s:is_win = has('win32')
+let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win)
+let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
+if s:is_win && &shellslash
+ set noshellslash
+ let s:me = resolve(expand('<sfile>:p'))
+ set shellslash
+else
+ let s:me = resolve(expand('<sfile>:p'))
+endif
+let s:base_spec = { 'branch': '', 'frozen': 0 }
+let s:TYPE = {
+\ 'string': type(''),
+\ 'list': type([]),
+\ 'dict': type({}),
+\ 'funcref': type(function('call'))
+\ }
+let s:loaded = get(s:, 'loaded', {})
+let s:triggers = get(s:, 'triggers', {})
+
+function! s:is_powershell(shell)
+ return a:shell =~# 'powershell\(\.exe\)\?$' || a:shell =~# 'pwsh\(\.exe\)\?$'
+endfunction
+
+function! s:isabsolute(dir) abort
+ return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)')
+endfunction
+
+function! s:git_dir(dir) abort
+ let gitdir = s:trim(a:dir) . '/.git'
+ if isdirectory(gitdir)
+ return gitdir
+ endif
+ if !filereadable(gitdir)
+ return ''
+ endif
+ let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*')
+ if len(gitdir) && !s:isabsolute(gitdir)
+ let gitdir = a:dir . '/' . gitdir
+ endif
+ return isdirectory(gitdir) ? gitdir : ''
+endfunction
+
+function! s:git_origin_url(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let config = gitdir . '/config'
+ if empty(gitdir) || !filereadable(config)
+ return ''
+ endif
+ return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze')
+endfunction
+
+function! s:git_revision(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+
+ let line = get(readfile(head), 0, '')
+ let ref = matchstr(line, '^ref: \zs.*')
+ if empty(ref)
+ return line
+ endif
+
+ if filereadable(gitdir . '/' . ref)
+ return get(readfile(gitdir . '/' . ref), 0, '')
+ endif
+
+ if filereadable(gitdir . '/packed-refs')
+ for line in readfile(gitdir . '/packed-refs')
+ if line =~# ' ' . ref
+ return matchstr(line, '^[0-9a-f]*')
+ endif
+ endfor
+ endif
+
+ return ''
+endfunction
+
+function! s:git_local_branch(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+ let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*')
+ return len(branch) ? branch : 'HEAD'
+endfunction
+
+function! s:git_origin_branch(spec)
+ if len(a:spec.branch)
+ return a:spec.branch
+ endif
+
+ " The file may not be present if this is a local repository
+ let gitdir = s:git_dir(a:spec.dir)
+ let origin_head = gitdir.'/refs/remotes/origin/HEAD'
+ if len(gitdir) && filereadable(origin_head)
+ return matchstr(get(readfile(origin_head), 0, ''),
+ \ '^ref: refs/remotes/origin/\zs.*')
+ endif
+
+ " The command may not return the name of a branch in detached HEAD state
+ let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir))
+ return v:shell_error ? '' : result[-1]
+endfunction
+
+if s:is_win
+ function! s:plug_call(fn, ...)
+ let shellslash = &shellslash
+ try
+ set noshellslash
+ return call(a:fn, a:000)
+ finally
+ let &shellslash = shellslash
+ endtry
+ endfunction
+else
+ function! s:plug_call(fn, ...)
+ return call(a:fn, a:000)
+ endfunction
+endif
+
+function! s:plug_getcwd()
+ return s:plug_call('getcwd')
+endfunction
+
+function! s:plug_fnamemodify(fname, mods)
+ return s:plug_call('fnamemodify', a:fname, a:mods)
+endfunction
+
+function! s:plug_expand(fmt)
+ return s:plug_call('expand', a:fmt, 1)
+endfunction
+
+function! s:plug_tempname()
+ return s:plug_call('tempname')
+endfunction
+
+function! plug#begin(...)
+ if a:0 > 0
+ let s:plug_home_org = a:1
+ let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p'))
+ elseif exists('g:plug_home')
+ let home = s:path(g:plug_home)
+ elseif has('nvim')
+ let home = stdpath('data') . '/plugged'
+ elseif !empty(&rtp)
+ let home = s:path(split(&rtp, ',')[0]) . '/plugged'
+ else
+ return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')
+ endif
+ if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp
+ return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.')
+ endif
+
+ let g:plug_home = home
+ let g:plugs = {}
+ let g:plugs_order = []
+ let s:triggers = {}
+
+ call s:define_commands()
+ return 1
+endfunction
+
+function! s:define_commands()
+ command! -nargs=+ -bar Plug call plug#(<args>)
+ if !executable('git')
+ return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.')
+ endif
+ if has('win32')
+ \ && &shellslash
+ \ && (&shell =~# 'cmd\(\.exe\)\?$' || s:is_powershell(&shell))
+ return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.')
+ endif
+ if !has('nvim')
+ \ && (has('win32') || has('win32unix'))
+ \ && !has('multi_byte')
+ return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.')
+ endif
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(<bang>0, [<f-args>])
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(<bang>0, [<f-args>])
+ command! -nargs=0 -bar -bang PlugClean call s:clean(<bang>0)
+ command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif
+ command! -nargs=0 -bar PlugStatus call s:status()
+ command! -nargs=0 -bar PlugDiff call s:diff()
+ command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(<bang>0, <f-args>)
+endfunction
+
+function! s:to_a(v)
+ return type(a:v) == s:TYPE.list ? a:v : [a:v]
+endfunction
+
+function! s:to_s(v)
+ return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"
+endfunction
+
+function! s:glob(from, pattern)
+ return s:lines(globpath(a:from, a:pattern))
+endfunction
+
+function! s:source(from, ...)
+ let found = 0
+ for pattern in a:000
+ for vim in s:glob(a:from, pattern)
+ execute 'source' s:esc(vim)
+ let found = 1
+ endfor
+ endfor
+ return found
+endfunction
+
+function! s:assoc(dict, key, val)
+ let a:dict[a:key] = add(get(a:dict, a:key, []), a:val)
+endfunction
+
+function! s:ask(message, ...)
+ call inputsave()
+ echohl WarningMsg
+ let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) '))
+ echohl None
+ call inputrestore()
+ echo "\r"
+ return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0
+endfunction
+
+function! s:ask_no_interrupt(...)
+ try
+ return call('s:ask', a:000)
+ catch
+ return 0
+ endtry
+endfunction
+
+function! s:lazy(plug, opt)
+ return has_key(a:plug, a:opt) &&
+ \ (empty(s:to_a(a:plug[a:opt])) ||
+ \ !isdirectory(a:plug.dir) ||
+ \ len(s:glob(s:rtp(a:plug), 'plugin')) ||
+ \ len(s:glob(s:rtp(a:plug), 'after/plugin')))
+endfunction
+
+function! plug#end()
+ if !exists('g:plugs')
+ return s:err('plug#end() called without calling plug#begin() first')
+ endif
+
+ if exists('#PlugLOD')
+ augroup PlugLOD
+ autocmd!
+ augroup END
+ augroup! PlugLOD
+ endif
+ let lod = { 'ft': {}, 'map': {}, 'cmd': {} }
+
+ if get(g:, 'did_load_filetypes', 0)
+ filetype off
+ endif
+ for name in g:plugs_order
+ if !has_key(g:plugs, name)
+ continue
+ endif
+ let plug = g:plugs[name]
+ if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for')
+ let s:loaded[name] = 1
+ continue
+ endif
+
+ if has_key(plug, 'on')
+ let s:triggers[name] = { 'map': [], 'cmd': [] }
+ for cmd in s:to_a(plug.on)
+ if cmd =~? '^<Plug>.\+'
+ if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
+ call s:assoc(lod.map, cmd, name)
+ endif
+ call add(s:triggers[name].map, cmd)
+ elseif cmd =~# '^[A-Z]'
+ let cmd = substitute(cmd, '!*$', '', '')
+ if exists(':'.cmd) != 2
+ call s:assoc(lod.cmd, cmd, name)
+ endif
+ call add(s:triggers[name].cmd, cmd)
+ else
+ call s:err('Invalid `on` option: '.cmd.
+ \ '. Should start with an uppercase letter or `<Plug>`.')
+ endif
+ endfor
+ endif
+
+ if has_key(plug, 'for')
+ let types = s:to_a(plug.for)
+ if !empty(types)
+ augroup filetypedetect
+ call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim')
+ augroup END
+ endif
+ for type in types
+ call s:assoc(lod.ft, type, name)
+ endfor
+ endif
+ endfor
+
+ for [cmd, names] in items(lod.cmd)
+ execute printf(
+ \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
+ \ cmd, string(cmd), string(names))
+ endfor
+
+ for [map, names] in items(lod.map)
+ for [mode, map_prefix, key_prefix] in
+ \ [['i', '<C-\><C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
+ execute printf(
+ \ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, %s, "%s")<CR>',
+ \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix)
+ endfor
+ endfor
+
+ for [ft, names] in items(lod.ft)
+ augroup PlugLOD
+ execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',
+ \ ft, string(ft), string(names))
+ augroup END
+ endfor
+
+ call s:reorg_rtp()
+ filetype plugin indent on
+ if has('vim_starting')
+ if has('syntax') && !exists('g:syntax_on')
+ syntax enable
+ end
+ else
+ call s:reload_plugins()
+ endif
+endfunction
+
+function! s:loaded_names()
+ return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)')
+endfunction
+
+function! s:load_plugin(spec)
+ call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim')
+endfunction
+
+function! s:reload_plugins()
+ for name in s:loaded_names()
+ call s:load_plugin(g:plugs[name])
+ endfor
+endfunction
+
+function! s:trim(str)
+ return substitute(a:str, '[\/]\+$', '', '')
+endfunction
+
+function! s:version_requirement(val, min)
+ for idx in range(0, len(a:min) - 1)
+ let v = get(a:val, idx, 0)
+ if v < a:min[idx] | return 0
+ elseif v > a:min[idx] | return 1
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:git_version_requirement(...)
+ if !exists('s:git_version')
+ let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)')
+ endif
+ return s:version_requirement(s:git_version, a:000)
+endfunction
+
+function! s:progress_opt(base)
+ return a:base && !s:is_win &&
+ \ s:git_version_requirement(1, 7, 1) ? '--progress' : ''
+endfunction
+
+function! s:rtp(spec)
+ return s:path(a:spec.dir . get(a:spec, 'rtp', ''))
+endfunction
+
+if s:is_win
+ function! s:path(path)
+ return s:trim(substitute(a:path, '/', '\', 'g'))
+ endfunction
+
+ function! s:dirpath(path)
+ return s:path(a:path) . '\'
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo =~? '^[a-z]:\|^[%~]'
+ endfunction
+
+ " Copied from fzf
+ function! s:wrap_cmds(cmds)
+ let cmds = [
+ \ '@echo off',
+ \ 'setlocal enabledelayedexpansion']
+ \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds])
+ \ + ['endlocal']
+ if has('iconv')
+ if !exists('s:codepage')
+ let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0)
+ endif
+ return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage))
+ endif
+ return map(cmds, 'v:val."\r"')
+ endfunction
+
+ function! s:batchfile(cmd)
+ let batchfile = s:plug_tempname().'.bat'
+ call writefile(s:wrap_cmds(a:cmd), batchfile)
+ let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0})
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ return [batchfile, cmd]
+ endfunction
+else
+ function! s:path(path)
+ return s:trim(a:path)
+ endfunction
+
+ function! s:dirpath(path)
+ return substitute(a:path, '[/\\]*$', '/', '')
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo[0] =~ '[/$~]'
+ endfunction
+endif
+
+function! s:err(msg)
+ echohl ErrorMsg
+ echom '[vim-plug] '.a:msg
+ echohl None
+endfunction
+
+function! s:warn(cmd, msg)
+ echohl WarningMsg
+ execute a:cmd 'a:msg'
+ echohl None
+endfunction
+
+function! s:esc(path)
+ return escape(a:path, ' ')
+endfunction
+
+function! s:escrtp(path)
+ return escape(a:path, ' ,')
+endfunction
+
+function! s:remove_rtp()
+ for name in s:loaded_names()
+ let rtp = s:rtp(g:plugs[name])
+ execute 'set rtp-='.s:escrtp(rtp)
+ let after = globpath(rtp, 'after')
+ if isdirectory(after)
+ execute 'set rtp-='.s:escrtp(after)
+ endif
+ endfor
+endfunction
+
+function! s:reorg_rtp()
+ if !empty(s:first_rtp)
+ execute 'set rtp-='.s:first_rtp
+ execute 'set rtp-='.s:last_rtp
+ endif
+
+ " &rtp is modified from outside
+ if exists('s:prtp') && s:prtp !=# &rtp
+ call s:remove_rtp()
+ unlet! s:middle
+ endif
+
+ let s:middle = get(s:, 'middle', &rtp)
+ let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')
+ let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)')
+ let rtp = join(map(rtps, 'escape(v:val, ",")'), ',')
+ \ . ','.s:middle.','
+ \ . join(map(afters, 'escape(v:val, ",")'), ',')
+ let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')
+ let s:prtp = &rtp
+
+ if !empty(s:first_rtp)
+ execute 'set rtp^='.s:first_rtp
+ execute 'set rtp+='.s:last_rtp
+ endif
+endfunction
+
+function! s:doautocmd(...)
+ if exists('#'.join(a:000, '#'))
+ execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '<nomodeline>' : '') join(a:000)
+ endif
+endfunction
+
+function! s:dobufread(names)
+ for name in a:names
+ let path = s:rtp(g:plugs[name])
+ for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin']
+ if len(finddir(dir, path))
+ if exists('#BufRead')
+ doautocmd BufRead
+ endif
+ return
+ endif
+ endfor
+ endfor
+endfunction
+
+function! plug#load(...)
+ if a:0 == 0
+ return s:err('Argument missing: plugin name(s) required')
+ endif
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000
+ let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)')
+ if !empty(unknowns)
+ let s = len(unknowns) > 1 ? 's' : ''
+ return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))
+ end
+ let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)')
+ if !empty(unloaded)
+ for name in unloaded
+ call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ endfor
+ call s:dobufread(unloaded)
+ return 1
+ end
+ return 0
+endfunction
+
+function! s:remove_triggers(name)
+ if !has_key(s:triggers, a:name)
+ return
+ endif
+ for cmd in s:triggers[a:name].cmd
+ execute 'silent! delc' cmd
+ endfor
+ for map in s:triggers[a:name].map
+ execute 'silent! unmap' map
+ execute 'silent! iunmap' map
+ endfor
+ call remove(s:triggers, a:name)
+endfunction
+
+function! s:lod(names, types, ...)
+ for name in a:names
+ call s:remove_triggers(name)
+ let s:loaded[name] = 1
+ endfor
+ call s:reorg_rtp()
+
+ for name in a:names
+ let rtp = s:rtp(g:plugs[name])
+ for dir in a:types
+ call s:source(rtp, dir.'/**/*.vim')
+ endfor
+ if a:0
+ if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2))
+ execute 'runtime' a:1
+ endif
+ call s:source(rtp, a:2)
+ endif
+ call s:doautocmd('User', name)
+ endfor
+endfunction
+
+function! s:lod_ft(pat, names)
+ let syn = 'syntax/'.a:pat.'.vim'
+ call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn)
+ execute 'autocmd! PlugLOD FileType' a:pat
+ call s:doautocmd('filetypeplugin', 'FileType')
+ call s:doautocmd('filetypeindent', 'FileType')
+endfunction
+
+function! s:lod_cmd(cmd, bang, l1, l2, args, names)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
+endfunction
+
+function! s:lod_map(map, names, with_prefix, prefix)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ let extra = ''
+ while 1
+ let c = getchar(0)
+ if c == 0
+ break
+ endif
+ let extra .= nr2char(c)
+ endwhile
+
+ if a:with_prefix
+ let prefix = v:count ? v:count : ''
+ let prefix .= '"'.v:register.a:prefix
+ if mode(1) == 'no'
+ if v:operator == 'c'
+ let prefix = "\<esc>" . prefix
+ endif
+ let prefix .= v:operator
+ endif
+ call feedkeys(prefix, 'n')
+ endif
+ call feedkeys(substitute(a:map, '^<Plug>', "\<Plug>", '') . extra)
+endfunction
+
+function! plug#(repo, ...)
+ if a:0 > 1
+ return s:err('Invalid number of arguments (1..2)')
+ endif
+
+ try
+ let repo = s:trim(a:repo)
+ let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec
+ let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??'))
+ let spec = extend(s:infer_properties(name, repo), opts)
+ if !has_key(g:plugs, name)
+ call add(g:plugs_order, name)
+ endif
+ let g:plugs[name] = spec
+ let s:loaded[name] = get(s:loaded, name, 0)
+ catch
+ return s:err(repo . ' ' . v:exception)
+ endtry
+endfunction
+
+function! s:parse_options(arg)
+ let opts = copy(s:base_spec)
+ let type = type(a:arg)
+ let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)'
+ if type == s:TYPE.string
+ if empty(a:arg)
+ throw printf(opt_errfmt, 'tag', 'string')
+ endif
+ let opts.tag = a:arg
+ elseif type == s:TYPE.dict
+ for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as']
+ if has_key(a:arg, opt)
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string')
+ endif
+ endfor
+ for opt in ['on', 'for']
+ if has_key(a:arg, opt)
+ \ && type(a:arg[opt]) != s:TYPE.list
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string or list')
+ endif
+ endfor
+ if has_key(a:arg, 'do')
+ \ && type(a:arg.do) != s:TYPE.funcref
+ \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do))
+ throw printf(opt_errfmt, 'do', 'string or funcref')
+ endif
+ call extend(opts, a:arg)
+ if has_key(opts, 'dir')
+ let opts.dir = s:dirpath(s:plug_expand(opts.dir))
+ endif
+ else
+ throw 'Invalid argument type (expected: string or dictionary)'
+ endif
+ return opts
+endfunction
+
+function! s:infer_properties(name, repo)
+ let repo = a:repo
+ if s:is_local_plug(repo)
+ return { 'dir': s:dirpath(s:plug_expand(repo)) }
+ else
+ if repo =~ ':'
+ let uri = repo
+ else
+ if repo !~ '/'
+ throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo)
+ endif
+ let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git')
+ let uri = printf(fmt, repo)
+ endif
+ return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri }
+ endif
+endfunction
+
+function! s:install(force, names)
+ call s:update_impl(0, a:force, a:names)
+endfunction
+
+function! s:update(force, names)
+ call s:update_impl(1, a:force, a:names)
+endfunction
+
+function! plug#helptags()
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ for spec in values(g:plugs)
+ let docd = join([s:rtp(spec), 'doc'], '/')
+ if isdirectory(docd)
+ silent! execute 'helptags' s:esc(docd)
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:syntax()
+ syntax clear
+ syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber
+ syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX
+ syn match plugNumber /[0-9]\+[0-9.]*/ contained
+ syn match plugBracket /[[\]]/ contained
+ syn match plugX /x/ contained
+ syn match plugDash /^-\{1}\ /
+ syn match plugPlus /^+/
+ syn match plugStar /^*/
+ syn match plugMessage /\(^- \)\@<=.*/
+ syn match plugName /\(^- \)\@<=[^ ]*:/
+ syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/
+ syn match plugTag /(tag: [^)]\+)/
+ syn match plugInstall /\(^+ \)\@<=[^:]*/
+ syn match plugUpdate /\(^* \)\@<=[^:]*/
+ syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag
+ syn match plugEdge /^ \X\+$/
+ syn match plugEdge /^ \X*/ contained nextgroup=plugSha
+ syn match plugSha /[0-9a-f]\{7,9}/ contained
+ syn match plugRelDate /([^)]*)$/ contained
+ syn match plugNotLoaded /(not loaded)$/
+ syn match plugError /^x.*/
+ syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/
+ syn match plugH2 /^.*:\n-\+$/
+ syn match plugH2 /^-\{2,}/
+ syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean
+ hi def link plug1 Title
+ hi def link plug2 Repeat
+ hi def link plugH2 Type
+ hi def link plugX Exception
+ hi def link plugBracket Structure
+ hi def link plugNumber Number
+
+ hi def link plugDash Special
+ hi def link plugPlus Constant
+ hi def link plugStar Boolean
+
+ hi def link plugMessage Function
+ hi def link plugName Label
+ hi def link plugInstall Function
+ hi def link plugUpdate Type
+
+ hi def link plugError Error
+ hi def link plugDeleted Ignore
+ hi def link plugRelDate Comment
+ hi def link plugEdge PreProc
+ hi def link plugSha Identifier
+ hi def link plugTag Constant
+
+ hi def link plugNotLoaded Comment
+endfunction
+
+function! s:lpad(str, len)
+ return a:str . repeat(' ', a:len - len(a:str))
+endfunction
+
+function! s:lines(msg)
+ return split(a:msg, "[\r\n]")
+endfunction
+
+function! s:lastline(msg)
+ return get(s:lines(a:msg), -1, '')
+endfunction
+
+function! s:new_window()
+ execute get(g:, 'plug_window', 'vertical topleft new')
+endfunction
+
+function! s:plug_window_exists()
+ let buflist = tabpagebuflist(s:plug_tab)
+ return !empty(buflist) && index(buflist, s:plug_buf) >= 0
+endfunction
+
+function! s:switch_in()
+ if !s:plug_window_exists()
+ return 0
+ endif
+
+ if winbufnr(0) != s:plug_buf
+ let s:pos = [tabpagenr(), winnr(), winsaveview()]
+ execute 'normal!' s:plug_tab.'gt'
+ let winnr = bufwinnr(s:plug_buf)
+ execute winnr.'wincmd w'
+ call add(s:pos, winsaveview())
+ else
+ let s:pos = [winsaveview()]
+ endif
+
+ setlocal modifiable
+ return 1
+endfunction
+
+function! s:switch_out(...)
+ call winrestview(s:pos[-1])
+ setlocal nomodifiable
+ if a:0 > 0
+ execute a:1
+ endif
+
+ if len(s:pos) > 1
+ execute 'normal!' s:pos[0].'gt'
+ execute s:pos[1] 'wincmd w'
+ call winrestview(s:pos[2])
+ endif
+endfunction
+
+function! s:finish_bindings()
+ nnoremap <silent> <buffer> R :call <SID>retry()<cr>
+ nnoremap <silent> <buffer> D :PlugDiff<cr>
+ nnoremap <silent> <buffer> S :PlugStatus<cr>
+ nnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ xnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
+ nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
+endfunction
+
+function! s:prepare(...)
+ if empty(s:plug_getcwd())
+ throw 'Invalid current working directory. Cannot proceed.'
+ endif
+
+ for evar in ['$GIT_DIR', '$GIT_WORK_TREE']
+ if exists(evar)
+ throw evar.' detected. Cannot proceed.'
+ endif
+ endfor
+
+ call s:job_abort()
+ if s:switch_in()
+ if b:plug_preview == 1
+ pc
+ endif
+ enew
+ else
+ call s:new_window()
+ endif
+
+ nnoremap <silent> <buffer> q :call <SID>close_pane()<cr>
+ if a:0 == 0
+ call s:finish_bindings()
+ endif
+ let b:plug_preview = -1
+ let s:plug_tab = tabpagenr()
+ let s:plug_buf = winbufnr(0)
+ call s:assign_name()
+
+ for k in ['<cr>', 'L', 'o', 'X', 'd', 'dd']
+ execute 'silent! unmap <buffer>' k
+ endfor
+ setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell
+ if exists('+colorcolumn')
+ setlocal colorcolumn=
+ endif
+ setf vim-plug
+ if exists('g:syntax_on')
+ call s:syntax()
+ endif
+endfunction
+
+function! s:close_pane()
+ if b:plug_preview == 1
+ pc
+ let b:plug_preview = -1
+ else
+ bd
+ endif
+endfunction
+
+function! s:assign_name()
+ " Assign buffer name
+ let prefix = '[Plugins]'
+ let name = prefix
+ let idx = 2
+ while bufexists(name)
+ let name = printf('%s (%s)', prefix, idx)
+ let idx = idx + 1
+ endwhile
+ silent! execute 'f' fnameescape(name)
+endfunction
+
+function! s:chsh(swap)
+ let prev = [&shell, &shellcmdflag, &shellredir]
+ if !s:is_win
+ set shell=sh
+ endif
+ if a:swap
+ if s:is_powershell(&shell)
+ let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s'
+ elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$'
+ set shellredir=>%s\ 2>&1
+ endif
+ endif
+ return prev
+endfunction
+
+function! s:bang(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(a:0)
+ " FIXME: Escaping is incomplete. We could use shellescape with eval,
+ " but it won't work on Windows.
+ let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%')
+ execute "normal! :execute g:_plug_bang\<cr>\<cr>"
+ finally
+ unlet g:_plug_bang
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ return v:shell_error ? 'Exit status: ' . v:shell_error : ''
+endfunction
+
+function! s:regress_bar()
+ let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '')
+ call s:progress_bar(2, bar, len(bar))
+endfunction
+
+function! s:is_updated(dir)
+ return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir))
+endfunction
+
+function! s:do(pull, force, todo)
+ for [name, spec] in items(a:todo)
+ if !isdirectory(spec.dir)
+ continue
+ endif
+ let installed = has_key(s:update.new, name)
+ let updated = installed ? 0 :
+ \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir))
+ if a:force || installed || updated
+ execute 'cd' s:esc(spec.dir)
+ call append(3, '- Post-update hook for '. name .' ... ')
+ let error = ''
+ let type = type(spec.do)
+ if type == s:TYPE.string
+ if spec.do[0] == ':'
+ if !get(s:loaded, name, 0)
+ let s:loaded[name] = 1
+ call s:reorg_rtp()
+ endif
+ call s:load_plugin(spec)
+ try
+ execute spec.do[1:]
+ catch
+ let error = v:exception
+ endtry
+ if !s:plug_window_exists()
+ cd -
+ throw 'Warning: vim-plug was terminated by the post-update hook of '.name
+ endif
+ else
+ let error = s:bang(spec.do)
+ endif
+ elseif type == s:TYPE.funcref
+ try
+ call s:load_plugin(spec)
+ let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged')
+ call spec.do({ 'name': name, 'status': status, 'force': a:force })
+ catch
+ let error = v:exception
+ endtry
+ else
+ let error = 'Invalid hook type'
+ endif
+ call s:switch_in()
+ call setline(4, empty(error) ? (getline(4) . 'OK')
+ \ : ('x' . getline(4)[1:] . error))
+ if !empty(error)
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ endif
+ cd -
+ endif
+ endfor
+endfunction
+
+function! s:hash_match(a, b)
+ return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0
+endfunction
+
+function! s:checkout(spec)
+ let sha = a:spec.commit
+ let output = s:git_revision(a:spec.dir)
+ if !empty(output) && !s:hash_match(sha, s:lines(output)[0])
+ let credential_helper = s:git_version_requirement(2) ? '-c credential.helper= ' : ''
+ let output = s:system(
+ \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
+ endif
+ return output
+endfunction
+
+function! s:finish(pull)
+ let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen'))
+ if new_frozen
+ let s = new_frozen > 1 ? 's' : ''
+ call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))
+ endif
+ call append(3, '- Finishing ... ') | 4
+ redraw
+ call plug#helptags()
+ call plug#end()
+ call setline(4, getline(4) . 'Done!')
+ redraw
+ let msgs = []
+ if !empty(s:update.errors)
+ call add(msgs, "Press 'R' to retry.")
+ endif
+ if a:pull && len(s:update.new) < len(filter(getline(5, '$'),
+ \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'"))
+ call add(msgs, "Press 'D' to see the updated changes.")
+ endif
+ echo join(msgs, ' ')
+ call s:finish_bindings()
+endfunction
+
+function! s:retry()
+ if empty(s:update.errors)
+ return
+ endif
+ echo
+ call s:update_impl(s:update.pull, s:update.force,
+ \ extend(copy(s:update.errors), [s:update.threads]))
+endfunction
+
+function! s:is_managed(name)
+ return has_key(g:plugs[a:name], 'uri')
+endfunction
+
+function! s:names(...)
+ return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))
+endfunction
+
+function! s:check_ruby()
+ silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'")
+ if !exists('g:plug_ruby')
+ redraw!
+ return s:warn('echom', 'Warning: Ruby interface is broken')
+ endif
+ let ruby_version = split(g:plug_ruby, '\.')
+ unlet g:plug_ruby
+ return s:version_requirement(ruby_version, [1, 8, 7])
+endfunction
+
+function! s:update_impl(pull, force, args) abort
+ let sync = index(a:args, '--sync') >= 0 || has('vim_starting')
+ let args = filter(copy(a:args), 'v:val != "--sync"')
+ let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
+ \ remove(args, -1) : get(g:, 'plug_threads', 16)
+
+ let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
+ let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') :
+ \ filter(managed, 'index(args, v:key) >= 0')
+
+ if empty(todo)
+ return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install'))
+ endif
+
+ if !s:is_win && s:git_version_requirement(2, 3)
+ let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : ''
+ let $GIT_TERMINAL_PROMPT = 0
+ for plug in values(todo)
+ let plug.uri = substitute(plug.uri,
+ \ '^https://git::@github\.com', 'https://github.com', '')
+ endfor
+ endif
+
+ if !isdirectory(g:plug_home)
+ try
+ call mkdir(g:plug_home, 'p')
+ catch
+ return s:err(printf('Invalid plug directory: %s. '.
+ \ 'Try to call plug#begin with a valid directory', g:plug_home))
+ endtry
+ endif
+
+ if has('nvim') && !exists('*jobwait') && threads > 1
+ call s:warn('echom', '[vim-plug] Update Neovim for parallel installer')
+ endif
+
+ let use_job = s:nvim || s:vim8
+ let python = (has('python') || has('python3')) && !use_job
+ let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby()
+
+ let s:update = {
+ \ 'start': reltime(),
+ \ 'all': todo,
+ \ 'todo': copy(todo),
+ \ 'errors': [],
+ \ 'pull': a:pull,
+ \ 'force': a:force,
+ \ 'new': {},
+ \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1,
+ \ 'bar': '',
+ \ 'fin': 0
+ \ }
+
+ call s:prepare(1)
+ call append(0, ['', ''])
+ normal! 2G
+ silent! redraw
+
+ " Set remote name, overriding a possible user git config's clone.defaultRemoteName
+ let s:clone_opt = ['--origin', 'origin']
+ if get(g:, 'plug_shallow', 1)
+ call extend(s:clone_opt, ['--depth', '1'])
+ if s:git_version_requirement(1, 7, 10)
+ call add(s:clone_opt, '--no-single-branch')
+ endif
+ endif
+
+ if has('win32unix') || has('wsl')
+ call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input'])
+ endif
+
+ let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : ''
+
+ " Python version requirement (>= 2.7)
+ if python && !has('python3') && !ruby && !use_job && s:update.threads > 1
+ redir => pyv
+ silent python import platform; print platform.python_version()
+ redir END
+ let python = s:version_requirement(
+ \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])
+ endif
+
+ if (python || ruby) && s:update.threads > 1
+ try
+ let imd = &imd
+ if s:mac_gui
+ set noimd
+ endif
+ if ruby
+ call s:update_ruby()
+ else
+ call s:update_python()
+ endif
+ catch
+ let lines = getline(4, '$')
+ let printed = {}
+ silent! 4,$d _
+ for line in lines
+ let name = s:extract_name(line, '.', '')
+ if empty(name) || !has_key(printed, name)
+ call append('$', line)
+ if !empty(name)
+ let printed[name] = 1
+ if line[0] == 'x' && index(s:update.errors, name) < 0
+ call add(s:update.errors, name)
+ end
+ endif
+ endif
+ endfor
+ finally
+ let &imd = imd
+ call s:update_finish()
+ endtry
+ else
+ call s:update_vim()
+ while use_job && sync
+ sleep 100m
+ if s:update.fin
+ break
+ endif
+ endwhile
+ endif
+endfunction
+
+function! s:log4(name, msg)
+ call setline(4, printf('- %s (%s)', a:msg, a:name))
+ redraw
+endfunction
+
+function! s:update_finish()
+ if exists('s:git_terminal_prompt')
+ let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt
+ endif
+ if s:switch_in()
+ call append(3, '- Updating ...') | 4
+ for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))'))
+ let [pos, _] = s:logpos(name)
+ if !pos
+ continue
+ endif
+ if has_key(spec, 'commit')
+ call s:log4(name, 'Checking out '.spec.commit)
+ let out = s:checkout(spec)
+ elseif has_key(spec, 'tag')
+ let tag = spec.tag
+ if tag =~ '\*'
+ let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir))
+ if !v:shell_error && !empty(tags)
+ let tag = tags[0]
+ call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
+ call append(3, '')
+ endif
+ endif
+ call s:log4(name, 'Checking out '.tag)
+ let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)
+ else
+ let branch = s:git_origin_branch(spec)
+ call s:log4(name, 'Merging origin/'.s:esc(branch))
+ let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1'
+ \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir)
+ endif
+ if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&
+ \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir))
+ call s:log4(name, 'Updating submodules. This may take a while.')
+ let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir)
+ endif
+ let msg = s:format_message(v:shell_error ? 'x': '-', name, out)
+ if v:shell_error
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ silent execute pos 'd _'
+ call append(4, msg) | 4
+ elseif !empty(out)
+ call setline(pos, msg[0])
+ endif
+ redraw
+ endfor
+ silent 4 d _
+ try
+ call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")'))
+ catch
+ call s:warn('echom', v:exception)
+ call s:warn('echo', '')
+ return
+ endtry
+ call s:finish(s:update.pull)
+ call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')
+ call s:switch_out('normal! gg')
+ endif
+endfunction
+
+function! s:job_abort()
+ if (!s:nvim && !s:vim8) || !exists('s:jobs')
+ return
+ endif
+
+ for [name, j] in items(s:jobs)
+ if s:nvim
+ silent! call jobstop(j.jobid)
+ elseif s:vim8
+ silent! call job_stop(j.jobid)
+ endif
+ if j.new
+ call s:rm_rf(g:plugs[name].dir)
+ endif
+ endfor
+ let s:jobs = {}
+endfunction
+
+function! s:last_non_empty_line(lines)
+ let len = len(a:lines)
+ for idx in range(len)
+ let line = a:lines[len-idx-1]
+ if !empty(line)
+ return line
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:job_out_cb(self, data) abort
+ let self = a:self
+ let data = remove(self.lines, -1) . a:data
+ let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]')
+ call extend(self.lines, lines)
+ " To reduce the number of buffer updates
+ let self.tick = get(self, 'tick', -1) + 1
+ if !self.running || self.tick % len(s:jobs) == 0
+ let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-')
+ let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines)
+ call s:log(bullet, self.name, result)
+ endif
+endfunction
+
+function! s:job_exit_cb(self, data) abort
+ let a:self.running = 0
+ let a:self.error = a:data != 0
+ call s:reap(a:self.name)
+ call s:tick()
+endfunction
+
+function! s:job_cb(fn, job, ch, data)
+ if !s:plug_window_exists() " plug window closed
+ return s:job_abort()
+ endif
+ call call(a:fn, [a:job, a:data])
+endfunction
+
+function! s:nvim_cb(job_id, data, event) dict abort
+ return (a:event == 'stdout' || a:event == 'stderr') ?
+ \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) :
+ \ s:job_cb('s:job_exit_cb', self, 0, a:data)
+endfunction
+
+function! s:spawn(name, cmd, opts)
+ let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''],
+ \ 'new': get(a:opts, 'new', 0) }
+ let s:jobs[a:name] = job
+
+ if s:nvim
+ if has_key(a:opts, 'dir')
+ let job.cwd = a:opts.dir
+ endif
+ let argv = a:cmd
+ call extend(job, {
+ \ 'on_stdout': function('s:nvim_cb'),
+ \ 'on_stderr': function('s:nvim_cb'),
+ \ 'on_exit': function('s:nvim_cb'),
+ \ })
+ let jid = s:plug_call('jobstart', argv, job)
+ if jid > 0
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = [jid < 0 ? argv[0].' is not executable' :
+ \ 'Invalid arguments (or job table is full)']
+ endif
+ elseif s:vim8
+ let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"script": 0})'))
+ if has_key(a:opts, 'dir')
+ let cmd = s:with_cd(cmd, a:opts.dir, 0)
+ endif
+ let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd]
+ let jid = job_start(s:is_win ? join(argv, ' ') : argv, {
+ \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'err_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]),
+ \ 'err_mode': 'raw',
+ \ 'out_mode': 'raw'
+ \})
+ if job_status(jid) == 'run'
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = ['Failed to start job']
+ endif
+ else
+ let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]))
+ let job.error = v:shell_error != 0
+ let job.running = 0
+ endif
+endfunction
+
+function! s:reap(name)
+ let job = s:jobs[a:name]
+ if job.error
+ call add(s:update.errors, a:name)
+ elseif get(job, 'new', 0)
+ let s:update.new[a:name] = 1
+ endif
+ let s:update.bar .= job.error ? 'x' : '='
+
+ let bullet = job.error ? 'x' : '-'
+ let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines)
+ call s:log(bullet, a:name, empty(result) ? 'OK' : result)
+ call s:bar()
+
+ call remove(s:jobs, a:name)
+endfunction
+
+function! s:bar()
+ if s:switch_in()
+ let total = len(s:update.all)
+ call setline(1, (s:update.pull ? 'Updating' : 'Installing').
+ \ ' plugins ('.len(s:update.bar).'/'.total.')')
+ call s:progress_bar(2, s:update.bar, total)
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:logpos(name)
+ let max = line('$')
+ for i in range(4, max > 4 ? max : 4)
+ if getline(i) =~# '^[-+x*] '.a:name.':'
+ for j in range(i + 1, max > 5 ? max : 5)
+ if getline(j) !~ '^ '
+ return [i, j - 1]
+ endif
+ endfor
+ return [i, i]
+ endif
+ endfor
+ return [0, 0]
+endfunction
+
+function! s:log(bullet, name, lines)
+ if s:switch_in()
+ let [b, e] = s:logpos(a:name)
+ if b > 0
+ silent execute printf('%d,%d d _', b, e)
+ if b > winheight('.')
+ let b = 4
+ endif
+ else
+ let b = 4
+ endif
+ " FIXME For some reason, nomodifiable is set after :d in vim8
+ setlocal modifiable
+ call append(b - 1, s:format_message(a:bullet, a:name, a:lines))
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:update_vim()
+ let s:jobs = {}
+
+ call s:bar()
+ call s:tick()
+endfunction
+
+function! s:tick()
+ let pull = s:update.pull
+ let prog = s:progress_opt(s:nvim || s:vim8)
+while 1 " Without TCO, Vim stack is bound to explode
+ if empty(s:update.todo)
+ if empty(s:jobs) && !s:update.fin
+ call s:update_finish()
+ let s:update.fin = 1
+ endif
+ return
+ endif
+
+ let name = keys(s:update.todo)[0]
+ let spec = remove(s:update.todo, name)
+ let new = empty(globpath(spec.dir, '.git', 1))
+
+ call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')
+ redraw
+
+ let has_tag = has_key(spec, 'tag')
+ if !new
+ let [error, _] = s:git_validate(spec, 0)
+ if empty(error)
+ if pull
+ let cmd = s:git_version_requirement(2) ? ['git', '-c', 'credential.helper=', 'fetch'] : ['git', 'fetch']
+ if has_tag && !empty(globpath(spec.dir, '.git/shallow'))
+ call extend(cmd, ['--depth', '99999999'])
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ call s:spawn(name, cmd, { 'dir': spec.dir })
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 }
+ endif
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 }
+ endif
+ else
+ let cmd = ['git', 'clone']
+ if !has_tag
+ call extend(cmd, s:clone_opt)
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ call s:spawn(name, extend(cmd, [spec.uri, s:trim(spec.dir)]), { 'new': 1 })
+ endif
+
+ if !s:jobs[name].running
+ call s:reap(name)
+ endif
+ if len(s:jobs) >= s:update.threads
+ break
+ endif
+endwhile
+endfunction
+
+function! s:update_python()
+let py_exe = has('python') ? 'python' : 'python3'
+execute py_exe "<< EOF"
+import datetime
+import functools
+import os
+try:
+ import queue
+except ImportError:
+ import Queue as queue
+import random
+import re
+import shutil
+import signal
+import subprocess
+import tempfile
+import threading as thr
+import time
+import traceback
+import vim
+
+G_NVIM = vim.eval("has('nvim')") == '1'
+G_PULL = vim.eval('s:update.pull') == '1'
+G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1
+G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)'))
+G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt'))
+G_PROGRESS = vim.eval('s:progress_opt(1)')
+G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads'))
+G_STOP = thr.Event()
+G_IS_WIN = vim.eval('s:is_win') == '1'
+
+class PlugError(Exception):
+ def __init__(self, msg):
+ self.msg = msg
+class CmdTimedOut(PlugError):
+ pass
+class CmdFailed(PlugError):
+ pass
+class InvalidURI(PlugError):
+ pass
+class Action(object):
+ INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-']
+
+class Buffer(object):
+ def __init__(self, lock, num_plugs, is_pull):
+ self.bar = ''
+ self.event = 'Updating' if is_pull else 'Installing'
+ self.lock = lock
+ self.maxy = int(vim.eval('winheight(".")'))
+ self.num_plugs = num_plugs
+
+ def __where(self, name):
+ """ Find first line with name in current buffer. Return line num. """
+ found, lnum = False, 0
+ matcher = re.compile('^[-+x*] {0}:'.format(name))
+ for line in vim.current.buffer:
+ if matcher.search(line) is not None:
+ found = True
+ break
+ lnum += 1
+
+ if not found:
+ lnum = -1
+ return lnum
+
+ def header(self):
+ curbuf = vim.current.buffer
+ curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs)
+
+ num_spaces = self.num_plugs - len(self.bar)
+ curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ')
+
+ with self.lock:
+ vim.command('normal! 2G')
+ vim.command('redraw')
+
+ def write(self, action, name, lines):
+ first, rest = lines[0], lines[1:]
+ msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)]
+ msg.extend([' ' + line for line in rest])
+
+ try:
+ if action == Action.ERROR:
+ self.bar += 'x'
+ vim.command("call add(s:update.errors, '{0}')".format(name))
+ elif action == Action.DONE:
+ self.bar += '='
+
+ curbuf = vim.current.buffer
+ lnum = self.__where(name)
+ if lnum != -1: # Found matching line num
+ del curbuf[lnum]
+ if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]):
+ lnum = 3
+ else:
+ lnum = 3
+ curbuf.append(msg, lnum)
+
+ self.header()
+ except vim.error:
+ pass
+
+class Command(object):
+ CD = 'cd /d' if G_IS_WIN else 'cd'
+
+ def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None):
+ self.cmd = cmd
+ if cmd_dir:
+ self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd)
+ self.timeout = timeout
+ self.callback = cb if cb else (lambda msg: None)
+ self.clean = clean if clean else (lambda: None)
+ self.proc = None
+
+ @property
+ def alive(self):
+ """ Returns true only if command still running. """
+ return self.proc and self.proc.poll() is None
+
+ def execute(self, ntries=3):
+ """ Execute the command with ntries if CmdTimedOut.
+ Returns the output of the command if no Exception.
+ """
+ attempt, finished, limit = 0, False, self.timeout
+
+ while not finished:
+ try:
+ attempt += 1
+ result = self.try_command()
+ finished = True
+ return result
+ except CmdTimedOut:
+ if attempt != ntries:
+ self.notify_retry()
+ self.timeout += limit
+ else:
+ raise
+
+ def notify_retry(self):
+ """ Retry required for command, notify user. """
+ for count in range(3, 0, -1):
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+ msg = 'Timeout. Will retry in {0} second{1} ...'.format(
+ count, 's' if count != 1 else '')
+ self.callback([msg])
+ time.sleep(1)
+ self.callback(['Retrying ...'])
+
+ def try_command(self):
+ """ Execute a cmd & poll for callback. Returns list of output.
+ Raises CmdFailed -> return code for Popen isn't 0
+ Raises CmdTimedOut -> command exceeded timeout without new output
+ """
+ first_line = True
+
+ try:
+ tfile = tempfile.NamedTemporaryFile(mode='w+b')
+ preexec_fn = not G_IS_WIN and os.setsid or None
+ self.proc = subprocess.Popen(self.cmd, stdout=tfile,
+ stderr=subprocess.STDOUT,
+ stdin=subprocess.PIPE, shell=True,
+ preexec_fn=preexec_fn)
+ thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,))
+ thrd.start()
+
+ thread_not_started = True
+ while thread_not_started:
+ try:
+ thrd.join(0.1)
+ thread_not_started = False
+ except RuntimeError:
+ pass
+
+ while self.alive:
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+
+ if first_line or random.random() < G_LOG_PROB:
+ first_line = False
+ line = '' if G_IS_WIN else nonblock_read(tfile.name)
+ if line:
+ self.callback([line])
+
+ time_diff = time.time() - os.path.getmtime(tfile.name)
+ if time_diff > self.timeout:
+ raise CmdTimedOut(['Timeout!'])
+
+ thrd.join(0.5)
+
+ tfile.seek(0)
+ result = [line.decode('utf-8', 'replace').rstrip() for line in tfile]
+
+ if self.proc.returncode != 0:
+ raise CmdFailed([''] + result)
+
+ return result
+ except:
+ self.terminate()
+ raise
+
+ def terminate(self):
+ """ Terminate process and cleanup. """
+ if self.alive:
+ if G_IS_WIN:
+ os.kill(self.proc.pid, signal.SIGINT)
+ else:
+ os.killpg(self.proc.pid, signal.SIGTERM)
+ self.clean()
+
+class Plugin(object):
+ def __init__(self, name, args, buf_q, lock):
+ self.name = name
+ self.args = args
+ self.buf_q = buf_q
+ self.lock = lock
+ self.tag = args.get('tag', 0)
+
+ def manage(self):
+ try:
+ if os.path.exists(self.args['dir']):
+ self.update()
+ else:
+ self.install()
+ with self.lock:
+ thread_vim_command("let s:update.new['{0}'] = 1".format(self.name))
+ except PlugError as exc:
+ self.write(Action.ERROR, self.name, exc.msg)
+ except KeyboardInterrupt:
+ G_STOP.set()
+ self.write(Action.ERROR, self.name, ['Interrupted!'])
+ except:
+ # Any exception except those above print stack trace
+ msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip())
+ self.write(Action.ERROR, self.name, msg.split('\n'))
+ raise
+
+ def install(self):
+ target = self.args['dir']
+ if target[-1] == '\\':
+ target = target[0:-1]
+
+ def clean(target):
+ def _clean():
+ try:
+ shutil.rmtree(target)
+ except OSError:
+ pass
+ return _clean
+
+ self.write(Action.INSTALL, self.name, ['Installing ...'])
+ callback = functools.partial(self.write, Action.INSTALL, self.name)
+ cmd = 'git clone {0} {1} {2} {3} 2>&1'.format(
+ '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'],
+ esc(target))
+ com = Command(cmd, None, G_TIMEOUT, callback, clean(target))
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+
+ def repo_uri(self):
+ cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url'
+ command = Command(cmd, self.args['dir'], G_TIMEOUT,)
+ result = command.execute(G_RETRIES)
+ return result[-1]
+
+ def update(self):
+ actual_uri = self.repo_uri()
+ expect_uri = self.args['uri']
+ regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$')
+ ma = regex.match(actual_uri)
+ mb = regex.match(expect_uri)
+ if ma is None or mb is None or ma.groups() != mb.groups():
+ msg = ['',
+ 'Invalid URI: {0}'.format(actual_uri),
+ 'Expected {0}'.format(expect_uri),
+ 'PlugClean required.']
+ raise InvalidURI(msg)
+
+ if G_PULL:
+ self.write(Action.UPDATE, self.name, ['Updating ...'])
+ callback = functools.partial(self.write, Action.UPDATE, self.name)
+ fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else ''
+ cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS)
+ com = Command(cmd, self.args['dir'], G_TIMEOUT, callback)
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+ else:
+ self.write(Action.DONE, self.name, ['Already installed'])
+
+ def write(self, action, name, msg):
+ self.buf_q.put((action, name, msg))
+
+class PlugThread(thr.Thread):
+ def __init__(self, tname, args):
+ super(PlugThread, self).__init__()
+ self.tname = tname
+ self.args = args
+
+ def run(self):
+ thr.current_thread().name = self.tname
+ buf_q, work_q, lock = self.args
+
+ try:
+ while not G_STOP.is_set():
+ name, args = work_q.get_nowait()
+ plug = Plugin(name, args, buf_q, lock)
+ plug.manage()
+ work_q.task_done()
+ except queue.Empty:
+ pass
+
+class RefreshThread(thr.Thread):
+ def __init__(self, lock):
+ super(RefreshThread, self).__init__()
+ self.lock = lock
+ self.running = True
+
+ def run(self):
+ while self.running:
+ with self.lock:
+ thread_vim_command('noautocmd normal! a')
+ time.sleep(0.33)
+
+ def stop(self):
+ self.running = False
+
+if G_NVIM:
+ def thread_vim_command(cmd):
+ vim.session.threadsafe_call(lambda: vim.command(cmd))
+else:
+ def thread_vim_command(cmd):
+ vim.command(cmd)
+
+def esc(name):
+ return '"' + name.replace('"', '\"') + '"'
+
+def nonblock_read(fname):
+ """ Read a file with nonblock flag. Return the last line. """
+ fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK)
+ buf = os.read(fread, 100000).decode('utf-8', 'replace')
+ os.close(fread)
+
+ line = buf.rstrip('\r\n')
+ left = max(line.rfind('\r'), line.rfind('\n'))
+ if left != -1:
+ left += 1
+ line = line[left:]
+
+ return line
+
+def main():
+ thr.current_thread().name = 'main'
+ nthreads = int(vim.eval('s:update.threads'))
+ plugs = vim.eval('s:update.todo')
+ mac_gui = vim.eval('s:mac_gui') == '1'
+
+ lock = thr.Lock()
+ buf = Buffer(lock, len(plugs), G_PULL)
+ buf_q, work_q = queue.Queue(), queue.Queue()
+ for work in plugs.items():
+ work_q.put(work)
+
+ start_cnt = thr.active_count()
+ for num in range(nthreads):
+ tname = 'PlugT-{0:02}'.format(num)
+ thread = PlugThread(tname, (buf_q, work_q, lock))
+ thread.start()
+ if mac_gui:
+ rthread = RefreshThread(lock)
+ rthread.start()
+
+ while not buf_q.empty() or thr.active_count() != start_cnt:
+ try:
+ action, name, msg = buf_q.get(True, 0.25)
+ buf.write(action, name, ['OK'] if not msg else msg)
+ buf_q.task_done()
+ except queue.Empty:
+ pass
+ except KeyboardInterrupt:
+ G_STOP.set()
+
+ if mac_gui:
+ rthread.stop()
+ rthread.join()
+
+main()
+EOF
+endfunction
+
+function! s:update_ruby()
+ ruby << EOF
+ module PlugStream
+ SEP = ["\r", "\n", nil]
+ def get_line
+ buffer = ''
+ loop do
+ char = readchar rescue return
+ if SEP.include? char.chr
+ buffer << $/
+ break
+ else
+ buffer << char
+ end
+ end
+ buffer
+ end
+ end unless defined?(PlugStream)
+
+ def esc arg
+ %["#{arg.gsub('"', '\"')}"]
+ end
+
+ def killall pid
+ pids = [pid]
+ if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil }
+ else
+ unless `which pgrep 2> /dev/null`.empty?
+ children = pids
+ until children.empty?
+ children = children.map { |pid|
+ `pgrep -P #{pid}`.lines.map { |l| l.chomp }
+ }.flatten
+ pids += children
+ end
+ end
+ pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil }
+ end
+ end
+
+ def compare_git_uri a, b
+ regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$}
+ regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1)
+ end
+
+ require 'thread'
+ require 'fileutils'
+ require 'timeout'
+ running = true
+ iswin = VIM::evaluate('s:is_win').to_i == 1
+ pull = VIM::evaluate('s:update.pull').to_i == 1
+ base = VIM::evaluate('g:plug_home')
+ all = VIM::evaluate('s:update.todo')
+ limit = VIM::evaluate('get(g:, "plug_timeout", 60)')
+ tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1
+ nthr = VIM::evaluate('s:update.threads').to_i
+ maxy = VIM::evaluate('winheight(".")').to_i
+ vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/
+ cd = iswin ? 'cd /d' : 'cd'
+ tot = VIM::evaluate('len(s:update.todo)') || 0
+ bar = ''
+ skip = 'Already installed'
+ mtx = Mutex.new
+ take1 = proc { mtx.synchronize { running && all.shift } }
+ logh = proc {
+ cnt = bar.length
+ $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})"
+ $curbuf[2] = '[' + bar.ljust(tot) + ']'
+ VIM::command('normal! 2G')
+ VIM::command('redraw')
+ }
+ where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } }
+ log = proc { |name, result, type|
+ mtx.synchronize do
+ ing = ![true, false].include?(type)
+ bar += type ? '=' : 'x' unless ing
+ b = case type
+ when :install then '+' when :update then '*'
+ when true, nil then '-' else
+ VIM::command("call add(s:update.errors, '#{name}')")
+ 'x'
+ end
+ result =
+ if type || type.nil?
+ ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"]
+ elsif result =~ /^Interrupted|^Timeout/
+ ["#{b} #{name}: #{result}"]
+ else
+ ["#{b} #{name}"] + result.lines.map { |l| " " << l }
+ end
+ if lnum = where.call(name)
+ $curbuf.delete lnum
+ lnum = 4 if ing && lnum > maxy
+ end
+ result.each_with_index do |line, offset|
+ $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp)
+ end
+ logh.call
+ end
+ }
+ bt = proc { |cmd, name, type, cleanup|
+ tried = timeout = 0
+ begin
+ tried += 1
+ timeout += limit
+ fd = nil
+ data = ''
+ if iswin
+ Timeout::timeout(timeout) do
+ tmp = VIM::evaluate('tempname()')
+ system("(#{cmd}) > #{tmp}")
+ data = File.read(tmp).chomp
+ File.unlink tmp rescue nil
+ end
+ else
+ fd = IO.popen(cmd).extend(PlugStream)
+ first_line = true
+ log_prob = 1.0 / nthr
+ while line = Timeout::timeout(timeout) { fd.get_line }
+ data << line
+ log.call name, line.chomp, type if name && (first_line || rand < log_prob)
+ first_line = false
+ end
+ fd.close
+ end
+ [$? == 0, data.chomp]
+ rescue Timeout::Error, Interrupt => e
+ if fd && !fd.closed?
+ killall fd.pid
+ fd.close
+ end
+ cleanup.call if cleanup
+ if e.is_a?(Timeout::Error) && tried < tries
+ 3.downto(1) do |countdown|
+ s = countdown > 1 ? 's' : ''
+ log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type
+ sleep 1
+ end
+ log.call name, 'Retrying ...', type
+ retry
+ end
+ [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"]
+ end
+ }
+ main = Thread.current
+ threads = []
+ watcher = Thread.new {
+ if vim7
+ while VIM::evaluate('getchar(1)')
+ sleep 0.1
+ end
+ else
+ require 'io/console' # >= Ruby 1.9
+ nil until IO.console.getch == 3.chr
+ end
+ mtx.synchronize do
+ running = false
+ threads.each { |t| t.raise Interrupt } unless vim7
+ end
+ threads.each { |t| t.join rescue nil }
+ main.kill
+ }
+ refresh = Thread.new {
+ while true
+ mtx.synchronize do
+ break unless running
+ VIM::command('noautocmd normal! a')
+ end
+ sleep 0.2
+ end
+ } if VIM::evaluate('s:mac_gui') == 1
+
+ clone_opt = VIM::evaluate('s:clone_opt').join(' ')
+ progress = VIM::evaluate('s:progress_opt(1)')
+ nthr.times do
+ mtx.synchronize do
+ threads << Thread.new {
+ while pair = take1.call
+ name = pair.first
+ dir, uri, tag = pair.last.values_at *%w[dir uri tag]
+ exists = File.directory? dir
+ ok, result =
+ if exists
+ chdir = "#{cd} #{iswin ? dir : esc(dir)}"
+ ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil
+ current_uri = data.lines.to_a.last
+ if !ret
+ if data =~ /^Interrupted|^Timeout/
+ [false, data]
+ else
+ [false, [data.chomp, "PlugClean required."].join($/)]
+ end
+ elsif !compare_git_uri(current_uri, uri)
+ [false, ["Invalid URI: #{current_uri}",
+ "Expected: #{uri}",
+ "PlugClean required."].join($/)]
+ else
+ if pull
+ log.call name, 'Updating ...', :update
+ fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : ''
+ bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil
+ else
+ [true, skip]
+ end
+ end
+ else
+ d = esc dir.sub(%r{[\\/]+$}, '')
+ log.call name, 'Installing ...', :install
+ bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc {
+ FileUtils.rm_rf dir
+ }
+ end
+ mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok
+ log.call name, result, ok
+ end
+ } if running
+ end
+ end
+ threads.each { |t| t.join rescue nil }
+ logh.call
+ refresh.kill if refresh
+ watcher.kill
+EOF
+endfunction
+
+function! s:shellesc_cmd(arg, script)
+ let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g')
+ return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g')
+endfunction
+
+function! s:shellesc_ps1(arg)
+ return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'"
+endfunction
+
+function! s:shellesc_sh(arg)
+ return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'"
+endfunction
+
+" Escape the shell argument based on the shell.
+" Vim and Neovim's shellescape() are insufficient.
+" 1. shellslash determines whether to use single/double quotes.
+" Double-quote escaping is fragile for cmd.exe.
+" 2. It does not work for powershell.
+" 3. It does not work for *sh shells if the command is executed
+" via cmd.exe (ie. cmd.exe /c sh -c command command_args)
+" 4. It does not support batchfile syntax.
+"
+" Accepts an optional dictionary with the following keys:
+" - shell: same as Vim/Neovim 'shell' option.
+" If unset, fallback to 'cmd.exe' on Windows or 'sh'.
+" - script: If truthy and shell is cmd.exe, escape for batchfile syntax.
+function! plug#shellescape(arg, ...)
+ if a:arg =~# '^[A-Za-z0-9_/:.-]\+$'
+ return a:arg
+ endif
+ let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}
+ let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh')
+ let script = get(opts, 'script', 1)
+ if shell =~# 'cmd\(\.exe\)\?$'
+ return s:shellesc_cmd(a:arg, script)
+ elseif s:is_powershell(shell)
+ return s:shellesc_ps1(a:arg)
+ endif
+ return s:shellesc_sh(a:arg)
+endfunction
+
+function! s:glob_dir(path)
+ return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
+endfunction
+
+function! s:progress_bar(line, bar, total)
+ call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']')
+endfunction
+
+function! s:compare_git_uri(a, b)
+ " See `git help clone'
+ " https:// [user@] github.com[:port] / junegunn/vim-plug [.git]
+ " [git@] github.com[:port] : junegunn/vim-plug [.git]
+ " file:// / junegunn/vim-plug [/]
+ " / junegunn/vim-plug [/]
+ let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$'
+ let ma = matchlist(a:a, pat)
+ let mb = matchlist(a:b, pat)
+ return ma[1:2] ==# mb[1:2]
+endfunction
+
+function! s:format_message(bullet, name, message)
+ if a:bullet != 'x'
+ return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))]
+ else
+ let lines = map(s:lines(a:message), '" ".v:val')
+ return extend([printf('x %s:', a:name)], lines)
+ endif
+endfunction
+
+function! s:with_cd(cmd, dir, ...)
+ let script = a:0 > 0 ? a:1 : 1
+ return printf('cd%s %s && %s', s:is_win ? ' /d' : '', plug#shellescape(a:dir, {'script': script}), a:cmd)
+endfunction
+
+function! s:system(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ if type(a:cmd) == s:TYPE.list
+ " Neovim's system() supports list argument to bypass the shell
+ " but it cannot set the working directory for the command.
+ " Assume that the command does not rely on the shell.
+ if has('nvim') && a:0 == 0
+ return system(a:cmd)
+ endif
+ let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ else
+ let cmd = a:cmd
+ endif
+ if a:0 > 0
+ let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list)
+ endif
+ if s:is_win && type(a:cmd) != s:TYPE.list
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ return system(cmd)
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+endfunction
+
+function! s:system_chomp(...)
+ let ret = call('s:system', a:000)
+ return v:shell_error ? '' : substitute(ret, '\n$', '', '')
+endfunction
+
+function! s:git_validate(spec, check_branch)
+ let err = ''
+ if isdirectory(a:spec.dir)
+ let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)]
+ let remote = result[-1]
+ if empty(remote)
+ let err = join([remote, 'PlugClean required.'], "\n")
+ elseif !s:compare_git_uri(remote, a:spec.uri)
+ let err = join(['Invalid URI: '.remote,
+ \ 'Expected: '.a:spec.uri,
+ \ 'PlugClean required.'], "\n")
+ elseif a:check_branch && has_key(a:spec, 'commit')
+ let sha = s:git_revision(a:spec.dir)
+ if empty(sha)
+ let err = join(add(result, 'PlugClean required.'), "\n")
+ elseif !s:hash_match(sha, a:spec.commit)
+ let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',
+ \ a:spec.commit[:6], sha[:6]),
+ \ 'PlugUpdate required.'], "\n")
+ endif
+ elseif a:check_branch
+ let current_branch = result[0]
+ " Check tag
+ let origin_branch = s:git_origin_branch(a:spec)
+ if has_key(a:spec, 'tag')
+ let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
+ if a:spec.tag !=# tag && a:spec.tag !~ '\*'
+ let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
+ \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
+ endif
+ " Check branch
+ elseif origin_branch !=# current_branch
+ let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',
+ \ current_branch, origin_branch)
+ endif
+ if empty(err)
+ let [ahead, behind] = split(s:lastline(s:system([
+ \ 'git', 'rev-list', '--count', '--left-right',
+ \ printf('HEAD...origin/%s', origin_branch)
+ \ ], a:spec.dir)), '\t')
+ if !v:shell_error && ahead
+ if behind
+ " Only mention PlugClean if diverged, otherwise it's likely to be
+ " pushable (and probably not that messed up).
+ let err = printf(
+ \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n"
+ \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind)
+ else
+ let err = printf("Ahead of origin/%s by %d commit(s).\n"
+ \ .'Cannot update until local changes are pushed.',
+ \ origin_branch, ahead)
+ endif
+ endif
+ endif
+ endif
+ else
+ let err = 'Not found'
+ endif
+ return [err, err =~# 'PlugClean']
+endfunction
+
+function! s:rm_rf(dir)
+ if isdirectory(a:dir)
+ return s:system(s:is_win
+ \ ? 'rmdir /S /Q '.plug#shellescape(a:dir)
+ \ : ['rm', '-rf', a:dir])
+ endif
+endfunction
+
+function! s:clean(force)
+ call s:prepare()
+ call append(0, 'Searching for invalid plugins in '.g:plug_home)
+ call append(1, '')
+
+ " List of valid directories
+ let dirs = []
+ let errs = {}
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ if !s:is_managed(name)
+ call add(dirs, spec.dir)
+ else
+ let [err, clean] = s:git_validate(spec, 1)
+ if clean
+ let errs[spec.dir] = s:lines(err)[0]
+ else
+ call add(dirs, spec.dir)
+ endif
+ endif
+ let cnt += 1
+ call s:progress_bar(2, repeat('=', cnt), total)
+ normal! 2G
+ redraw
+ endfor
+
+ let allowed = {}
+ for dir in dirs
+ let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1
+ let allowed[dir] = 1
+ for child in s:glob_dir(dir)
+ let allowed[child] = 1
+ endfor
+ endfor
+
+ let todo = []
+ let found = sort(s:glob_dir(g:plug_home))
+ while !empty(found)
+ let f = remove(found, 0)
+ if !has_key(allowed, f) && isdirectory(f)
+ call add(todo, f)
+ call append(line('$'), '- ' . f)
+ if has_key(errs, f)
+ call append(line('$'), ' ' . errs[f])
+ endif
+ let found = filter(found, 'stridx(v:val, f) != 0')
+ end
+ endwhile
+
+ 4
+ redraw
+ if empty(todo)
+ call append(line('$'), 'Already clean.')
+ else
+ let s:clean_count = 0
+ call append(3, ['Directories to delete:', ''])
+ redraw!
+ if a:force || s:ask_no_interrupt('Delete all directories?')
+ call s:delete([6, line('$')], 1)
+ else
+ call setline(4, 'Cancelled.')
+ nnoremap <silent> <buffer> d :set opfunc=<sid>delete_op<cr>g@
+ nmap <silent> <buffer> dd d_
+ xnoremap <silent> <buffer> d :<c-u>call <sid>delete_op(visualmode(), 1)<cr>
+ echo 'Delete the lines (d{motion}) to delete the corresponding directories'
+ endif
+ endif
+ 4
+ setlocal nomodifiable
+endfunction
+
+function! s:delete_op(type, ...)
+ call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0)
+endfunction
+
+function! s:delete(range, force)
+ let [l1, l2] = a:range
+ let force = a:force
+ let err_count = 0
+ while l1 <= l2
+ let line = getline(l1)
+ if line =~ '^- ' && isdirectory(line[2:])
+ execute l1
+ redraw!
+ let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1)
+ let force = force || answer > 1
+ if answer
+ let err = s:rm_rf(line[2:])
+ setlocal modifiable
+ if empty(err)
+ call setline(l1, '~'.line[1:])
+ let s:clean_count += 1
+ else
+ delete _
+ call append(l1 - 1, s:format_message('x', line[1:], err))
+ let l2 += len(s:lines(err))
+ let err_count += 1
+ endif
+ let msg = printf('Removed %d directories.', s:clean_count)
+ if err_count > 0
+ let msg .= printf(' Failed to remove %d directories.', err_count)
+ endif
+ call setline(4, msg)
+ setlocal nomodifiable
+ endif
+ endif
+ let l1 += 1
+ endwhile
+endfunction
+
+function! s:upgrade()
+ echo 'Downloading the latest version of vim-plug'
+ redraw
+ let tmp = s:plug_tempname()
+ let new = tmp . '/plug.vim'
+
+ try
+ let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp])
+ if v:shell_error
+ return s:err('Error upgrading vim-plug: '. out)
+ endif
+
+ if readfile(s:me) ==# readfile(new)
+ echo 'vim-plug is already up-to-date'
+ return 0
+ else
+ call rename(s:me, s:me . '.old')
+ call rename(new, s:me)
+ unlet g:loaded_plug
+ echo 'vim-plug has been upgraded'
+ return 1
+ endif
+ finally
+ silent! call s:rm_rf(tmp)
+ endtry
+endfunction
+
+function! s:upgrade_specs()
+ for spec in values(g:plugs)
+ let spec.frozen = get(spec, 'frozen', 0)
+ endfor
+endfunction
+
+function! s:status()
+ call s:prepare()
+ call append(0, 'Checking plugins')
+ call append(1, '')
+
+ let ecnt = 0
+ let unloaded = 0
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ let is_dir = isdirectory(spec.dir)
+ if has_key(spec, 'uri')
+ if is_dir
+ let [err, _] = s:git_validate(spec, 1)
+ let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]
+ else
+ let [valid, msg] = [0, 'Not found. Try PlugInstall.']
+ endif
+ else
+ if is_dir
+ let [valid, msg] = [1, 'OK']
+ else
+ let [valid, msg] = [0, 'Not found.']
+ endif
+ endif
+ let cnt += 1
+ let ecnt += !valid
+ " `s:loaded` entry can be missing if PlugUpgraded
+ if is_dir && get(s:loaded, name, -1) == 0
+ let unloaded = 1
+ let msg .= ' (not loaded)'
+ endif
+ call s:progress_bar(2, repeat('=', cnt), total)
+ call append(3, s:format_message(valid ? '-' : 'x', name, msg))
+ normal! 2G
+ redraw
+ endfor
+ call setline(1, 'Finished. '.ecnt.' error(s).')
+ normal! gg
+ setlocal nomodifiable
+ if unloaded
+ echo "Press 'L' on each line to load plugin, or 'U' to update"
+ nnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ xnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ end
+endfunction
+
+function! s:extract_name(str, prefix, suffix)
+ return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$')
+endfunction
+
+function! s:status_load(lnum)
+ let line = getline(a:lnum)
+ let name = s:extract_name(line, '-', '(not loaded)')
+ if !empty(name)
+ call plug#load(name)
+ setlocal modifiable
+ call setline(a:lnum, substitute(line, ' (not loaded)$', '', ''))
+ setlocal nomodifiable
+ endif
+endfunction
+
+function! s:status_update() range
+ let lines = getline(a:firstline, a:lastline)
+ let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)')
+ if !empty(names)
+ echo
+ execute 'PlugUpdate' join(names)
+ endif
+endfunction
+
+function! s:is_preview_window_open()
+ silent! wincmd P
+ if &previewwindow
+ wincmd p
+ return 1
+ endif
+endfunction
+
+function! s:find_name(lnum)
+ for lnum in reverse(range(1, a:lnum))
+ let line = getline(lnum)
+ if empty(line)
+ return ''
+ endif
+ let name = s:extract_name(line, '-', '')
+ if !empty(name)
+ return name
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:preview_commit()
+ if b:plug_preview < 0
+ let b:plug_preview = !s:is_preview_window_open()
+ endif
+
+ let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}')
+ if empty(sha)
+ let name = matchstr(getline('.'), '^- \zs[^:]*\ze:$')
+ if empty(name)
+ return
+ endif
+ let title = 'HEAD@{1}..'
+ let command = 'git diff --no-color HEAD@{1}'
+ else
+ let title = sha
+ let command = 'git show --no-color --pretty=medium '.sha
+ let name = s:find_name(line('.'))
+ endif
+
+ if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir)
+ return
+ endif
+
+ if exists('g:plug_pwindow') && !s:is_preview_window_open()
+ execute g:plug_pwindow
+ execute 'e' title
+ else
+ execute 'pedit' title
+ wincmd P
+ endif
+ setlocal previewwindow filetype=git buftype=nofile bufhidden=wipe nobuflisted modifiable
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && '.command
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ execute 'silent %!' cmd
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ setlocal nomodifiable
+ nnoremap <silent> <buffer> q :q<cr>
+ wincmd p
+endfunction
+
+function! s:section(flags)
+ call search('\(^[x-] \)\@<=[^:]\+:', a:flags)
+endfunction
+
+function! s:format_git_log(line)
+ let indent = ' '
+ let tokens = split(a:line, nr2char(1))
+ if len(tokens) != 5
+ return indent.substitute(a:line, '\s*$', '', '')
+ endif
+ let [graph, sha, refs, subject, date] = tokens
+ let tag = matchstr(refs, 'tag: [^,)]\+')
+ let tag = empty(tag) ? ' ' : ' ('.tag.') '
+ return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date)
+endfunction
+
+function! s:append_ul(lnum, text)
+ call append(a:lnum, ['', a:text, repeat('-', len(a:text))])
+endfunction
+
+function! s:diff()
+ call s:prepare()
+ call append(0, ['Collecting changes ...', ''])
+ let cnts = [0, 0]
+ let bar = ''
+ let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)')
+ call s:progress_bar(2, bar, len(total))
+ for origin in [1, 0]
+ let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))'))))
+ if empty(plugs)
+ continue
+ endif
+ call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
+ for [k, v] in plugs
+ let branch = s:git_origin_branch(v)
+ if len(branch)
+ let range = origin ? '..origin/'.branch : 'HEAD@{1}..'
+ let cmd = ['git', 'log', '--graph', '--color=never']
+ if s:git_version_requirement(2, 10, 0)
+ call add(cmd, '--no-show-signature')
+ endif
+ call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])
+ if has_key(v, 'rtp')
+ call extend(cmd, ['--', v.rtp])
+ endif
+ let diff = s:system_chomp(cmd, v.dir)
+ if !empty(diff)
+ let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
+ call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
+ let cnts[origin] += 1
+ endif
+ endif
+ let bar .= '='
+ call s:progress_bar(2, bar, len(total))
+ normal! 2G
+ redraw
+ endfor
+ if !cnts[origin]
+ call append(5, ['', 'N/A'])
+ endif
+ endfor
+ call setline(1, printf('%d plugin(s) updated.', cnts[0])
+ \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : ''))
+
+ if cnts[0] || cnts[1]
+ nnoremap <silent> <buffer> <plug>(plug-preview) :silent! call <SID>preview_commit()<cr>
+ if empty(maparg("\<cr>", 'n'))
+ nmap <buffer> <cr> <plug>(plug-preview)
+ endif
+ if empty(maparg('o', 'n'))
+ nmap <buffer> o <plug>(plug-preview)
+ endif
+ endif
+ if cnts[0]
+ nnoremap <silent> <buffer> X :call <SID>revert()<cr>
+ echo "Press 'X' on each block to revert the update"
+ endif
+ normal! gg
+ setlocal nomodifiable
+endfunction
+
+function! s:revert()
+ if search('^Pending updates', 'bnW')
+ return
+ endif
+
+ let name = s:find_name(line('.'))
+ if empty(name) || !has_key(g:plugs, name) ||
+ \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y'
+ return
+ endif
+
+ call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir)
+ setlocal modifiable
+ normal! "_dap
+ setlocal nomodifiable
+ echo 'Reverted'
+endfunction
+
+function! s:snapshot(force, ...) abort
+ call s:prepare()
+ setf vim
+ call append(0, ['" Generated by vim-plug',
+ \ '" '.strftime("%c"),
+ \ '" :source this file in vim to restore the snapshot',
+ \ '" or execute: vim -S snapshot.vim',
+ \ '', '', 'PlugUpdate!'])
+ 1
+ let anchor = line('$') - 3
+ let names = sort(keys(filter(copy(g:plugs),
+ \'has_key(v:val, "uri") && isdirectory(v:val.dir)')))
+ for name in reverse(names)
+ let sha = has_key(g:plugs[name], 'commit') ? g:plugs[name].commit : s:git_revision(g:plugs[name].dir)
+ if !empty(sha)
+ call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))
+ redraw
+ endif
+ endfor
+
+ if a:0 > 0
+ let fn = s:plug_expand(a:1)
+ if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?'))
+ return
+ endif
+ call writefile(getline(1, '$'), fn)
+ echo 'Saved as '.a:1
+ silent execute 'e' s:esc(fn)
+ setf vim
+ endif
+endfunction
+
+function! s:split_rtp()
+ return split(&rtp, '\\\@<!,')
+endfunction
+
+let s:first_rtp = s:escrtp(get(s:split_rtp(), 0, ''))
+let s:last_rtp = s:escrtp(get(s:split_rtp(), -1, ''))
+
+if exists('g:plugs')
+ let g:plugs_order = get(g:, 'plugs_order', keys(g:plugs))
+ call s:upgrade_specs()
+ call s:define_commands()
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/nvim/init.vim b/nvim/init.vim
new file mode 100644
index 0000000..0aa9c34
--- /dev/null
+++ b/nvim/init.vim
@@ -0,0 +1,89 @@
+set nocompatible
+
+" vim-plugged
+call plug#begin()
+ Plug 'itchyny/lightline.vim'
+ Plug 'junegunn/goyo.vim'
+ Plug 'mattn/emmet-vim'
+ Plug 'neoclide/coc.nvim', {'branch': 'release'}
+ Plug 'preservim/nerdtree'
+ Plug 'ryanoasis/vim-devicons'
+ Plug 'bluz71/vim-nightfly-guicolors'
+ Plug 'morhetz/gruvbox'
+ Plug 'dylanaraps/wal.vim'
+call plug#end()
+
+" Lightline Integration
+ let g:lightline = {'colorscheme': 'nightfly'}
+
+" General
+ set laststatus=2
+ set encoding=UTF-8
+ set bg=dark
+ syntax on
+ set nohlsearch
+ set cursorline
+ set incsearch
+ set clipboard=unnamedplus
+ set tabstop=4
+ set softtabstop=4
+ set shiftwidth=4
+ set expandtab
+ set autoindent
+ set fileformat=unix
+ set number
+ set relativenumber
+ set nowrap
+ set noswapfile
+ set noshowmode
+ set incsearch
+ set scrolloff=8
+
+colorscheme wal
+
+" Autoload
+augroup remember_folds
+ autocmd!
+ autocmd BufWinLeave * mkview
+ autocmd BufWinEnter * silent! loadview
+augroup END
+
+
+" Keymaps
+ let mapleader = " "
+ vnoremap <C-c> "+y
+ map <C-p> "+P
+ let g:user_emmet_leader_key=','
+ map <leader>h :wincmd h<CR>
+ map <leader>j :wincmd j<CR>
+ map <leader>k :wincmd k<CR>
+ map <leader>l :wincmd l<CR>
+ nnoremap <leader>nt :NERDTreeToggle %:p:h<CR>
+
+" NERDTree
+ map <F2> :NERDTreeToggle<CR>
+ nnoremap <leader>nt :NERDTree %:p:h<CR>
+
+" Goyo
+ nnoremap <leader>g :Goyo<CR>
+
+function! s:goyo_enter()
+ set linebreak
+ set spell spelllang=en_us
+ HexokinaseTurnOff
+endfunction
+
+function! s:goyo_leave()
+ set nolinebreak
+ set nolinebreak
+ HexokinaseTurnOn
+endfunction
+
+" CoC
+" Tab navigation and confirmation
+inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
+inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>" Tab autocompletion
+inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"
+
+" Remove Whitespaces After Closing File
+autocmd BufWritePre *.sh :%s/\s\+$//e
diff --git a/nvim/plugged/coc.nvim b/nvim/plugged/coc.nvim
new file mode 160000
+Subproject 77e8e82646170091843d9e6d84b0be465405a96
diff --git a/nvim/plugged/emmet-vim b/nvim/plugged/emmet-vim
new file mode 160000
+Subproject def5d57a1ae5afb1b96ebe83c4652d1c03640f4
diff --git a/nvim/plugged/goyo.vim b/nvim/plugged/goyo.vim
new file mode 160000
+Subproject a9c7283dce60ffcdec952384f6451ff42f8914f
diff --git a/nvim/plugged/gruvbox b/nvim/plugged/gruvbox
new file mode 160000
+Subproject bf2885a95efdad7bd5e4794dd0213917770d79b
diff --git a/nvim/plugged/lightline.vim b/nvim/plugged/lightline.vim
new file mode 160000
+Subproject 11931e2de42cb1a14887a002a874f0b2daf12bc
diff --git a/nvim/plugged/nerdtree b/nvim/plugged/nerdtree
new file mode 160000
+Subproject eed488b1cd1867bd25f19f90e10440c5cc7d642
diff --git a/nvim/plugged/vim-devicons b/nvim/plugged/vim-devicons
new file mode 160000
+Subproject a2258658661e42dd4cdba4958805dbad1fe29ef
diff --git a/nvim/plugged/vim-nightfly-guicolors b/nvim/plugged/vim-nightfly-guicolors
new file mode 160000
+Subproject 2d8d5194ee45826a2994264e220d53546e608b4
diff --git a/nvim/plugged/wal.vim b/nvim/plugged/wal.vim
new file mode 160000
+Subproject c72ba0d18946f29aab9c95eb6975d321c68b368
diff --git a/picom/picom.conf b/picom/picom.conf
new file mode 100644
index 0000000..14ab14a
--- /dev/null
+++ b/picom/picom.conf
@@ -0,0 +1,68 @@
+# Shadows #
+shadow = true;
+shadow-radius = 20;
+shadow-opacity = 1;
+shadow-offset-x = -7;
+shadow-offset-y = -7;
+
+shadow-exclude = [
+ "name = 'Notification'",
+ "class_g = 'Conky'",
+ "class_g ?= 'Notify-osd'",
+ "class_g = 'Cairo-clock'",
+ "class_g = 'Dunst'",
+ "_GTK_FRAME_EXTENTS@:c"
+];
+
+# Fading #
+fading = true
+fade-in-step = 0.1;
+fade-out-step = 0.1;
+
+# Transparency / Opacity #
+inactive-opacity = 0.9;
+#frame-opacity = 0.7;
+inactive-opacity-override = false;
+
+opacity-rule = [
+ "100:class_g = 'firefox'",
+ "100:class_g = 'Brave-browser'",
+ "100:class_g = 'Shotcut'",
+ "100:class_i = 'ncmpzug'",
+ "100:class_g = 'Dino'",
+ "100:class_g = 'Zathura'",
+ "100:class_g = 'libreoffice-startcenter'",
+ "100:class_g = 'libreoffice-writer'",
+ "100:class_g = 'krita'",
+ "100:class_g = 'mpv'"
+ ];
+
+# Background-Blurring #
+blur-kern = "3x3box";
+blur-background-exclude = [
+ "window_type = 'dock'",
+ "window_type = 'desktop'",
+ "_GTK_FRAME_EXTENTS@:c"
+];
+
+# General Settings #
+backend = "xrender";
+vsync = true
+mark-wmwin-focused = true;
+mark-ovredir-focused = true;
+detect-rounded-corners = true;
+detect-client-opacity = true;
+refresh-rate = 0
+detect-transient = true
+detect-client-leader = true
+use-damage = true
+log-level = "warn";
+
+wintypes:
+{
+ tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
+ dock = { shadow = false; }
+ dnd = { shadow = false; }
+ popup_menu = { opacity = 0.8; }
+ dropdown_menu = { opacity = 0.8; }
+};
diff --git a/polybar/cuts/bars.ini b/polybar/cuts/bars.ini
new file mode 100644
index 0000000..43edc3a
--- /dev/null
+++ b/polybar/cuts/bars.ini
@@ -0,0 +1,542 @@
+;; ┌────────────────────────────────────────────────────┐
+;; │░█▀█░█▀█░█░░░█░█░█▀▄░█▀█░█▀▄░░░░░░░░░█▀▄░█▀█░█▀▄░█▀▀│
+;; │░█▀▀░█░█░█░░░░█░░█▀▄░█▀█░█▀▄░░░░▀░░░░█▀▄░█▀█░█▀▄░▀▀█│
+;; │░▀░░░▀▀▀░▀▀▀░░▀░░▀▀░░▀░▀░▀░▀░░░░▀░░░░▀▀░░▀░▀░▀░▀░▀▀▀│
+;; │░Created░By░Aditya░Shakya░@adi1090x░░░░░░░░░░░░░░░░░│
+;; └────────────────────────────────────────────────────┘
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[bar]
+fill = ﭳ
+empty = ﭳ
+indicator =
+width = 6
+format = %{T4}%fill%%indicator%%empty%%{F-}%{T-}
+
+[module/volume]
+type = internal/alsa
+
+; Soundcard to be used
+; Usually in the format hw:# where # is the card number
+; You can find the different card numbers in `/proc/asound/cards`
+master-soundcard = default
+speaker-soundcard = default
+headphone-soundcard = default
+
+; Name of the master, speaker and headphone mixers
+; Use the following command to list available mixer controls:
+; $ amixer scontrols | sed -nr "s/.*'([[:alnum:]]+)'.*/\1/p"
+; If master, speaker or headphone-soundcard isn't the default,
+; use `amixer -c # scontrols` instead where # is the number
+; of the master, speaker or headphone soundcard respectively
+;
+; Default: Master
+master-mixer = Master
+
+; Optionally define speaker and headphone mixers
+; Default: none
+;;speaker-mixer = Speaker
+; Default: none
+;;headphone-mixer = Headphone
+
+; NOTE: This is required if headphone_mixer is defined
+; Use the following command to list available device controls
+; $ amixer controls | sed -r "/CARD/\!d; s/.*=([0-9]+).*name='([^']+)'.*/printf '%3.0f: %s\n' '\1' '\2'/e" | sort
+; You may also need to use `amixer -c # controls` as above for the mixer names
+; Default: none
+;;headphone-id = 9
+
+; Use volume mapping (similar to amixer -M and alsamixer), where the increase in volume is linear to the ear
+; Default: false
+;;mapped = true
+
+; Interval for volume increase/decrease (in percent points)
+; Default: 5
+interval = 5
+
+; Available tags:
+; <label-volume> (default)
+; <ramp-volume>
+; <bar-volume>
+format-volume = <ramp-volume> <bar-volume>
+format-volume-background = ${color.background}
+format-volume-padding = 1
+
+; Available tags:
+; <label-muted> (default)
+; <ramp-volume>
+; <bar-volume>
+format-muted = <label-muted>
+format-muted-prefix = 
+format-muted-background = ${color.background}
+format-muted-padding = 1
+
+; Available tokens:
+; %percentage% (default)
+label-volume = %percentage%%
+
+; Available tokens:
+; %percentage% (default
+label-muted = " Muted"
+label-muted-foreground = ${color.foreground}
+
+; Only applies if <ramp-volume> is used
+ramp-volume-0 = 
+ramp-volume-1 = 
+ramp-volume-2 = 
+
+; Only applies if <bar-volume> is used
+bar-volume-format = ${bar.format}
+bar-volume-width = ${bar.width}
+bar-volume-gradient = false
+
+bar-volume-indicator = ${bar.indicator}
+bar-volume-indicator-foreground = ${color.foreground}
+
+bar-volume-fill = ${bar.fill}
+bar-volume-foreground-0 = ${color.green}
+bar-volume-foreground-1 = ${color.green}
+bar-volume-foreground-2 = ${color.yellow}
+bar-volume-foreground-3 = ${color.yellow}
+bar-volume-foreground-4 = ${color.red}
+
+bar-volume-empty = ${bar.empty}
+bar-volume-empty-foreground = ${color.foreground-alt}
+
+; If defined, it will replace <ramp-volume> when
+; headphones are plugged in to `headphone_control_numid`
+; If undefined, <ramp-volume> will be used for both
+; Only applies if <ramp-volume> is used
+ramp-headphones-0 = 
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/brightness]
+;type = internal/xbacklight
+type = internal/backlight
+
+; Use the following command to list available cards:
+; $ ls -1 /sys/class/backlight/
+;card = intel_backlight
+card = amdgpu_bl0
+
+; Available tags:
+; <label> (default)
+; <ramp>
+; <bar>
+format = <ramp> <bar>
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %percentage% (default)
+label = %percentage%%
+
+; Only applies if <ramp> is used
+ramp-0 = 
+ramp-1 = 
+ramp-2 = 
+ramp-3 = 
+ramp-4 = 
+
+; Only applies if <bar> is used
+bar-format = ${bar.format}
+bar-width = ${bar.width}
+bar-gradient = false
+
+bar-indicator = ${bar.indicator}
+bar-indicator-foreground = ${color.foreground}
+
+bar-fill = ${bar.fill}
+bar-foreground-0 = ${color.green}
+bar-foreground-1 = ${color.green}
+bar-foreground-2 = ${color.yellow}
+bar-foreground-3 = ${color.yellow}
+bar-foreground-4 = ${color.red}
+
+bar-empty = ${bar.empty}
+bar-empty-foreground = ${color.foreground-alt}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/battery_bar]
+type = internal/battery
+
+; This is useful in case the battery never reports 100% charge
+full-at = 99
+
+; Use the following command to list batteries and adapters:
+; $ ls -1 /sys/class/power_supply/
+battery = BAT1
+adapter = ACAD
+
+; If an inotify event haven't been reported in this many
+; seconds, manually poll for new values.
+;
+; Needed as a fallback for systems that don't report events
+; on sysfs/procfs.
+;
+; Disable polling by setting the interval to 0.
+;
+; Default: 5
+poll-interval = 2
+
+; see "man date" for details on how to format the time string
+; NOTE: if you want to use syntax tags here you need to use %%{...}
+; Default: %H:%M:%S
+time-format = %H:%M
+
+; Available tags:
+; <label-charging> (default)
+; <bar-capacity>
+; <ramp-capacity>
+; <animation-charging>
+format-charging = <bar-capacity>
+format-charging-prefix = " "
+format-charging-background = ${color.background}
+format-charging-padding = 1
+
+; Available tags:
+; <label-discharging> (default)
+; <bar-capacity>
+; <ramp-capacity>
+; <animation-discharging>
+format-discharging = <bar-capacity>
+format-discharging-prefix = " "
+format-discharging-background = ${color.background}
+format-discharging-padding = 1
+
+; Available tags:
+; <label-full> (default)
+; <bar-capacity>
+; <ramp-capacity>
+format-full = <label-full>
+format-full-prefix = " "
+format-full-background = ${color.background}
+format-full-padding = 1
+
+; Available tokens:
+; %percentage% (default)
+; %time%
+; %consumption% (shows current charge rate in watts)
+
+label-charging = %percentage%%
+
+; Available tokens:
+; %percentage% (default)
+; %time%
+; %consumption% (shows current discharge rate in watts)
+label-discharging = %percentage%%
+
+; Available tokens:
+; %percentage% (default)
+label-full = " Full"
+
+; Only applies if <bar-capacity> is used
+bar-capacity-format = ${bar.format}
+bar-capacity-width = ${bar.width}
+bar-capacity-gradient = false
+
+bar-capacity-indicator = ${bar.indicator}
+bar-capacity-indicator-foreground = ${color.foreground}
+
+bar-capacity-fill = ${bar.fill}
+bar-capacity-foreground-0 = ${color.green}
+bar-capacity-foreground-1 = ${color.green}
+bar-capacity-foreground-2 = ${color.yellow}
+bar-capacity-foreground-3 = ${color.yellow}
+bar-capacity-foreground-4 = ${color.red}
+
+bar-capacity-empty = ${bar.empty}
+bar-capacity-empty-foreground = ${color.foreground-alt}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/cpu_bar]
+type = internal/cpu
+
+; Seconds to sleep between updates
+; Default: 1
+interval = 0.5
+
+; Available tags:
+; <label> (default)
+; <bar-load>
+; <ramp-load>
+; <ramp-coreload>
+;;format = <label> <ramp-coreload>
+format = <bar-load> <label>
+format-prefix = " "
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %percentage% (default) - total cpu load averaged over all cores
+; %percentage-sum% - Cumulative load on all cores
+; %percentage-cores% - load percentage for each core
+; %percentage-core[1-9]% - load percentage for specific core
+label = "%percentage%%"
+
+; Only applies if <bar-load> is used
+bar-load-format = ${bar.format}
+bar-load-width = ${bar.width}
+bar-load-gradient = false
+
+bar-load-indicator = ${bar.indicator}
+bar-load-indicator-foreground = ${color.foreground}
+
+bar-load-fill = ${bar.fill}
+bar-load-foreground-0 = ${color.green}
+bar-load-foreground-1 = ${color.green}
+bar-load-foreground-2 = ${color.yellow}
+bar-load-foreground-3 = ${color.yellow}
+bar-load-foreground-4 = ${color.red}
+
+bar-load-empty = ${bar.empty}
+bar-load-empty-foreground = ${color.foreground-alt}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/filesystem_bar]
+type = internal/fs
+
+; Mountpoints to display
+mount-0 = /
+;;mount-1 = /home
+;;mount-2 = /var
+
+; Seconds to sleep between updates
+; Default: 30
+interval = 30
+
+; Display fixed precision values
+; Default: false
+fixed-values = false
+
+; Spacing between entries
+; Default: 2
+;;spacing = 4
+
+; Available tags:
+; <label-mounted> (default)
+; <bar-free>
+; <bar-used>
+; <ramp-capacity>
+format-mounted = <bar-used> <label-mounted>
+format-mounted-prefix = " "
+format-mounted-background = ${color.background}
+format-mounted-padding = 1
+
+; Available tags:
+; <label-unmounted> (default)
+format-unmounted = <label-unmounted>
+format-unmounted-prefix = " "
+format-unmounted-background = ${color.background}
+format-unmounted-padding = 1
+
+; Available tokens:
+; %mountpoint%
+; %type%
+; %fsname%
+; %percentage_free%
+; %percentage_used%
+; %total%
+; %free%
+; %used%
+; Default: %mountpoint% %percentage_free%%
+label-mounted = %used%/%total%
+
+; Available tokens:
+; %mountpoint%
+; Default: %mountpoint% is not mounted
+label-unmounted = "%mountpoint%: not mounted"
+
+; Only applies if <bar-used> is used
+bar-used-format = ${bar.format}
+bar-used-width = ${bar.width}
+bar-used-gradient = false
+
+bar-used-indicator = ${bar.indicator}
+bar-used-indicator-foreground = ${color.foreground}
+
+bar-used-fill = ${bar.fill}
+bar-used-foreground-0 = ${color.green}
+bar-used-foreground-1 = ${color.green}
+bar-used-foreground-2 = ${color.yellow}
+bar-used-foreground-3 = ${color.yellow}
+bar-used-foreground-4 = ${color.red}
+
+bar-used-empty = ${bar.empty}
+bar-used-empty-foreground = ${color.foreground-alt}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/memory_bar]
+type = internal/memory
+
+; Seconds to sleep between updates
+; Default: 1
+interval = 2
+
+; Available tags:
+; <label> (default)
+; <bar-used>
+; <bar-free>
+; <ramp-used>
+; <ramp-free>
+; <bar-swap-used>
+; <bar-swap-free>
+; <ramp-swap-used>
+; <ramp-swap-free>
+format = <bar-used> <label>
+format-prefix = " "
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %percentage_used% (default)
+; %percentage_free%
+; %gb_used%
+; %gb_free%
+; %gb_total%
+; %mb_used%
+; %mb_free%
+; %mb_total%
+; %percentage_swap_used%
+; %percentage_swap_free%
+; %mb_swap_total%
+; %mb_swap_free%
+; %mb_swap_used%
+; %gb_swap_total%
+; %gb_swap_free%
+; %gb_swap_used%
+
+label = "%mb_used%"
+
+; Only applies if <bar-used> is used
+bar-used-format = ${bar.format}
+bar-used-width = ${bar.width}
+bar-used-gradient = false
+
+bar-used-indicator = ${bar.indicator}
+bar-used-indicator-foreground = ${color.foreground}
+
+bar-used-fill = ${bar.fill}
+bar-used-foreground-0 = ${color.green}
+bar-used-foreground-1 = ${color.green}
+bar-used-foreground-2 = ${color.yellow}
+bar-used-foreground-3 = ${color.yellow}
+bar-used-foreground-4 = ${color.red}
+
+bar-used-empty = ${bar.empty}
+bar-used-empty-foreground = ${color.foreground-alt}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/mpd_bar]
+type = internal/mpd
+
+; Host where mpd is running (either ip or domain name)
+; Can also be the full path to a unix socket where mpd is running.
+;;host = 127.0.0.1
+;;port = 6600
+;;password = mysecretpassword
+
+; Seconds to sleep between progressbar/song timer sync
+; Default: 1
+interval = 1
+
+; Available tags:
+; <label-song> (default)
+; <label-time>
+; <bar-progress>
+; <toggle> - gets replaced with <icon-(pause|play)>
+; <toggle-stop> - gets replaced with <icon-(stop|play)>
+; <icon-random>
+; <icon-repeat>
+; <icon-repeatone> (deprecated)
+; <icon-single> - Toggle playing only a single song. Replaces <icon-repeatone>
+; <icon-consume>
+; <icon-prev>
+; <icon-stop>
+; <icon-play>
+; <icon-pause>
+; <icon-next>
+; <icon-seekb>
+; <icon-seekf>
+format-online = <label-song> <bar-progress> <label-time>
+format-online-prefix = 
+format-online-background = ${color.background}
+format-online-padding = 1
+
+;format-playing = ${self.format-online}
+;format-paused = ${self.format-online}
+;format-stopped = ${self.format-online}
+
+; Available tags:
+; <label-offline>
+format-offline = <label-offline>
+format-offline-prefix = 
+format-offline-background = ${color.background}
+format-offline-padding = 1
+
+; Available tokens:
+; %artist%
+; %album-artist%
+; %album%
+; %date%
+; %title%
+; Default: %artist% - %title%
+label-song = " %artist% - %title%"
+label-song-maxlen = 25
+label-song-ellipsis = true
+
+; Available tokens:
+; %elapsed%
+; %total%
+; Default: %elapsed% / %total%
+label-time = %elapsed% / %total%
+
+; Available tokens:
+; None
+label-offline = " Offline"
+
+; Only applies if <icon-X> is used
+icon-play = 
+icon-pause = 
+icon-stop = 
+icon-next = 
+icon-prev = 
+icon-seekf =
+icon-seekb =
+icon-random =
+icon-repeat =
+icon-repeatone =
+icon-single =
+icon-consume =
+
+; Used to display the state of random/repeat/repeatone/single
+; Only applies if <icon-[random|repeat|repeatone|single]> is used
+toggle-on-foreground = ${color.green}
+toggle-off-foreground = ${color.red}
+
+; Only applies if <bar-progress> is used
+bar-progress-format = ${bar.format}
+bar-progress-width = ${bar.width}
+bar-progress-gradient = false
+
+bar-progress-indicator = ${bar.indicator}
+bar-progress-indicator-foreground = ${color.foreground}
+
+bar-progress-fill = ${bar.fill}
+bar-progress-foreground-0 = ${color.green}
+bar-progress-foreground-1 = ${color.green}
+bar-progress-foreground-2 = ${color.yellow}
+bar-progress-foreground-3 = ${color.yellow}
+bar-progress-foreground-4 = ${color.red}
+
+bar-progress-empty = ${bar.empty}
+bar-progress-empty-foreground = ${color.foreground-alt}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
diff --git a/polybar/cuts/colors.ini b/polybar/cuts/colors.ini
new file mode 100644
index 0000000..011de7f
--- /dev/null
+++ b/polybar/cuts/colors.ini
@@ -0,0 +1,32 @@
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[color]
+
+;; Use pywal.sh in scripts directory to use colors from an image/wallpaper.
+
+;; Colors
+background-alt = #8C100f0e
+foreground-alt = #33e5e5e8
+primary = #717986
+green = #43a047
+
+;; Xresources
+background = ${xrdb:background}
+foreground = ${xrdb:foreground}
+color0 = ${xrdb:color0}
+color1 = ${xrdb:color1}
+color2 = ${xrdb:color2}
+color3 = ${xrdb:color3}
+color4 = ${xrdb:color4}
+color5 = ${xrdb:color5}
+color6 = ${xrdb:color6}
+color7 = ${xrdb:color7}
+color8 = ${xrdb:color8}
+color9 = ${xrdb:color9}
+color10 = ${xrdb:color10}
+color11 = ${xrdb:color11}
+color12 = ${xrdb:color12}
+color13 = ${xrdb:color13}
+color14 = ${xrdb:color14}
+color15 = ${xrdb:color15}
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
diff --git a/polybar/cuts/config.ini b/polybar/cuts/config.ini
new file mode 100644
index 0000000..2bfa4fa
--- /dev/null
+++ b/polybar/cuts/config.ini
@@ -0,0 +1,308 @@
+;; ┌────────────────────────────────────────────────────────────┐
+;; │░█▀█░█▀█░█░░░█░█░█▀▄░█▀█░█▀▄░░░░░░░░░█▀▀░█▀█░█▀█░█▀▀░▀█▀░█▀▀│
+;; │░█▀▀░█░█░█░░░░█░░█▀▄░█▀█░█▀▄░░░░▀░░░░█░░░█░█░█░█░█▀▀░░█░░█░█│
+;; │░▀░░░▀▀▀░▀▀▀░░▀░░▀▀░░▀░▀░▀░▀░░░░▀░░░░▀▀▀░▀▀▀░▀░▀░▀░░░▀▀▀░▀▀▀│
+;; │░Created░By░Aditya░Shakya░@adi1090x░░░░░░░░░░░░░░░░░░░░░░░░░│
+;; └────────────────────────────────────────────────────────────┘
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; Global WM Settings
+
+[global/wm]
+; Adjust the _NET_WM_STRUT_PARTIAL top value
+; Used for top aligned bars
+margin-bottom = 0
+
+; Adjust the _NET_WM_STRUT_PARTIAL bottom value
+; Used for bottom aligned bars
+margin-top = 0
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; File Inclusion
+; include an external file, like module file, etc.
+
+include-file = ~/.config/polybar/cuts/bars.ini
+include-file = ~/.config/polybar/cuts/colors.ini
+include-file = ~/.config/polybar/cuts/modules.ini
+include-file = ~/.config/polybar/cuts/user_modules.ini
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; Bar Settings
+
+[bar/main]
+; Use either of the following command to list available outputs:
+; If unspecified, the application will pick the first one it finds.
+; $ polybar -m | cut -d ':' -f 1
+; $ xrandr -q | grep " connected" | cut -d ' ' -f1
+monitor = HDMI-1
+
+; Use the specified monitor as a fallback if the main one is not found.
+monitor-fallback = HDMI-1
+
+; Require the monitor to be in connected state
+; XRandR sometimes reports my monitor as being disconnected (when in use)
+monitor-strict = false
+
+; Tell the Window Manager not to configure the window.
+; Use this to detach the bar if your WM is locking its size/position.
+override-redirect = false
+
+; Put the bar at the bottom of the screen
+bottom = false
+
+; Prefer fixed center position for the `modules-center` block
+; When false, the center position will be based on the size of the other blocks.
+fixed-center = true
+
+; Dimension defined as pixel value (e.g. 35) or percentage (e.g. 50%),
+; the percentage can optionally be extended with a pixel offset like so:
+; 50%:-10, this will result in a width or height of 50% minus 10 pixels
+width = 100%
+height = 28
+
+; Offset defined as pixel value (e.g. 35) or percentage (e.g. 50%)
+; the percentage can optionally be extended with a pixel offset like so:
+; 50%:-10, this will result in an offset in the x or y direction
+; of 50% minus 10 pixels
+offset-x = 0%
+offset-y = 0%
+
+; Background ARGB color (e.g. #f00, #ff992a, #ddff1023)
+background = ${color.background-alt}
+
+; Foreground ARGB color (e.g. #f00, #ff992a, #ddff1023)
+foreground = ${color.foreground}
+
+; Background gradient (vertical steps)
+; background-[0-9]+ = #aarrggbb
+;;background-0 =
+
+; Value used for drawing rounded corners
+; Note: This shouldn't be used together with border-size because the border
+; doesn't get rounded
+; Individual top/bottom values can be defined using:
+; radius-{top,bottom}
+radius-top = 0.0
+radius-bottom = 0.0
+
+; Under-/overline pixel size and argb color
+; Individual values can be defined using:
+; {overline,underline}-size
+; {overline,underline}-color
+line-size = 2
+line-color = ${color.primary}
+
+; Values applied to all borders
+; Individual side values can be defined using:
+; border-{left,top,right,bottom}-size
+; border-{left,top,right,bottom}-color
+; The top and bottom borders are added to the bar height, so the effective
+; window height is:
+; height + border-top-size + border-bottom-size
+; Meanwhile the effective window width is defined entirely by the width key and
+; the border is placed withing this area. So you effectively only have the
+; following horizontal space on the bar:
+; width - border-right-size - border-left-size
+border-size = 0
+border-color = ${color.primary}
+
+; Number of spaces to add at the beginning/end of the bar
+; Individual side values can be defined using:
+; padding-{left,right}
+padding = 0
+
+; Number of spaces to add before/after each module
+; Individual side values can be defined using:
+; module-margin-{left,right}
+module-margin-left = 0
+module-margin-right = 0
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+; Fonts are defined using <font-name>;<vertical-offset>
+; Font names are specified using a fontconfig pattern.
+; font-0 = NotoSans-Regular:size=8;2
+; font-1 = MaterialIcons:size=10
+; font-2 = Termsynu:size=8;-1
+; font-3 = FontAwesome:size=10
+; See the Fonts wiki page for more details
+
+; Text Fonts
+font-0 = Iosevka Nerd Font:style=Regular:size=10.3;4
+; Icons Fonts
+font-1 = feather:style=Medium:size=12;3
+; Powerline Glyphs
+font-2 = Iosevka Nerd Font:style=Medium:size=19;3
+; Larger font size for bar fill icons
+font-3 = Iosevka Nerd Font:style=Medium:size=12;4
+; Smaller font size for shorter spaces
+font-4 = Iosevka Nerd Font:style=Medium:size=7;4
+; Japanese
+font-5 = Sazanami Gothic:style=Gothic-Regular:size=10;2.5
+
+; Modules are added to one of the available blocks
+; modules-left = cpu ram
+; modules-center = xwindow xbacklight
+; modules-right = ipc clock
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[bar/top]
+inherit = bar/main
+modules-left = workspaces decor1 decor2 updates decor1
+modules-right = decor4 memory date
+modules-center = decor2 mpd decor3
+enable-ipc = true
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+; The separator will be inserted between the output of each module
+separator =
+
+; Opacity value between 0.0 and 1.0 used on fade in/out
+dim-value = 1.0
+
+; Value to be used to set the WM_NAME atom
+; If the value is empty or undefined, the atom value
+; will be created from the following template: polybar-[BAR]_[MONITOR]
+; NOTE: The placeholders are not available for custom values
+wm-name =
+
+; Locale used to localize various module data (e.g. date)
+; Expects a valid libc locale, for example: sv_SE.UTF-8
+locale =
+
+; Position of the system tray window
+; If empty or undefined, tray support will be disabled
+; NOTE: A center aligned tray will cover center aligned modules
+;
+; Available positions:
+; left
+; center
+; right
+; none
+tray-position = right
+
+; If true, the bar will not shift its
+; contents when the tray changes
+tray-detached = false
+
+; Tray icon max size
+tray-maxsize = 16
+
+; Background color for the tray container
+; ARGB color (e.g. #f00, #ff992a, #ddff1023)
+; By default the tray container will use the bar
+; background color.
+tray-background = ${color.background}
+
+; Tray offset defined as pixel value (e.g. 35) or percentage (e.g. 50%)
+tray-offset-x = 0
+tray-offset-y = 0
+
+; Pad the sides of each tray icon
+tray-padding = 0
+
+; Scale factor for tray clients
+tray-scale = 1.0
+
+; Restack the bar window and put it above the
+; selected window manager's root
+;
+; Fixes the issue where the bar is being drawn
+; on top of fullscreen window's
+;
+; Currently supported WM's:
+; bspwm
+; i3 (requires: `override-redirect = true`)
+;;wm-restack =
+
+; Set a DPI values used when rendering text
+; This only affects scalable fonts
+; dpi =
+
+; Enable support for inter-process messaging
+; See the Messaging wiki page for more details.
+;enable-ipc = true
+
+; Fallback click handlers that will be called if
+; there's no matching module handler found.
+click-left =
+click-middle =
+click-right =
+scroll-up =
+scroll-down =
+double-click-left =
+double-click-middle =
+double-click-right =
+
+; Requires polybar to be built with xcursor support (xcb-util-cursor)
+; Possible values are:
+; - default : The default pointer as before, can also be an empty string (default)
+; - pointer : Typically in the form of a hand
+; - ns-resize : Up and down arrows, can be used to indicate scrolling
+cursor-click =
+cursor-scroll =
+
+;; WM Workspace Specific
+
+; bspwm
+;;scroll-up = bspwm-desknext
+;;scroll-down = bspwm-deskprev
+;;scroll-up = bspc desktop -f prev.local
+;;scroll-down = bspc desktop -f next.local
+
+;i3
+;;scroll-up = i3wm-wsnext
+;;scroll-down = i3wm-wsprev
+;;scroll-up = i3-msg workspace next_on_output
+;;scroll-down = i3-msg workspace prev_on_output
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; Application Settings
+
+[settings]
+; The throttle settings lets the eventloop swallow up til X events
+; if they happen within Y millisecond after first event was received.
+; This is done to prevent flood of update event.
+;
+; For example if 5 modules emit an update event at the same time, we really
+; just care about the last one. But if we wait too long for events to swallow
+; the bar would appear sluggish so we continue if timeout
+; expires or limit is reached.
+throttle-output = 5
+throttle-output-for = 10
+
+; Time in milliseconds that the input handler will wait between processing events
+;throttle-input-for = 30
+
+; Reload upon receiving XCB_RANDR_SCREEN_CHANGE_NOTIFY events
+screenchange-reload = false
+
+; Compositing operators
+; @see: https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-operator-t
+compositing-background = source
+compositing-foreground = over
+compositing-overline = over
+compositing-underline = over
+compositing-border = over
+
+; Define fallback values used by all module formats
+;format-foreground =
+;format-background =
+;format-underline =
+;format-overline =
+;format-spacing =
+;format-padding =
+;format-margin =
+;format-offset =
+
+; Enables pseudo-transparency for the bar
+; If set to true the bar can be transparent without a compositor.
+pseudo-transparency = false
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
diff --git a/polybar/cuts/launch.sh b/polybar/cuts/launch.sh
new file mode 100755
index 0000000..22fe096
--- /dev/null
+++ b/polybar/cuts/launch.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+# Add this script to your wm startup file.
+DIR="$HOME/.config/polybar/cuts"
+
+# Terminate already running bar instances
+killall -q polybar
+
+# Wait until the processes have been shut down
+while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
+
+# Launch the bar
+polybar -q top -c "$DIR"/config.ini &
+polybar -q bottom -c "$DIR"/config.ini &
diff --git a/polybar/cuts/modules.ini b/polybar/cuts/modules.ini
new file mode 100644
index 0000000..58ad006
--- /dev/null
+++ b/polybar/cuts/modules.ini
@@ -0,0 +1,1108 @@
+;; ┌────────────────────────────────────────────────────────────────┐
+;; │░█▀█░█▀█░█░░░█░█░█▀▄░█▀█░█▀▄░░░░░░░░░█▄█░█▀█░█▀▄░█░█░█░░░█▀▀░█▀▀│
+;; │░█▀▀░█░█░█░░░░█░░█▀▄░█▀█░█▀▄░░░░▀░░░░█░█░█░█░█░█░█░█░█░░░█▀▀░▀▀█│
+;; │░▀░░░▀▀▀░▀▀▀░░▀░░▀▀░░▀░▀░▀░▀░░░░▀░░░░▀░▀░▀▀▀░▀▀░░▀▀▀░▀▀▀░▀▀▀░▀▀▀│
+;; │░Created░By░Aditya░Shakya░@adi1090x░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
+;; └────────────────────────────────────────────────────────────────┘
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/alsa]
+type = internal/alsa
+
+; Soundcard to be used
+; Usually in the format hw:# where # is the card number
+; You can find the different card numbers in `/proc/asound/cards`
+master-soundcard = default
+speaker-soundcard = default
+headphone-soundcard = default
+
+; Name of the master, speaker and headphone mixers
+; Use the following command to list available mixer controls:
+; $ amixer scontrols | sed -nr "s/.*'([[:alnum:]]+)'.*/\1/p"
+; If master, speaker or headphone-soundcard isn't the default,
+; use `amixer -c # scontrols` instead where # is the number
+; of the master, speaker or headphone soundcard respectively
+;
+; Default: Master
+master-mixer = Master
+
+; Optionally define speaker and headphone mixers
+; Default: none
+;;speaker-mixer = Speaker
+; Default: none
+;;headphone-mixer = Headphone
+
+; NOTE: This is required if headphone_mixer is defined
+; Use the following command to list available device controls
+; $ amixer controls | sed -r "/CARD/\!d; s/.*=([0-9]+).*name='([^']+)'.*/printf '%3.0f: %s\n' '\1' '\2'/e" | sort
+; You may also need to use `amixer -c # controls` as above for the mixer names
+; Default: none
+;;headphone-id = 9
+
+; Use volume mapping (similar to amixer -M and alsamixer), where the increase in volume is linear to the ear
+; Default: false
+;;mapped = true
+
+; Interval for volume increase/decrease (in percent points)
+; Default: 5
+interval = 5
+
+; Available tags:
+; <label-volume> (default)
+; <ramp-volume>
+; <bar-volume>
+format-volume = <ramp-volume> <label-volume>
+format-volume-background = ${color.background}
+format-volume-padding = 1
+
+; Available tags:
+; <label-muted> (default)
+; <ramp-volume>
+; <bar-volume>
+format-muted = <label-muted>
+format-muted-prefix = 
+format-muted-background = ${color.background}
+format-muted-padding = 1
+
+; Available tokens:
+; %percentage% (default)
+label-volume = %percentage%%
+
+; Available tokens:
+; %percentage% (default
+label-muted = " Muted"
+label-muted-foreground = ${color.foreground}
+
+; Only applies if <ramp-volume> is used
+ramp-volume-0 = 
+ramp-volume-1 = 
+ramp-volume-2 = 
+
+; If defined, it will replace <ramp-volume> when
+; headphones are plugged in to `headphone_control_numid`
+; If undefined, <ramp-volume> will be used for both
+; Only applies if <ramp-volume> is used
+ramp-headphones-0 = 
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/backlight]
+;type = internal/xbacklight
+type = internal/backlight
+
+; Use the following command to list available cards:
+; $ ls -1 /sys/class/backlight/
+;card = intel_backlight
+card = amdgpu_bl0
+
+; Available tags:
+; <label> (default)
+; <ramp>
+; <bar>
+format = <ramp> <label>
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %percentage% (default)
+label = %percentage%%
+
+; Only applies if <ramp> is used
+ramp-0 = 
+ramp-1 = 
+ramp-2 = 
+ramp-3 = 
+ramp-4 = 
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/battery]
+type = internal/battery
+
+; This is useful in case the battery never reports 100% charge
+full-at = 99
+
+; Use the following command to list batteries and adapters:
+; $ ls -1 /sys/class/power_supply/
+battery = BAT1
+adapter = ACAD
+
+; If an inotify event haven't been reported in this many
+; seconds, manually poll for new values.
+;
+; Needed as a fallback for systems that don't report events
+; on sysfs/procfs.
+;
+; Disable polling by setting the interval to 0.
+;
+; Default: 5
+poll-interval = 2
+
+; see "man date" for details on how to format the time string
+; NOTE: if you want to use syntax tags here you need to use %%{...}
+; Default: %H:%M:%S
+time-format = %H:%M
+
+; Available tags:
+; <label-charging> (default)
+; <bar-capacity>
+; <ramp-capacity>
+; <animation-charging>
+format-charging = <label-charging>
+format-charging-prefix = " "
+format-charging-background = ${color.background}
+format-charging-padding = 1
+
+; Available tags:
+; <label-discharging> (default)
+; <bar-capacity>
+; <ramp-capacity>
+; <animation-discharging>
+format-discharging = <label-discharging>
+format-discharging-prefix = " "
+format-discharging-background = ${color.background}
+format-discharging-padding = 1
+
+; Available tags:
+; <label-full> (default)
+; <bar-capacity>
+; <ramp-capacity>
+format-full = <label-full>
+format-full-prefix = " "
+format-full-background = ${color.background}
+format-full-padding = 1
+
+; Available tokens:
+; %percentage% (default)
+; %time%
+; %consumption% (shows current charge rate in watts)
+label-charging = %percentage%%
+
+; Available tokens:
+; %percentage% (default)
+; %time%
+; %consumption% (shows current discharge rate in watts)
+label-discharging = %percentage%%
+
+; Available tokens:
+; %percentage% (default)
+label-full = Full
+
+; Only applies if <ramp-capacity> is used
+ramp-capacity-0 =
+ramp-capacity-1 =
+ramp-capacity-2 =
+ramp-capacity-3 =
+ramp-capacity-4 =
+
+; Only applies if <bar-capacity> is used
+;bar-capacity-width = 10
+
+; Only applies if <animation-charging> is used
+animation-charging-0 =
+animation-charging-1 =
+
+; Framerate in milliseconds
+animation-charging-framerate = 750
+
+; Only applies if <animation-discharging> is used
+;;animation-discharging-0 = ${battery.anim0}
+;;animation-discharging-1 = ${battery.anim1}
+
+; Framerate in milliseconds
+;animation-discharging-framerate = 500
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;;[module/bspwm]
+;;type = internal/bspwm
+
+; Only show workspaces defined on the same output as the bar
+; NOTE: The bspwm and XRandR monitor names must match, which they do by default.
+; Default: true
+;;pin-workspaces = true
+
+; Output mode flags after focused state label
+; Default: false
+;;inline-mode = false
+
+; Create click handler used to focus workspace
+; Default: true
+;;enable-click = false
+
+; Create scroll handlers used to cycle workspaces
+; Default: true
+;;enable-scroll = false
+
+; Set the scroll cycle direction
+; Default: true
+;;reverse-scroll = false
+
+; Use fuzzy (partial) matching on labels when assigning
+; icons to workspaces
+; Example: code;♚ will apply the icon to all workspaces
+; containing 'code' in the label
+; Default: false
+;;fuzzy-match = true
+
+; ws-icon-[0-9]+ = label;icon
+; Note that the label needs to correspond with the bspwm workspace name
+;;ws-icon-0 = code;♚
+;;ws-icon-1 = office;♛
+;;ws-icon-2 = graphics;♜
+;;ws-icon-3 = mail;♝
+;;ws-icon-4 = web;♞
+;;ws-icon-default = ♟
+
+; Available tags:
+; <label-monitor>
+; <label-state> - gets replaced with <label-(focused|urgent|occupied|empty)>
+; <label-mode> - gets replaced with <label-(monocle|tiled|fullscreen|floating|locked|sticky|private)>
+; Default: <label-state>
+;;format = <label-state> <label-mode>
+
+; Available tokens:
+; %name%
+; Default: %name%
+;;label-monitor = %name%
+
+; If any values for label-dimmed-N are defined, the workspace/mode
+; colors will get overridden with those values if the monitor is out of focus
+; To only override workspaces in a specific state, use:
+; label-dimmed-focused
+; label-dimmed-occupied
+; label-dimmed-urgent
+; label-dimmed-empty
+;;label-dimmed-foreground = #555
+;;label-dimmed-underline = ${bar/top.background}
+;;label-dimmed-focused-background = #f00
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+;;label-focused = %icon%
+;;label-focused-foreground = #ffffff
+;;label-focused-background = #3f3f3f
+;;label-focused-underline = #fba922
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+;;label-occupied = %icon%
+;;label-occupied-underline = #555555
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+;;label-urgent = %icon%
+;;label-urgent-foreground = #000000
+;;label-urgent-background = #bd2c40
+;;label-urgent-underline = #9b0a20
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+;;label-empty = %icon%
+;;label-empty-foreground = #55
+
+; The following labels will be used to indicate the layout/mode
+; for the focused workspace. Requires <label-mode>
+;
+; Available tokens:
+; None
+;label-monocle = 
+;label-tiled = 
+;label-fullscreen = 
+;label-floating = 
+;label-pseudotiled = P
+;label-locked = 
+;label-locked-foreground = #bd2c40
+;label-sticky = 
+;label-sticky-foreground = #fba922
+;label-private = 
+;label-private-foreground = #bd2c40
+
+; Separator in between workspaces
+;;label-separator = |
+;;label-separator-padding = 2
+;;label-separator-foreground = #ffb52a
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/cpu]
+type = internal/cpu
+
+; Seconds to sleep between updates
+; Default: 1
+interval = 1
+
+; Available tags:
+; <label> (default)
+; <bar-load>
+; <ramp-load>
+; <ramp-coreload>
+;;format = <label> <ramp-coreload>
+format = <label>
+format-prefix = 
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %percentage% (default) - total cpu load averaged over all cores
+; %percentage-sum% - Cumulative load on all cores
+; %percentage-cores% - load percentage for each core
+; %percentage-core[1-9]% - load percentage for specific core
+label = " %percentage%%"
+
+; Spacing between individual per-core ramps
+;;ramp-coreload-spacing = 1
+;;ramp-coreload-0 = ${cpu.load0}
+;;ramp-coreload-1 = ${cpu.load1}
+
+;;ramp-load-0 = ${cpu.load0}
+;;ramp-load-1 = ${cpu.load1}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/date]
+type = internal/date
+
+; Seconds to sleep between updates
+interval = 1.0
+
+; See "http://en.cppreference.com/w/cpp/io/manip/put_time" for details on how to format the date string
+; NOTE: if you want to use syntax tags here you need to use %%{...}
+;;date = %Y-%m-%d%
+
+; Optional time format
+time = " %I:%M %p"
+
+; if `date-alt` or `time-alt` is defined, clicking
+; the module will toggle between formats
+;;date-alt = %A, %d %B %Y
+time-alt = " %a, %d %b %Y"
+
+; Available tags:
+; <label> (default)
+format = <label>
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %date%
+; %time%
+; Default: %date%
+label = %time%
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/filesystem]
+type = internal/fs
+
+; Mountpoints to display
+mount-0 = /
+;;mount-1 = /home
+;;mount-2 = /var
+
+; Seconds to sleep between updates
+; Default: 30
+interval = 30
+
+; Display fixed precision values
+; Default: false
+fixed-values = true
+
+; Spacing between entries
+; Default: 2
+;;spacing = 4
+
+; Available tags:
+; <label-mounted> (default)
+; <bar-free>
+; <bar-used>
+; <ramp-capacity>
+format-mounted = <label-mounted>
+format-mounted-prefix = 
+format-mounted-background = ${color.background}
+format-mounted-padding = 1
+
+; Available tags:
+; <label-unmounted> (default)
+format-unmounted = <label-unmounted>
+format-unmounted-prefix = 
+format-unmounted-background = ${color.background}
+format-unmounted-padding = 1
+
+; Available tokens:
+; %mountpoint%
+; %type%
+; %fsname%
+; %percentage_free%
+; %percentage_used%
+; %total%
+; %free%
+; %used%
+; Default: %mountpoint% %percentage_free%%
+label-mounted = " %free%"
+
+; Available tokens:
+; %mountpoint%
+; Default: %mountpoint% is not mounted
+label-unmounted = " %mountpoint%: not mounted"
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;;[module/github]
+;;type = internal/github
+
+; Accessing an access token stored in file
+;;token = ${file:/path/to/file/containing/github/access.token}
+
+; Accessing an access token stored in an environment variable
+;;token = ${env:GITHUB_ACCESS_TOKEN}
+
+; Whether empty notifications should be displayed or not
+;;empty-notifications = false
+
+; Number of seconds in between requests
+;;interval = 10
+
+; Available tags:
+; <label> (default)
+;;format = <label>
+;;format-prefix = 
+
+; Available tokens:
+; %notifications% (default)
+; Default: Notifications: %notifications%
+;;label = %notifications%
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;;[module/i3]
+;;type = internal/i3
+
+; Only show workspaces defined on the same output as the bar
+;
+; Useful if you want to show monitor specific workspaces
+; on different bars
+;
+; Default: false
+;;pin-workspaces = true
+
+; This will split the workspace name on ':'
+; Default: false
+;;strip-wsnumbers = true
+
+; Sort the workspaces by index instead of the default
+; sorting that groups the workspaces by output
+; Default: false
+;;index-sort = true
+
+; Create click handler used to focus workspace
+; Default: true
+;;enable-click = false
+
+; Create scroll handlers used to cycle workspaces
+; Default: true
+;;enable-scroll = false
+
+; Wrap around when reaching the first/last workspace
+; Default: true
+;;wrapping-scroll = false
+
+; Set the scroll cycle direction
+; Default: true
+;;reverse-scroll = false
+
+; Use fuzzy (partial) matching on labels when assigning
+; icons to workspaces
+; Example: code;♚ will apply the icon to all workspaces
+; containing 'code' in the label
+; Default: false
+;;fuzzy-match = true
+
+; ws-icon-[0-9]+ = label;icon
+; NOTE: The label needs to match the name of the i3 workspace
+;;ws-icon-0 = 1;♚
+;;ws-icon-1 = 2;♛
+;;ws-icon-2 = 3;♜
+;;ws-icon-3 = 4;♝
+;;ws-icon-4 = 5;♞
+;;ws-icon-default = ♟
+; NOTE: You cannot skip icons, e.g. to get a ws-icon-6
+; you must also define a ws-icon-5.
+
+; Available tags:
+; <label-state> (default) - gets replaced with <label-(focused|unfocused|visible|urgent)>
+; <label-mode> (default)
+;;format = <label-state> <label-mode>
+
+; Available tokens:
+; %mode%
+; Default: %mode%
+;;label-mode = %mode%
+;;label-mode-padding = 2
+;;label-mode-background = #e60053
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; %output%
+; Default: %icon% %name%
+;;label-focused = %index%
+;;label-focused-foreground = #ffffff
+;;label-focused-background = #3f3f3f
+;;label-focused-underline = #fba922
+;;label-focused-padding = 4
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; %output%
+; Default: %icon% %name%
+;;label-unfocused = %index%
+;;label-unfocused-padding = 4
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; %output%
+; Default: %icon% %name%
+;;label-visible = %index%
+;;label-visible-underline = #555555
+;;label-visible-padding = 4
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; %output%
+; Default: %icon% %name%
+;;label-urgent = %index%
+;;label-urgent-foreground = #000000
+;;label-urgent-background = #bd2c40
+;;label-urgent-padding = 4
+
+; Separator in between workspaces
+;;label-separator = |
+;;label-separator-padding = 2
+;;label-separator-foreground = #ffb52a
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/memory]
+type = internal/memory
+
+; Seconds to sleep between updates
+; Default: 1
+interval = 1
+
+; Available tags:
+; <label> (default)
+; <bar-used>
+; <bar-free>
+; <ramp-used>
+; <ramp-free>
+; <bar-swap-used>
+; <bar-swap-free>
+; <ramp-swap-used>
+; <ramp-swap-free>
+format = <label>
+format-prefix = 
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %percentage_used% (default)
+; %percentage_free%
+; %gb_used%
+; %gb_free%
+; %gb_total%
+; %mb_used%
+; %mb_free%
+; %mb_total%
+; %percentage_swap_used%
+; %percentage_swap_free%
+; %mb_swap_total%
+; %mb_swap_free%
+; %mb_swap_used%
+; %gb_swap_total%
+; %gb_swap_free%
+; %gb_swap_used%
+
+label = " %mb_used%"
+
+; Only applies if <ramp-used> is used
+;;ramp-used-0 = ${memory.used0}
+;;ramp-used-1 = ${memory.used1}
+;;ramp-used-2 = ${memory.used2}
+
+; Only applies if <ramp-free> is used
+;;ramp-free-0 = ${memory.free0}
+;;ramp-free-1 = ${memory.free1}
+;;ramp-free-2 = ${memory.free2}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/mpd]
+type = internal/mpd
+
+; Host where mpd is running (either ip or domain name)
+; Can also be the full path to a unix socket where mpd is running.
+;;host = 127.0.0.1
+;;port = 6600
+;;password = mysecretpassword
+
+; Seconds to sleep between progressbar/song timer sync
+; Default: 1
+interval = 1
+
+; Available tags:
+; <label-song> (default)
+; <label-time>
+; <bar-progress>
+; <toggle> - gets replaced with <icon-(pause|play)>
+; <toggle-stop> - gets replaced with <icon-(stop|play)>
+; <icon-random>
+; <icon-repeat>
+; <icon-repeatone> (deprecated)
+; <icon-single> - Toggle playing only a single song. Replaces <icon-repeatone>
+; <icon-consume>
+; <icon-prev>
+; <icon-stop>
+; <icon-play>
+; <icon-pause>
+; <icon-next>
+; <icon-seekb>
+; <icon-seekf>
+format-online = <label-song> <icon-prev> <toggle> <icon-next>
+format-online-prefix = 
+format-online-background = ${color.background}
+format-online-padding = 1
+
+;format-playing = ${self.format-online}
+;format-paused = ${self.format-online}
+;format-stopped = ${self.format-online}
+
+; Available tags:
+; <label-offline>
+format-offline = <label-offline>
+format-offline-prefix = 
+format-offline-background = ${color.background}
+format-offline-padding = 1
+
+; Available tokens:
+; %artist%
+; %album-artist%
+; %album%
+; %date%
+; %title%
+; Default: %artist% - %title%
+label-song = " %artist% - %title%"
+label-song-maxlen = 25
+label-song-ellipsis = true
+
+; Available tokens:
+; %elapsed%
+; %total%
+; Default: %elapsed% / %total%
+label-time = %elapsed% / %total%
+
+; Available tokens:
+; None
+label-offline = " Offline"
+
+; Only applies if <icon-X> is used
+icon-play = 
+icon-pause = 
+icon-stop = 
+icon-next = 
+icon-prev = 
+icon-seekf =
+icon-seekb =
+icon-random =
+icon-repeat =
+icon-repeatone =
+icon-single =
+icon-consume =
+
+; Used to display the state of random/repeat/repeatone/single
+; Only applies if <icon-[random|repeat|repeatone|single]> is used
+toggle-on-foreground = ${color.green}
+toggle-off-foreground = ${color.red}
+
+; Only applies if <bar-progress> is used
+;;bar-progress-width = 45
+;;bar-progress-indicator = |
+;;bar-progress-fill = ─
+;;bar-progress-empty = ─
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+; If you use both a wired and a wireless network, just add 2 module definitions. For example
+[module/wired-network]
+type = internal/network
+interface = eth0
+
+[module/wireless-network]
+type = internal/network
+interface = wlp3s0
+
+; Normal Module
+[module/network]
+type = internal/network
+interface = wlan0
+
+; Seconds to sleep between updates
+; Default: 1
+interval = 1.0
+
+; Test connectivity every Nth update
+; A value of 0 disables the feature
+; NOTE: Experimental (needs more testing)
+; Default: 0
+;ping-interval = 3
+
+; @deprecated: Define min width using token specifiers (%downspeed:min% and %upspeed:min%)
+; Minimum output width of upload/download rate
+; Default: 3
+;;udspeed-minwidth = 5
+
+; Accumulate values from all interfaces
+; when querying for up/downspeed rate
+; Default: false
+accumulate-stats = true
+
+; Consider an `UNKNOWN` interface state as up.
+; Some devices have an unknown state, even when they're running
+; Default: false
+unknown-as-up = true
+
+; Available tags:
+; <label-connected> (default)
+; <ramp-signal>
+format-connected = <label-connected>
+format-connected-prefix = 
+format-connected-background = ${color.background}
+format-connected-padding = 1
+
+; Available tags:
+; <label-disconnected> (default)
+format-disconnected = <label-disconnected>
+format-disconnected-prefix = 
+format-disconnected-background = ${color.background}
+format-disconnected-padding = 1
+
+; Available tags:
+; <label-connected> (default)
+; <label-packetloss>
+; <animation-packetloss>
+;;format-packetloss = <animation-packetloss> <label-connected>
+
+; Available tokens:
+; %ifname% [wireless+wired]
+; %local_ip% [wireless+wired]
+; %local_ip6% [wireless+wired]
+; %essid% [wireless]
+; %signal% [wireless]
+; %upspeed% [wireless+wired]
+; %downspeed% [wireless+wired]
+; %linkspeed% [wired]
+; Default: %ifname% %local_ip%
+label-connected = "%{A1:networkmanager_dmenu &:} %essid%  %downspeed%  %upspeed%%{A}"
+
+; Available tokens:
+; %ifname% [wireless+wired]
+; Default: (none)
+label-disconnected = "%{A1:networkmanager_dmenu &:} Offline%{A}"
+;;label-disconnected-foreground = #66ffffff
+
+; Available tokens:
+; %ifname% [wireless+wired]
+; %local_ip% [wireless+wired]
+; %local_ip6% [wireless+wired]
+; %essid% [wireless]
+; %signal% [wireless]
+; %upspeed% [wireless+wired]
+; %downspeed% [wireless+wired]
+; %linkspeed% [wired]
+; Default: (none)
+;label-packetloss = %essid%
+;label-packetloss-foreground = #eefafafa
+
+; Only applies if <ramp-signal> is used
+ramp-signal-0 =
+ramp-signal-1 =
+ramp-signal-2 =
+
+; Only applies if <animation-packetloss> is used
+;;animation-packetloss-0 = ⚠
+;;animation-packetloss-0-foreground = #ffa64c
+;;animation-packetloss-1 = ⚠
+;;animation-packetloss-1-foreground = #000000
+; Framerate in milliseconds
+;;animation-packetloss-framerate = 500
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/pulseaudio]
+type = internal/pulseaudio
+
+; Sink to be used, if it exists (find using `pacmd list-sinks`, name field)
+; If not, uses default sink
+sink = alsa_output.pci-0000_03_00.6.analog-stereo
+
+; Use PA_VOLUME_UI_MAX (~153%) if true, or PA_VOLUME_NORM (100%) if false
+; Default: true
+use-ui-max = false
+
+; Interval for volume increase/decrease (in percent points)
+; Default: 5
+interval = 5
+
+; Available tags:
+; <label-volume> (default)
+; <ramp-volume>
+; <bar-volume>
+format-volume = <ramp-volume> <label-volume>
+format-volume-background = ${color.background}
+format-volume-padding = 1
+
+; Available tags:
+; <label-muted> (default)
+; <ramp-volume>
+; <bar-volume>
+format-muted = <label-muted>
+format-muted-prefix = 
+format-muted-background = ${color.background}
+format-muted-padding = 1
+
+; Available tokens:
+; %percentage% (default)
+label-volume = %percentage%%
+
+; Available tokens:
+; %percentage% (default
+label-muted = " Muted"
+label-muted-foreground = ${color.foreground}
+
+; Only applies if <ramp-volume> is used
+ramp-volume-0 = 
+ramp-volume-1 = 
+ramp-volume-2 = 
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/temperature]
+type = internal/temperature
+
+; Seconds to sleep between updates
+; Default: 1
+interval = 0.5
+
+; Thermal zone to use
+; To list all the zone types, run
+; $ for i in /sys/class/thermal/thermal_zone*; do echo "$i: $(<$i/type)"; done
+; Default: 0
+thermal-zone = 0
+
+; Full path of temperature sysfs path
+; Use `sensors` to find preferred temperature source, then run
+; $ for i in /sys/class/hwmon/hwmon*/temp*_input; do echo "$(<$(dirname $i)/name): $(cat ${i%_*}_label 2>/dev/null || echo $(basename ${i%_*})) $(readlink -f $i)"; done
+; to find path to desired file
+; Default reverts to thermal zone setting
+;;hwmon-path = /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp1_input
+hwmon-path = /sys/devices/pci0000:00/0000:00:01.3/0000:01:00.0/hwmon/hwmon0/temp1_input
+
+; Threshold temperature to display warning label (in degrees celsius)
+; Default: 80
+warn-temperature = 65
+
+; Whether or not to show units next to the temperature tokens (°C, °F)
+; Default: true
+units = true
+
+; Available tags:
+; <label> (default)
+; <ramp>
+format = <ramp> <label>
+format-background = ${color.background}
+format-padding = 1
+
+; Available tags:
+; <label-warn> (default)
+; <ramp>
+format-warn = <ramp> <label-warn>
+format-warn-background = ${color.background}
+format-warn-padding = 1
+
+; Available tokens:
+; %temperature% (deprecated)
+; %temperature-c% (default, temperature in °C)
+; %temperature-f% (temperature in °F)
+label = %temperature-c%
+
+; Available tokens:
+; %temperature% (deprecated)
+; %temperature-c% (default, temperature in °C)
+; %temperature-f% (temperature in °F)
+label-warn = "%temperature-c%"
+label-warn-foreground = ${color.red}
+
+; Requires the <ramp> tag
+; The icon selection will range from 0 to `warn-temperature`
+; with the current temperature as index.
+ramp-0 = 
+ramp-1 = 
+ramp-2 = 
+ramp-3 = 
+ramp-4 = 
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/keyboard]
+type = internal/xkeyboard
+
+; List of indicators to ignore
+blacklist-0 = num lock
+blacklist-1 = scroll lock
+
+; Available tags:
+; <label-layout> (default)
+; <label-indicator> (default)
+format = <label-layout> <label-indicator>
+format-background = ${color.background}
+format-padding = 1
+format-prefix = 
+
+; Available tokens:
+; %layout%
+; %name%
+; %number%
+; Default: %layout%
+label-layout = " %layout%"
+
+; Available tokens:
+; %name%
+; Default: %name%
+label-indicator-on = %name%
+label-indicator-on-foreground = ${color.primary}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/title]
+type = internal/xwindow
+
+; Available tags:
+; <label> (default)
+format = <label>
+format-background = ${color.background}
+format-padding = 0
+;format-prefix = 
+
+; Available tokens:
+; %title%
+; Default: %title%
+label = "%title%"
+label-maxlen = 30
+
+; Used instead of label when there is no window title
+;;label-empty = Arch Linux
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/workspaces]
+type = internal/xworkspaces
+
+; Only show workspaces defined on the same output as the bar
+;
+; Useful if you want to show monitor specific workspaces
+; on different bars
+;
+; Default: false
+pin-workspaces = true
+
+; Create click handler used to focus desktop
+; Default: true
+enable-click = true
+
+; Create scroll handlers used to cycle desktops
+; Default: true
+enable-scroll = true
+
+; icon-[0-9]+ = <desktop-name>;<icon>
+; NOTE: The desktop name needs to match the name configured by the WM
+; You can get a list of the defined desktops using:
+; $ xprop -root _NET_DESKTOP_NAMES
+icon-0 = 1;I
+icon-1 = 2;II
+icon-2 = 3;III
+icon-3 = 4;IV
+icon-4 = 5;V
+icon-default = VI
+
+
+; Available tags:
+; <label-monitor>
+; <label-state> - gets replaced with <label-(active|urgent|occupied|empty)>
+; Default: <label-state>
+format = <label-state>
+format-background = ${color.background}
+format-padding = 0
+
+; Available tokens:
+; %name%
+; Default: %name%
+label-monitor = %name%
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+label-active = %icon%
+label-active-foreground = ${color.red}
+label-active-overline = ${color.red}
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+label-occupied = %icon%
+label-occupied-foreground = ${color.yellow}
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+label-urgent = %icon%
+label-urgent-foreground = ${color.green}
+
+; Available tokens:
+; %name%
+; %icon%
+; %index%
+; Default: %icon% %name%
+label-empty = %icon%
+
+label-active-padding = 1
+label-urgent-padding = 1
+label-occupied-padding = 1
+label-empty-padding = 1
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
diff --git a/polybar/cuts/preview.ini b/polybar/cuts/preview.ini
new file mode 100644
index 0000000..3377f74
--- /dev/null
+++ b/polybar/cuts/preview.ini
@@ -0,0 +1,323 @@
+;; ┌────────────────────────────────────────────────────────────────────┐
+;; │░█▀█░█▀█░█░░░█░█░█▀▄░█▀█░█▀▄░░░░░░░░░█▀█░█▀▄░█▀▀░█░█░▀█▀░█▀▀░█░█░█▀▀│
+;; │░█▀▀░█░█░█░░░░█░░█▀▄░█▀█░█▀▄░░░░▀░░░░█▀▀░█▀▄░█▀▀░▀▄▀░░█░░█▀▀░█▄█░▀▀█│
+;; │░▀░░░▀▀▀░▀▀▀░░▀░░▀▀░░▀░▀░▀░▀░░░░▀░░░░▀░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀▀▀░▀░▀░▀▀▀│
+;; │░Created░By░Aditya░Shakya░@adi1090x░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
+;; └────────────────────────────────────────────────────────────────────┘
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; Global WM Settings
+
+[global/wm]
+; Adjust the _NET_WM_STRUT_PARTIAL top value
+; Used for top aligned bars
+margin-bottom = 0
+
+; Adjust the _NET_WM_STRUT_PARTIAL bottom value
+; Used for bottom aligned bars
+margin-top = 0
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; File Inclusion
+; include an external file, like module file, etc.
+
+include-file = ~/.config/polybar/cuts/bars.ini
+include-file = ~/.config/polybar/cuts/colors.ini
+include-file = ~/.config/polybar/cuts/modules.ini
+include-file = ~/.config/polybar/cuts/user_modules.ini
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; Bar Settings
+
+[bar/main]
+; Use either of the following command to list available outputs:
+; If unspecified, the application will pick the first one it finds.
+; $ polybar -m | cut -d ':' -f 1
+; $ xrandr -q | grep " connected" | cut -d ' ' -f1
+monitor =
+
+; Use the specified monitor as a fallback if the main one is not found.
+monitor-fallback =
+
+; Require the monitor to be in connected state
+; XRandR sometimes reports my monitor as being disconnected (when in use)
+monitor-strict = false
+
+; Tell the Window Manager not to configure the window.
+; Use this to detach the bar if your WM is locking its size/position.
+override-redirect = false
+
+; Put the bar at the bottom of the screen
+bottom = false
+
+; Prefer fixed center position for the `modules-center` block
+; When false, the center position will be based on the size of the other blocks.
+fixed-center = true
+
+; Dimension defined as pixel value (e.g. 35) or percentage (e.g. 50%),
+; the percentage can optionally be extended with a pixel offset like so:
+; 50%:-10, this will result in a width or height of 50% minus 10 pixels
+width = 100%
+height = 28
+
+; Offset defined as pixel value (e.g. 35) or percentage (e.g. 50%)
+; the percentage can optionally be extended with a pixel offset like so:
+; 50%:-10, this will result in an offset in the x or y direction
+; of 50% minus 10 pixels
+offset-x = 0%
+offset-y = 0%
+
+; Background ARGB color (e.g. #f00, #ff992a, #ddff1023)
+background = ${color.background-alt}
+
+; Foreground ARGB color (e.g. #f00, #ff992a, #ddff1023)
+foreground = ${color.foreground}
+
+; Background gradient (vertical steps)
+; background-[0-9]+ = #aarrggbb
+;;background-0 =
+
+; Value used for drawing rounded corners
+; Note: This shouldn't be used together with border-size because the border
+; doesn't get rounded
+; Individual top/bottom values can be defined using:
+; radius-{top,bottom}
+radius-top = 0.0
+radius-bottom = 0.0
+
+; Under-/overline pixel size and argb color
+; Individual values can be defined using:
+; {overline,underline}-size
+; {overline,underline}-color
+line-size = 2
+line-color = ${color.primary}
+
+; Values applied to all borders
+; Individual side values can be defined using:
+; border-{left,top,right,bottom}-size
+; border-{left,top,right,bottom}-color
+; The top and bottom borders are added to the bar height, so the effective
+; window height is:
+; height + border-top-size + border-bottom-size
+; Meanwhile the effective window width is defined entirely by the width key and
+; the border is placed withing this area. So you effectively only have the
+; following horizontal space on the bar:
+; width - border-right-size - border-left-size
+border-size = 0
+border-color = ${color.primary}
+
+; Number of spaces to add at the beginning/end of the bar
+; Individual side values can be defined using:
+; padding-{left,right}
+padding = 0
+
+; Number of spaces to add before/after each module
+; Individual side values can be defined using:
+; module-margin-{left,right}
+module-margin-left = 0
+module-margin-right = 0
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+; Fonts are defined using <font-name>;<vertical-offset>
+; Font names are specified using a fontconfig pattern.
+; font-0 = NotoSans-Regular:size=8;2
+; font-1 = MaterialIcons:size=10
+; font-2 = Termsynu:size=8;-1
+; font-3 = FontAwesome:size=10
+; See the Fonts wiki page for more details
+
+; Text Fonts
+font-0 = Iosevka Nerd Font:style=Medium:size=10;4
+; Icons Fonts
+font-1 = feather:style=Medium:size=12;3
+; Powerline Glyphs
+font-2 = Iosevka Nerd Font:style=Medium:size=19;3
+; Larger font size for bar fill icons
+font-3 = Iosevka Nerd Font:style=Medium:size=12;4
+; Smaller font size for shorter spaces
+font-4 = Iosevka Nerd Font:style=Medium:size=7;4
+
+; Modules are added to one of the available blocks
+; modules-left = cpu ram
+; modules-center = xwindow xbacklight
+; modules-right = ipc clock
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[bar/top]
+inherit = bar/main
+bottom = true
+offset-y = 71
+modules-left = launcher title decor1 decor2 workspaces decor1 decor2 color-switch decor1
+modules-right = decor4 updates decor3 decor4 temperature battery keyboard decor3 decor4 date sysmenu
+enable-ipc = true
+
+[bar/mid]
+inherit = bar/main
+bottom = true
+offset-y = 38
+modules-left = menu decor1 decor2 mpd_bar decor1 decor2 term files browser settings decor1 decor2 cpu_bar decor1
+modules-right = decor4 memory_bar decor3 decor4 alsa backlight decor3 decor4 filesystem_bar decor3 decor4 battery_bar pulseaudio decor3 decor4 powermenu
+enable-ipc = true
+
+[bar/bottom]
+inherit = bar/main
+bottom = true
+offset-y = 5
+modules-left = mpd decor3 decor4 cpu memory filesystem decor3
+modules-right = decor2 network decor1 decor2 volume brightness
+enable-ipc = true
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+; The separator will be inserted between the output of each module
+separator =
+
+; Opacity value between 0.0 and 1.0 used on fade in/out
+dim-value = 1.0
+
+; Value to be used to set the WM_NAME atom
+; If the value is empty or undefined, the atom value
+; will be created from the following template: polybar-[BAR]_[MONITOR]
+; NOTE: The placeholders are not available for custom values
+wm-name =
+
+; Locale used to localize various module data (e.g. date)
+; Expects a valid libc locale, for example: sv_SE.UTF-8
+locale =
+
+; Position of the system tray window
+; If empty or undefined, tray support will be disabled
+; NOTE: A center aligned tray will cover center aligned modules
+;
+; Available positions:
+; left
+; center
+; right
+; none
+tray-position = none
+
+; If true, the bar will not shift its
+; contents when the tray changes
+tray-detached = false
+
+; Tray icon max size
+tray-maxsize = 16
+
+; Background color for the tray container
+; ARGB color (e.g. #f00, #ff992a, #ddff1023)
+; By default the tray container will use the bar
+; background color.
+tray-background = ${color.background-alt}
+
+; Tray offset defined as pixel value (e.g. 35) or percentage (e.g. 50%)
+tray-offset-x = 0
+tray-offset-y = 0
+
+; Pad the sides of each tray icon
+tray-padding = 0
+
+; Scale factor for tray clients
+tray-scale = 1.0
+
+; Restack the bar window and put it above the
+; selected window manager's root
+;
+; Fixes the issue where the bar is being drawn
+; on top of fullscreen window's
+;
+; Currently supported WM's:
+; bspwm
+; i3 (requires: `override-redirect = true`)
+;;wm-restack =
+
+; Set a DPI values used when rendering text
+; This only affects scalable fonts
+; dpi =
+
+; Enable support for inter-process messaging
+; See the Messaging wiki page for more details.
+;enable-ipc = true
+
+; Fallback click handlers that will be called if
+; there's no matching module handler found.
+click-left =
+click-middle =
+click-right =
+scroll-up =
+scroll-down =
+double-click-left =
+double-click-middle =
+double-click-right =
+
+; Requires polybar to be built with xcursor support (xcb-util-cursor)
+; Possible values are:
+; - default : The default pointer as before, can also be an empty string (default)
+; - pointer : Typically in the form of a hand
+; - ns-resize : Up and down arrows, can be used to indicate scrolling
+cursor-click =
+cursor-scroll =
+
+;; WM Workspace Specific
+
+; bspwm
+;;scroll-up = bspwm-desknext
+;;scroll-down = bspwm-deskprev
+;;scroll-up = bspc desktop -f prev.local
+;;scroll-down = bspc desktop -f next.local
+
+;i3
+;;scroll-up = i3wm-wsnext
+;;scroll-down = i3wm-wsprev
+;;scroll-up = i3-msg workspace next_on_output
+;;scroll-down = i3-msg workspace prev_on_output
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+;; Application Settings
+
+[settings]
+; The throttle settings lets the eventloop swallow up til X events
+; if they happen within Y millisecond after first event was received.
+; This is done to prevent flood of update event.
+;
+; For example if 5 modules emit an update event at the same time, we really
+; just care about the last one. But if we wait too long for events to swallow
+; the bar would appear sluggish so we continue if timeout
+; expires or limit is reached.
+throttle-output = 5
+throttle-output-for = 10
+
+; Time in milliseconds that the input handler will wait between processing events
+;throttle-input-for = 30
+
+; Reload upon receiving XCB_RANDR_SCREEN_CHANGE_NOTIFY events
+screenchange-reload = false
+
+; Compositing operators
+; @see: https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-operator-t
+compositing-background = source
+compositing-foreground = over
+compositing-overline = over
+compositing-underline = over
+compositing-border = over
+
+; Define fallback values used by all module formats
+;format-foreground =
+;format-background =
+;format-underline =
+;format-overline =
+;format-spacing =
+;format-padding =
+;format-margin =
+;format-offset =
+
+; Enables pseudo-transparency for the bar
+; If set to true the bar can be transparent without a compositor.
+pseudo-transparency = false
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
diff --git a/polybar/cuts/preview.sh b/polybar/cuts/preview.sh
new file mode 100755
index 0000000..9bb0ae6
--- /dev/null
+++ b/polybar/cuts/preview.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+DIR="$HOME/.config/polybar/cuts"
+
+# Terminate already running bar instances
+killall -q polybar
+
+# Wait until the processes have been shut down
+while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
+
+# Launch the preview bar
+polybar -q top -c "$DIR"/preview.ini &
+polybar -q mid -c "$DIR"/preview.ini &
+polybar -q bottom -c "$DIR"/preview.ini &
diff --git a/polybar/cuts/scripts/checkupdates b/polybar/cuts/scripts/checkupdates
new file mode 100755
index 0000000..4d8a5e8
--- /dev/null
+++ b/polybar/cuts/scripts/checkupdates
@@ -0,0 +1,117 @@
+#!/usr/bin/bash
+#
+# checkupdates: Safely print a list of pending updates.
+#
+# Copyright (c) 2013 Kyle Keen <keenerd@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+declare -r myname='checkupdates'
+declare -r myver='1.0.0'
+
+plain() {
+ (( QUIET )) && return
+ local mesg=$1; shift
+ printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1
+}
+
+msg() {
+ (( QUIET )) && return
+ local mesg=$1; shift
+ printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1
+}
+
+msg2() {
+ (( QUIET )) && return
+ local mesg=$1; shift
+ printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1
+}
+
+ask() {
+ local mesg=$1; shift
+ printf "${BLUE}::${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}" "$@" >&1
+}
+
+warning() {
+ local mesg=$1; shift
+ printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+error() {
+ local mesg=$1; shift
+ printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+# check if messages are to be printed using color
+unset ALL_OFF BOLD BLUE GREEN RED YELLOW
+if [[ -t 2 && ! $USE_COLOR = "n" ]]; then
+ # prefer terminal safe colored and bold text when tput is supported
+ if tput setaf 0 &>/dev/null; then
+ ALL_OFF="$(tput sgr0)"
+ BOLD="$(tput bold)"
+ BLUE="${BOLD}$(tput setaf 4)"
+ GREEN="${BOLD}$(tput setaf 2)"
+ RED="${BOLD}$(tput setaf 1)"
+ YELLOW="${BOLD}$(tput setaf 3)"
+ else
+ ALL_OFF="\e[1;0m"
+ BOLD="\e[1;1m"
+ BLUE="${BOLD}\e[1;34m"
+ GREEN="${BOLD}\e[1;32m"
+ RED="${BOLD}\e[1;31m"
+ YELLOW="${BOLD}\e[1;33m"
+ fi
+fi
+readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
+
+
+if (( $# > 0 )); then
+ echo "${myname} v${myver}"
+ echo
+ echo "Safely print a list of pending updates"
+ echo
+ echo "Usage: ${myname}"
+ echo
+ echo 'Note: Export the "CHECKUPDATES_DB" variable to change the path of the temporary database.'
+ exit 0
+fi
+
+if ! type -P fakeroot >/dev/null; then
+ error 'Cannot find the fakeroot binary.'
+ exit 1
+fi
+
+if [[ -z $CHECKUPDATES_DB ]]; then
+ CHECKUPDATES_DB="${TMPDIR:-/tmp}/checkup-db-${USER}/"
+fi
+
+trap 'rm -f $CHECKUPDATES_DB/db.lck' INT TERM EXIT
+
+DBPath="$(pacman-conf DBPath)"
+if [[ -z "$DBPath" ]] || [[ ! -d "$DBPath" ]]; then
+ DBPath="/var/lib/pacman/"
+fi
+
+mkdir -p "$CHECKUPDATES_DB"
+ln -s "${DBPath}/local" "$CHECKUPDATES_DB" &> /dev/null
+if ! fakeroot -- pacman -Sy --dbpath "$CHECKUPDATES_DB" --logfile /dev/null &> /dev/null; then
+ error 'Cannot fetch updates'
+ exit 1
+fi
+pacman -Qu --dbpath "$CHECKUPDATES_DB" 2> /dev/null | grep -v '\[.*\]'
+
+exit 0
+
+# vim: set noet:
diff --git a/polybar/cuts/scripts/color-switch.sh b/polybar/cuts/scripts/color-switch.sh
new file mode 100755
index 0000000..83941b6
--- /dev/null
+++ b/polybar/cuts/scripts/color-switch.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+SDIR="$HOME/.config/polybar/cuts/scripts"
+
+# Launch Rofi
+MENU="$(rofi -no-config -no-lazy-grab -sep "|" -dmenu -i -p '' \
+-theme $SDIR/rofi/styles.rasi \
+<<< " amber| blue| blue-gray| brown| cyan| deep-orange|\
+ deep-purple| green| gray| indigo| blue-light| green-light|\
+ lime| orange| pink| purple| red| teal| yellow| amber-dark|\
+ blue-dark| blue-gray-dark| brown-dark| cyan-dark| deep-orange-dark|\
+ deep-purple-dark| green-dark| gray-dark| indigo-dark| blue-light-dark|\
+ green-light-dark| lime-dark| orange-dark| pink-dark| purple-dark| red-dark| teal-dark| yellow-dark|")"
+ case "$MENU" in
+ ## Light Colors
+ *amber) "$SDIR"/colors-light.sh --amber ;;
+ *blue) "$SDIR"/colors-light.sh --blue ;;
+ *blue-gray) "$SDIR"/colors-light.sh --blue-gray ;;
+ *brown) "$SDIR"/colors-light.sh --brown ;;
+ *cyan) "$SDIR"/colors-light.sh --cyan ;;
+ *deep-orange) "$SDIR"/colors-light.sh --deep-orange ;;
+ *deep-purple) "$SDIR"/colors-light.sh --deep-purple ;;
+ *green) "$SDIR"/colors-light.sh --green ;;
+ *gray) "$SDIR"/colors-light.sh --gray ;;
+ *indigo) "$SDIR"/colors-light.sh --indigo ;;
+ *blue-light) "$SDIR"/colors-light.sh --light-blue ;;
+ *green-light) "$SDIR"/colors-light.sh --light-green ;;
+ *lime) "$SDIR"/colors-light.sh --lime ;;
+ *orange) "$SDIR"/colors-light.sh --orange ;;
+ *pink) "$SDIR"/colors-light.sh --pink ;;
+ *purple) "$SDIR"/colors-light.sh --purple ;;
+ *red) "$SDIR"/colors-light.sh --red ;;
+ *teal) "$SDIR"/colors-light.sh --teal ;;
+ *yellow) "$SDIR"/colors-light.sh --yellow ;;
+ ## Dark Colors
+ *amber-dark) "$SDIR"/colors-dark.sh --amber ;;
+ *blue-dark) "$SDIR"/colors-dark.sh --blue ;;
+ *blue-gray-dark) "$SDIR"/colors-dark.sh --blue-gray ;;
+ *brown-dark) "$SDIR"/colors-dark.sh --brown ;;
+ *cyan-dark) "$SDIR"/colors-dark.sh --cyan ;;
+ *deep-orange-dark) "$SDIR"/colors-dark.sh --deep-orange ;;
+ *deep-purple-dark) "$SDIR"/colors-dark.sh --deep-purple ;;
+ *green-dark) "$SDIR"/colors-dark.sh --green ;;
+ *gray-dark) "$SDIR"/colors-dark.sh --gray ;;
+ *indigo-dark) "$SDIR"/colors-dark.sh --indigo ;;
+ *blue-light-dark) "$SDIR"/colors-dark.sh --light-blue ;;
+ *green-light-dark) "$SDIR"/colors-dark.sh --light-green ;;
+ *lime-dark) "$SDIR"/colors-dark.sh --lime ;;
+ *orange-dark) "$SDIR"/colors-dark.sh --orange ;;
+ *pink-dark) "$SDIR"/colors-dark.sh --pink ;;
+ *purple-dark) "$SDIR"/colors-dark.sh --purple ;;
+ *red-dark) "$SDIR"/colors-dark.sh --red ;;
+ *teal-dark) "$SDIR"/colors-dark.sh --teal ;;
+ *yellow-dark) "$SDIR"/colors-dark.sh --yellow
+ esac
diff --git a/polybar/cuts/scripts/colors-dark.sh b/polybar/cuts/scripts/colors-dark.sh
new file mode 100755
index 0000000..22f1ca8
--- /dev/null
+++ b/polybar/cuts/scripts/colors-dark.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+
+# Color files
+PFILE="$HOME/.config/polybar/cuts/colors.ini"
+RFILE="$HOME/.config/polybar/cuts/scripts/rofi/colors.rasi"
+
+BG="0a0a0a"
+FG="f5f5f5"
+
+# Change colors
+change_color() {
+ # polybar
+ sed -i -e "s/background = #.*/background = #${BG}/g" $PFILE
+ sed -i -e "s/background-alt = #.*/background-alt = #8C${BG}/g" $PFILE
+ sed -i -e "s/foreground = #.*/foreground = #${FG}/g" $PFILE
+ sed -i -e "s/foreground-alt = #.*/foreground-alt = #33${FG}/g" $PFILE
+ sed -i -e "s/primary = #.*/primary = $AC/g" $PFILE
+
+ # rofi
+ cat > $RFILE <<- EOF
+ /* colors */
+
+ * {
+ al: #00000000;
+ bg: #${BG}BF;
+ bga: #${BG}FF;
+ fg: #${FG}FF;
+ ac: ${AC}FF;
+ se: ${AC}1A;
+ }
+ EOF
+
+ polybar-msg cmd restart
+}
+
+if [[ $1 = "--amber" ]]; then
+ AC="#ffb300"
+ change_color
+elif [[ $1 = "--blue" ]]; then
+ AC="#1e88e5"
+ change_color
+elif [[ $1 = "--blue-gray" ]]; then
+ AC="#546e7a"
+ change_color
+elif [[ $1 = "--brown" ]]; then
+ AC="#6d4c41"
+ change_color
+elif [[ $1 = "--cyan" ]]; then
+ AC="#00acc1"
+ change_color
+elif [[ $1 = "--deep-orange" ]]; then
+ AC="#f4511e"
+ change_color
+elif [[ $1 = "--deep-purple" ]]; then
+ AC="#5e35b1"
+ change_color
+elif [[ $1 = "--green" ]]; then
+ AC="#43a047"
+ change_color
+elif [[ $1 = "--gray" ]]; then
+ AC="#757575"
+ change_color
+elif [[ $1 = "--indigo" ]]; then
+ AC="#3949ab"
+ change_color
+elif [[ $1 = "--light-blue" ]]; then
+ AC="#039be5"
+ change_color
+elif [[ $1 = "--light-green" ]]; then
+ AC="#7cb342"
+ change_color
+elif [[ $1 = "--lime" ]]; then
+ AC="#c0ca33"
+ change_color
+elif [[ $1 = "--orange" ]]; then
+ AC="#fb8c00"
+ change_color
+elif [[ $1 = "--pink" ]]; then
+ AC="#d81b60"
+ change_color
+elif [[ $1 = "--purple" ]]; then
+ AC="#8e24aa"
+ change_color
+elif [[ $1 = "--red" ]]; then
+ AC="#e53935"
+ change_color
+elif [[ $1 = "--teal" ]]; then
+ AC="#00897b"
+ change_color
+elif [[ $1 = "--yellow" ]]; then
+ AC="#fdd835"
+ change_color
+else
+ cat <<- _EOF_
+ No option specified, Available options:
+ --amber --blue --blue-gray --brown
+ --cyan --deep-orange --deep-purple --green
+ --gray --indigo --light-blue --light-green
+ --lime --orange --pink --purple
+ --red --teal --yellow
+ _EOF_
+fi
diff --git a/polybar/cuts/scripts/colors-light.sh b/polybar/cuts/scripts/colors-light.sh
new file mode 100755
index 0000000..d7151e9
--- /dev/null
+++ b/polybar/cuts/scripts/colors-light.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+
+# Color files
+PFILE="$HOME/.config/polybar/cuts/colors.ini"
+RFILE="$HOME/.config/polybar/cuts/scripts/rofi/colors.rasi"
+
+BG="FFFFFF"
+FG="0A0A0A"
+
+# Change colors
+change_color() {
+ # polybar
+ sed -i -e "s/background = #.*/background = #${BG}/g" $PFILE
+ sed -i -e "s/background-alt = #.*/background-alt = #8C${BG}/g" $PFILE
+ sed -i -e "s/foreground = #.*/foreground = #${FG}/g" $PFILE
+ sed -i -e "s/foreground-alt = #.*/foreground-alt = #33${FG}/g" $PFILE
+ sed -i -e "s/primary = #.*/primary = $AC/g" $PFILE
+
+ # rofi
+ cat > $RFILE <<- EOF
+ /* colors */
+
+ * {
+ al: #00000000;
+ bg: #${BG}BF;
+ bga: #${BG}FF;
+ fg: #${FG}FF;
+ ac: ${AC}FF;
+ se: ${AC}1A;
+ }
+ EOF
+
+ polybar-msg cmd restart
+}
+
+if [[ $1 = "--amber" ]]; then
+ AC="#ffb300"
+ change_color
+elif [[ $1 = "--blue" ]]; then
+ AC="#1e88e5"
+ change_color
+elif [[ $1 = "--blue-gray" ]]; then
+ AC="#546e7a"
+ change_color
+elif [[ $1 = "--brown" ]]; then
+ AC="#6d4c41"
+ change_color
+elif [[ $1 = "--cyan" ]]; then
+ AC="#00acc1"
+ change_color
+elif [[ $1 = "--deep-orange" ]]; then
+ AC="#f4511e"
+ change_color
+elif [[ $1 = "--deep-purple" ]]; then
+ AC="#5e35b1"
+ change_color
+elif [[ $1 = "--green" ]]; then
+ AC="#43a047"
+ change_color
+elif [[ $1 = "--gray" ]]; then
+ AC="#757575"
+ change_color
+elif [[ $1 = "--indigo" ]]; then
+ AC="#3949ab"
+ change_color
+elif [[ $1 = "--light-blue" ]]; then
+ AC="#039be5"
+ change_color
+elif [[ $1 = "--light-green" ]]; then
+ AC="#7cb342"
+ change_color
+elif [[ $1 = "--lime" ]]; then
+ AC="#c0ca33"
+ change_color
+elif [[ $1 = "--orange" ]]; then
+ AC="#fb8c00"
+ change_color
+elif [[ $1 = "--pink" ]]; then
+ AC="#d81b60"
+ change_color
+elif [[ $1 = "--purple" ]]; then
+ AC="#8e24aa"
+ change_color
+elif [[ $1 = "--red" ]]; then
+ AC="#e53935"
+ change_color
+elif [[ $1 = "--teal" ]]; then
+ AC="#00897b"
+ change_color
+elif [[ $1 = "--yellow" ]]; then
+ AC="#fdd835"
+ change_color
+else
+ cat <<- _EOF_
+ No option specified, Available options:
+ --amber --blue --blue-gray --brown
+ --cyan --deep-orange --deep-purple --green
+ --gray --indigo --light-blue --light-green
+ --lime --orange --pink --purple
+ --red --teal --yellow
+ _EOF_
+fi
diff --git a/polybar/cuts/scripts/launcher.sh b/polybar/cuts/scripts/launcher.sh
new file mode 100755
index 0000000..0386394
--- /dev/null
+++ b/polybar/cuts/scripts/launcher.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+rofi -no-config -no-lazy-grab -show drun -modi drun -theme ~/.config/polybar/cuts/scripts/rofi/launcher.rasi
diff --git a/polybar/cuts/scripts/powermenu.sh b/polybar/cuts/scripts/powermenu.sh
new file mode 100755
index 0000000..7017be5
--- /dev/null
+++ b/polybar/cuts/scripts/powermenu.sh
@@ -0,0 +1,94 @@
+#!/usr/bin/env bash
+
+## Author : Aditya Shakya
+## Mail : adi1090x@gmail.com
+## Github : @adi1090x
+## Twitter : @adi1090x
+
+dir="~/.config/polybar/cuts/scripts/rofi"
+uptime=$(uptime -p | sed -e 's/up //g')
+
+rofi_command="rofi -theme $dir/powermenu.rasi"
+
+# Options
+shutdown=" Shutdown"
+reboot=" Restart"
+lock=" Lock"
+suspend=" Sleep"
+logout=" Logout"
+
+# Confirmation
+confirm_exit() {
+ rofi -dmenu\
+ -i\
+ -no-fixed-num-lines\
+ -p "Are You Sure? : "\
+ -theme $dir/confirm.rasi
+}
+
+# Message
+msg() {
+ rofi -theme "$dir/message.rasi" -e "Available Options - yes / y / no / n"
+}
+
+# Variable passed to rofi
+options="$lock\n$suspend\n$logout\n$reboot\n$shutdown"
+
+chosen="$(echo -e "$options" | $rofi_command -p "Uptime: $uptime" -dmenu -selected-row 0)"
+case $chosen in
+ $shutdown)
+ ans=$(confirm_exit &)
+ if [[ $ans == "yes" || $ans == "YES" || $ans == "y" || $ans == "Y" ]]; then
+ systemctl poweroff
+ elif [[ $ans == "no" || $ans == "NO" || $ans == "n" || $ans == "N" ]]; then
+ exit 0
+ else
+ msg
+ fi
+ ;;
+ $reboot)
+ ans=$(confirm_exit &)
+ if [[ $ans == "yes" || $ans == "YES" || $ans == "y" || $ans == "Y" ]]; then
+ systemctl reboot
+ elif [[ $ans == "no" || $ans == "NO" || $ans == "n" || $ans == "N" ]]; then
+ exit 0
+ else
+ msg
+ fi
+ ;;
+ $lock)
+ if [[ -f /usr/bin/i3lock ]]; then
+ i3lock
+ elif [[ -f /usr/bin/betterlockscreen ]]; then
+ betterlockscreen -l
+ fi
+ ;;
+ $suspend)
+ ans=$(confirm_exit &)
+ if [[ $ans == "yes" || $ans == "YES" || $ans == "y" || $ans == "Y" ]]; then
+ mpc -q pause
+ amixer set Master mute
+ systemctl suspend
+ elif [[ $ans == "no" || $ans == "NO" || $ans == "n" || $ans == "N" ]]; then
+ exit 0
+ else
+ msg
+ fi
+ ;;
+ $logout)
+ ans=$(confirm_exit &)
+ if [[ $ans == "yes" || $ans == "YES" || $ans == "y" || $ans == "Y" ]]; then
+ if [[ "$DESKTOP_SESSION" == "Openbox" ]]; then
+ openbox --exit
+ elif [[ "$DESKTOP_SESSION" == "bspwm" ]]; then
+ bspc quit
+ elif [[ "$DESKTOP_SESSION" == "i3" ]]; then
+ i3-msg exit
+ fi
+ elif [[ $ans == "no" || $ans == "NO" || $ans == "n" || $ans == "N" ]]; then
+ exit 0
+ else
+ msg
+ fi
+ ;;
+esac
diff --git a/polybar/cuts/scripts/pywal.sh b/polybar/cuts/scripts/pywal.sh
new file mode 100755
index 0000000..fac5fbc
--- /dev/null
+++ b/polybar/cuts/scripts/pywal.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+
+# Color files
+PFILE="$HOME/.config/polybar/cuts/colors.ini"
+RFILE="$HOME/.config/polybar/cuts/scripts/rofi/colors.rasi"
+
+# Get colors
+pywal_get() {
+ wal -i "$1" -q -t
+}
+
+# Change colors
+change_color() {
+ # polybar
+ sed -i -e "s/background = #.*/background = #${BG}/g" $PFILE
+ sed -i -e "s/background-alt = #.*/background-alt = #8C${BG}/g" $PFILE
+ sed -i -e "s/foreground = #.*/foreground = #${FG}/g" $PFILE
+ sed -i -e "s/foreground-alt = #.*/foreground-alt = #33${FG}/g" $PFILE
+ sed -i -e "s/primary = #.*/primary = $AC/g" $PFILE
+
+ # rofi
+ cat > $RFILE <<- EOF
+ /* colors */
+
+ * {
+ al: #00000000;
+ bg: #${BG}BF;
+ bga: #${BG}FF;
+ fg: #${FG}FF;
+ ac: ${AC}FF;
+ se: ${AC}1A;
+ }
+ EOF
+
+ polybar-msg cmd restart
+}
+
+# Main
+if [[ -f "/usr/bin/wal" ]]; then
+ if [[ "$1" ]]; then
+ pywal_get "$1"
+
+ # Source the pywal color file
+ . "$HOME/.cache/wal/colors.sh"
+
+ BGC=`printf "%s\n" "$background"`
+ BG=${BGC:1}
+ FGC=`printf "%s\n" "$foreground"`
+ FG=${FGC:1}
+ AC=`printf "%s\n" "$color1"`
+
+ change_color
+ else
+ echo -e "[!] Please enter the path to wallpaper. \n"
+ echo "Usage : ./pywal.sh path/to/image"
+ fi
+else
+ echo "[!] 'pywal' is not installed."
+fi
diff --git a/polybar/cuts/scripts/random.sh b/polybar/cuts/scripts/random.sh
new file mode 100755
index 0000000..6addb58
--- /dev/null
+++ b/polybar/cuts/scripts/random.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env bash
+
+# Color files
+PFILE="$HOME/.config/polybar/cuts/colors.ini"
+RFILE="$HOME/.config/polybar/cuts/scripts/rofi/colors.rasi"
+
+# Change colors
+change_color() {
+ # polybar
+ sed -i -e "s/background = #.*/background = #${BG}/g" $PFILE
+ sed -i -e "s/background-alt = #.*/background-alt = #8C${BG}/g" $PFILE
+ sed -i -e "s/foreground = #.*/foreground = #${FG}/g" $PFILE
+ sed -i -e "s/foreground-alt = #.*/foreground-alt = #33${FG}/g" $PFILE
+ sed -i -e "s/primary = #.*/primary = $AC/g" $PFILE
+
+ # rofi
+ cat > $RFILE <<- EOF
+ /* colors */
+
+ * {
+ al: #00000000;
+ bg: #${BG}BF;
+ bga: #${BG}FF;
+ fg: #${FG}FF;
+ ac: ${AC}FF;
+ se: ${AC}1A;
+ }
+ EOF
+
+ polybar-msg cmd restart
+}
+
+get_random_number() {
+ RNUM=$(( ($RANDOM % $1) + 1 ))
+}
+
+get_random_color() {
+ RCOLOR="#"
+ for i in 1 2 3 4 5 6
+ do
+ get_random_number "16"
+ case $RNUM in
+ "1") NEXTDIGIT="1";;
+ "2") NEXTDIGIT="2";;
+ "3") NEXTDIGIT="3";;
+ "4") NEXTDIGIT="4";;
+ "5") NEXTDIGIT="5";;
+ "6") NEXTDIGIT="6";;
+ "7") NEXTDIGIT="7";;
+ "8") NEXTDIGIT="8";;
+ "9") NEXTDIGIT="9";;
+ "10") NEXTDIGIT="A";;
+ "11") NEXTDIGIT="B";;
+ "12") NEXTDIGIT="C";;
+ "13") NEXTDIGIT="D";;
+ "14") NEXTDIGIT="E";;
+ "15") NEXTDIGIT="F";;
+ "16") NEXTDIGIT="0";;
+ esac
+ RCOLOR="$RCOLOR$NEXTDIGIT"
+ done
+ echo $RCOLOR
+}
+
+hex_to_rgb() {
+ # Convert a hex value WITHOUT the hashtag (#)
+ R=$(printf "%d" 0x${1:0:2})
+ G=$(printf "%d" 0x${1:2:2})
+ B=$(printf "%d" 0x${1:4:2})
+}
+
+get_fg_color(){
+ INTENSITY=$(calc "$R*0.299 + $G*0.587 + $B*0.114")
+
+ if [ $(echo "$INTENSITY>186" | bc) -eq 1 ]; then
+ FG="0a0a0a"
+ AC="#0a0a0a"
+ else
+ FG="F5F5F5"
+ AC="#F5F5F5"
+ fi
+}
+
+# Main
+BGC=`get_random_color`
+BG=${BGC:1}
+HEX=$BG
+
+hex_to_rgb $HEX
+get_fg_color
+change_color
diff --git a/polybar/cuts/scripts/rofi/colors.rasi b/polybar/cuts/scripts/rofi/colors.rasi
new file mode 100644
index 0000000..9ca84d0
--- /dev/null
+++ b/polybar/cuts/scripts/rofi/colors.rasi
@@ -0,0 +1,10 @@
+/* colors */
+
+* {
+ al: #00000000;
+ bg: #100f0eBF;
+ bga: #100f0eFF;
+ fg: #e5e5e8FF;
+ ac: #717986FF;
+ se: #7179861A;
+}
diff --git a/polybar/cuts/scripts/rofi/confirm.rasi b/polybar/cuts/scripts/rofi/confirm.rasi
new file mode 100644
index 0000000..bd82b52
--- /dev/null
+++ b/polybar/cuts/scripts/rofi/confirm.rasi
@@ -0,0 +1,25 @@
+/* Confirm Dialog */
+
+@import "colors.rasi"
+
+* {
+ background-color: @bga;
+ text-color: @fg;
+ font: "Iosevka Nerd Font 10";
+}
+
+window {
+ width: 225px;
+ padding: 25px;
+ border: 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ location: center;
+ y-offset: -2em;
+}
+
+entry {
+ expand: true;
+ text-color: @ac;
+}
+
diff --git a/polybar/cuts/scripts/rofi/launcher.rasi b/polybar/cuts/scripts/rofi/launcher.rasi
new file mode 100644
index 0000000..f9be5dd
--- /dev/null
+++ b/polybar/cuts/scripts/rofi/launcher.rasi
@@ -0,0 +1,115 @@
+/*
+ *
+ * Author : Aditya Shakya
+ * Mail : adi1090x@gmail.com
+ * Github : @adi1090x
+ * Twitter : @adi1090x
+ *
+ */
+
+configuration {
+ font: "Iosevka Nerd Font 10";
+ show-icons: true;
+ icon-theme: "Papirus";
+ display-drun: "";
+ drun-display-format: "{name}";
+ disable-history: false;
+ fullscreen: false;
+ hide-scrollbar: true;
+ sidebar-mode: false;
+}
+
+@import "colors.rasi"
+
+window {
+ transparency: "real";
+ background-color: @bg;
+ text-color: @fg;
+ border: 0px;
+ border-color: @ac;
+ border-radius: 0px;
+ width: 500px;
+ location: center;
+ x-offset: 0;
+ y-offset: 0;
+}
+
+prompt {
+ enabled: true;
+ padding: 0px;
+ background-color: @al;
+ text-color: @ac;
+ font: "feather 12";
+}
+
+entry {
+ background-color: @al;
+ text-color: @fg;
+ placeholder-color: @fg;
+ expand: true;
+ horizontal-align: 0;
+ placeholder: "Search...";
+ padding: 0px 0px 0px 8px;
+ blink: true;
+}
+
+inputbar {
+ children: [ prompt, entry ];
+ background-color: @bga;
+ text-color: @fg;
+ expand: false;
+ border: 0px 0px 0px 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ margin: 0px;
+ padding: 12px;
+}
+
+listview {
+ background-color: @al;
+ padding: 0px;
+ columns: 1;
+ lines: 6;
+ spacing: 5px;
+ cycle: true;
+ dynamic: true;
+ layout: vertical;
+}
+
+mainbox {
+ background-color: @al;
+ border: 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ children: [ inputbar, listview ];
+ spacing: 0px;
+ padding: 0px;
+}
+
+element {
+ background-color: @al;
+ text-color: @fg;
+ orientation: horizontal;
+ border-radius: 0px;
+ padding: 8px;
+}
+
+element-icon {
+ size: 24px;
+ border: 0px;
+}
+
+element-text {
+ expand: true;
+ horizontal-align: 0;
+ vertical-align: 0.5;
+ margin: 0px 2.5px 0px 2.5px;
+}
+
+element selected {
+ background-color: @se;
+ text-color: @fg;
+ border: 0px 0px 0px 2px;
+ border-radius: 0px;
+ border-color: @ac;
+}
diff --git a/polybar/cuts/scripts/rofi/message.rasi b/polybar/cuts/scripts/rofi/message.rasi
new file mode 100644
index 0000000..434f16b
--- /dev/null
+++ b/polybar/cuts/scripts/rofi/message.rasi
@@ -0,0 +1,24 @@
+/* Confirm Dialog */
+
+@import "colors.rasi"
+
+* {
+ background-color: @bga;
+ text-color: @fg;
+ font: "Iosevka Nerd Font 10";
+}
+
+window {
+ width: 320px;
+ padding: 25px;
+ border: 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ location: center;
+ y-offset: -2em;
+}
+
+entry {
+ expand: true;
+ text-color: @ac;
+}
diff --git a/polybar/cuts/scripts/rofi/networkmenu.rasi b/polybar/cuts/scripts/rofi/networkmenu.rasi
new file mode 100644
index 0000000..2ac18b8
--- /dev/null
+++ b/polybar/cuts/scripts/rofi/networkmenu.rasi
@@ -0,0 +1,123 @@
+/*
+ *
+ * Author : Aditya Shakya
+ * Mail : adi1090x@gmail.com
+ * Github : @adi1090x
+ * Twitter : @adi1090x
+ *
+ */
+
+configuration {
+ font: "Iosevka Nerd Font 10";
+ show-icons: true;
+ icon-theme: "Papirus";
+ display-drun: "";
+ drun-display-format: "{name}";
+ disable-history: false;
+ fullscreen: false;
+ hide-scrollbar: true;
+ sidebar-mode: false;
+}
+
+@import "colors.rasi"
+
+window {
+ transparency: "real";
+ background-color: @bg;
+ text-color: @fg;
+ border: 0px;
+ border-color: @ac;
+ border-radius: 0px;
+ width: 400px;
+ location: center;
+ x-offset: 0;
+ y-offset: 0;
+}
+
+prompt {
+ enabled: true;
+ padding: 0px 0px 0px 5px;
+ background-color: @al;
+ text-color: @fg;
+}
+
+textbox-prompt-colon {
+ padding: 0px 0px 0px 2px;
+ background-color: @al;
+ text-color: @ac;
+ expand: false;
+ str: "";
+ font: "feather 12";
+}
+
+entry {
+ background-color: @al;
+ text-color: @fg;
+ placeholder-color: @fg;
+ expand: true;
+ horizontal-align: 0;
+ placeholder: "Search...";
+ padding: 0px;
+ blink: true;
+}
+
+inputbar {
+ children: [ textbox-prompt-colon, prompt ];
+ background-color: @bga;
+ text-color: @fg;
+ expand: false;
+ border: 0px 0px 0px 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ margin: 0px;
+ padding: 12px;
+}
+
+listview {
+ background-color: @al;
+ padding: 0px;
+ columns: 1;
+ lines: 8;
+ spacing: 0px;
+ cycle: true;
+ dynamic: true;
+ layout: vertical;
+}
+
+mainbox {
+ background-color: @al;
+ border: 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ children: [ inputbar, listview ];
+ spacing: 0px;
+ padding: 0px;
+}
+
+element {
+ background-color: @al;
+ text-color: @fg;
+ orientation: horizontal;
+ border-radius: 0px;
+ padding: 8px 8px 8px -15px;
+}
+
+element-icon {
+ size: 24px;
+ border: 0px;
+}
+
+element-text {
+ expand: true;
+ horizontal-align: 0;
+ vertical-align: 0.5;
+ margin: 0px 2.5px 0px 2.5px;
+}
+
+element selected {
+ background-color: @se;
+ text-color: @fg;
+ border: 0px 0px 0px 2px;
+ border-radius: 0px;
+ border-color: @ac;
+}
diff --git a/polybar/cuts/scripts/rofi/powermenu.rasi b/polybar/cuts/scripts/rofi/powermenu.rasi
new file mode 100644
index 0000000..7c83572
--- /dev/null
+++ b/polybar/cuts/scripts/rofi/powermenu.rasi
@@ -0,0 +1,123 @@
+/*
+ *
+ * Author : Aditya Shakya
+ * Mail : adi1090x@gmail.com
+ * Github : @adi1090x
+ * Twitter : @adi1090x
+ *
+ */
+
+configuration {
+ font: "Iosevka Nerd Font 10";
+ show-icons: true;
+ icon-theme: "Papirus";
+ display-drun: "";
+ drun-display-format: "{name}";
+ disable-history: false;
+ fullscreen: false;
+ hide-scrollbar: true;
+ sidebar-mode: false;
+}
+
+@import "colors.rasi"
+
+window {
+ transparency: "real";
+ background-color: @bg;
+ text-color: @fg;
+ border: 0px;
+ border-color: @ac;
+ border-radius: 0px;
+ width: 300px;
+ location: center;
+ x-offset: 0;
+ y-offset: 0;
+}
+
+prompt {
+ enabled: true;
+ padding: 0px 0px 0px 5px;
+ background-color: @al;
+ text-color: @fg;
+}
+
+textbox-prompt-colon {
+ padding: 0px 0px 0px 2px;
+ background-color: @al;
+ text-color: @ac;
+ expand: false;
+ str: "";
+ font: "feather 12";
+}
+
+entry {
+ background-color: @al;
+ text-color: @fg;
+ placeholder-color: @fg;
+ expand: true;
+ horizontal-align: 0;
+ placeholder: "Search...";
+ padding: 0px;
+ blink: true;
+}
+
+inputbar {
+ children: [ textbox-prompt-colon, prompt ];
+ background-color: @bga;
+ text-color: @fg;
+ expand: false;
+ border: 0px 0px 0px 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ margin: 0px;
+ padding: 12px;
+}
+
+listview {
+ background-color: @al;
+ padding: 0px;
+ columns: 1;
+ lines: 5;
+ spacing: 0px;
+ cycle: true;
+ dynamic: true;
+ layout: vertical;
+}
+
+mainbox {
+ background-color: @al;
+ border: 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ children: [ inputbar, listview ];
+ spacing: 0px;
+ padding: 0px;
+}
+
+element {
+ background-color: @al;
+ text-color: @fg;
+ orientation: horizontal;
+ border-radius: 0px;
+ padding: 8px 8px 8px -15px;
+}
+
+element-icon {
+ size: 24px;
+ border: 0px;
+}
+
+element-text {
+ expand: true;
+ horizontal-align: 0;
+ vertical-align: 0.5;
+ margin: 0px 2.5px 0px 2.5px;
+}
+
+element selected {
+ background-color: @se;
+ text-color: @fg;
+ border: 0px 0px 0px 2px;
+ border-radius: 0px;
+ border-color: @ac;
+}
diff --git a/polybar/cuts/scripts/rofi/styles.rasi b/polybar/cuts/scripts/rofi/styles.rasi
new file mode 100644
index 0000000..6d3b7f2
--- /dev/null
+++ b/polybar/cuts/scripts/rofi/styles.rasi
@@ -0,0 +1,123 @@
+/*
+ *
+ * Author : Aditya Shakya
+ * Mail : adi1090x@gmail.com
+ * Github : @adi1090x
+ * Twitter : @adi1090x
+ *
+ */
+
+configuration {
+ font: "Iosevka Nerd Font 10";
+ show-icons: true;
+ icon-theme: "Papirus";
+ display-drun: "";
+ drun-display-format: "{name}";
+ disable-history: false;
+ fullscreen: false;
+ hide-scrollbar: true;
+ sidebar-mode: false;
+}
+
+@import "colors.rasi"
+
+window {
+ transparency: "real";
+ background-color: @bg;
+ text-color: @fg;
+ border: 0px;
+ border-color: @ac;
+ border-radius: 0px;
+ width: 300px;
+ location: center;
+ x-offset: 0;
+ y-offset: 0;
+}
+
+prompt {
+ enabled: true;
+ padding: 0px 0px 0px 5px;
+ background-color: @al;
+ text-color: @fg;
+}
+
+textbox-prompt-colon {
+ padding: 0px 0px 0px 2px;
+ background-color: @al;
+ text-color: @ac;
+ expand: false;
+ str: "";
+ font: "feather 12";
+}
+
+entry {
+ background-color: @al;
+ text-color: @fg;
+ placeholder-color: @fg;
+ expand: true;
+ horizontal-align: 0;
+ placeholder: "Search...";
+ padding: 0px 0px 0px 5px;
+ blink: true;
+}
+
+inputbar {
+ children: [ textbox-prompt-colon, entry ];
+ background-color: @bga;
+ text-color: @fg;
+ expand: false;
+ border: 0px 0px 0px 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ margin: 0px;
+ padding: 12px;
+}
+
+listview {
+ background-color: @al;
+ padding: 0px;
+ columns: 1;
+ lines: 5;
+ spacing: 0px;
+ cycle: true;
+ dynamic: true;
+ layout: vertical;
+}
+
+mainbox {
+ background-color: @al;
+ border: 0px;
+ border-radius: 0px;
+ border-color: @ac;
+ children: [ inputbar, listview ];
+ spacing: 0px;
+ padding: 0px;
+}
+
+element {
+ background-color: @al;
+ text-color: @fg;
+ orientation: horizontal;
+ border-radius: 0px;
+ padding: 8px 8px 8px -15px;
+}
+
+element-icon {
+ size: 24px;
+ border: 0px;
+}
+
+element-text {
+ expand: true;
+ horizontal-align: 0;
+ vertical-align: 0.5;
+ margin: 0px 2.5px 0px 2.5px;
+}
+
+element selected {
+ background-color: @se;
+ text-color: @fg;
+ border: 0px 0px 0px 2px;
+ border-radius: 0px;
+ border-color: @ac;
+}
diff --git a/polybar/cuts/scripts/style-switch.sh b/polybar/cuts/scripts/style-switch.sh
new file mode 100755
index 0000000..e693e53
--- /dev/null
+++ b/polybar/cuts/scripts/style-switch.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+SDIR="$HOME/.config/polybar/cuts/scripts"
+
+# Launch Rofi
+MENU="$(rofi -no-config -no-lazy-grab -sep "|" -dmenu -i -p '' \
+-theme $SDIR/rofi/styles.rasi \
+<<< " Black| Adapta| Dark| Red| Green| Teal| Gruvbox| Nord| Solarized| Cherry|")"
+ case "$MENU" in
+ *Black) "$SDIR"/styles.sh --mode1 ;;
+ *Adapta) "$SDIR"/styles.sh --mode2 ;;
+ *Dark) "$SDIR"/styles.sh --mode3 ;;
+ *Red) "$SDIR"/styles.sh --mode4 ;;
+ *Green) "$SDIR"/styles.sh --mode5 ;;
+ *Teal) "$SDIR"/styles.sh --mode6 ;;
+ *Gruvbox) "$SDIR"/styles.sh --mode7 ;;
+ *Nord) "$SDIR"/styles.sh --mode8 ;;
+ *Solarized) "$SDIR"/styles.sh --mode9 ;;
+ *Cherry) "$SDIR"/styles.sh --mode10 ;;
+ esac
diff --git a/polybar/cuts/scripts/styles.sh b/polybar/cuts/scripts/styles.sh
new file mode 100755
index 0000000..94b6739
--- /dev/null
+++ b/polybar/cuts/scripts/styles.sh
@@ -0,0 +1,89 @@
+#!/usr/bin/env bash
+
+# Color files
+PFILE="$HOME/.config/polybar/cuts/colors.ini"
+RFILE="$HOME/.config/polybar/cuts/scripts/rofi/colors.rasi"
+
+# Change colors
+change_color() {
+ # polybar
+ sed -i -e "s/background = #.*/background = #${BG}/g" $PFILE
+ sed -i -e "s/background-alt = #.*/background-alt = #8C${BG}/g" $PFILE
+ sed -i -e "s/foreground = #.*/foreground = #${FG}/g" $PFILE
+ sed -i -e "s/foreground-alt = #.*/foreground-alt = #33${FG}/g" $PFILE
+ sed -i -e "s/primary = #.*/primary = $AC/g" $PFILE
+
+ # rofi
+ cat > $RFILE <<- EOF
+ /* colors */
+
+ * {
+ al: #00000000;
+ bg: #${BG}BF;
+ bga: #${BG}FF;
+ fg: #${FG}FF;
+ ac: ${AC}FF;
+ se: ${AC}1A;
+ }
+ EOF
+
+ polybar-msg cmd restart
+}
+
+if [[ $1 = "--mode1" ]]; then
+ BG="0a0a0a"
+ FG="f5f5f5"
+ AC="#fdd835"
+ change_color
+elif [[ $1 = "--mode2" ]]; then
+ BG="263238"
+ FG="DFDFDF"
+ AC="#00BCD4"
+ change_color
+elif [[ $1 = "--mode3" ]]; then
+ BG="112526"
+ FG="C4AAA5"
+ AC="#EE7313"
+ change_color
+elif [[ $1 = "--mode4" ]]; then
+ BG="461320"
+ FG="f5f5f5"
+ AC="#fdd835"
+ change_color
+elif [[ $1 = "--mode5" ]]; then
+ BG="092F1C"
+ FG="f5f5f5"
+ AC="#fdd835"
+ change_color
+elif [[ $1 = "--mode6" ]]; then
+ BG="003C3C"
+ FG="CFCFCF"
+ AC="#00acc1"
+ change_color
+elif [[ $1 = "--mode7" ]]; then
+ BG="3C3836"
+ FG="EBDBB2"
+ AC="#FB4934"
+ change_color
+elif [[ $1 = "--mode8" ]]; then
+ BG="2E3440"
+ FG="D8DEE9"
+ AC="#BF616A"
+ change_color
+elif [[ $1 = "--mode9" ]]; then
+ BG="002b36"
+ FG="839496"
+ AC="#b58900"
+ change_color
+elif [[ $1 = "--mode10" ]]; then
+ BG="1F1626"
+ FG="FFFFFF"
+ AC="#FFD16F"
+ change_color
+else
+ cat <<- _EOF_
+ No option specified, Available options:
+ --mode1 --mode2 --mode3 --mode4 --mode5
+ --mode6 --mode7 --mode8 --mode9 --mode10
+ _EOF_
+fi
diff --git a/polybar/cuts/scripts/updates.sh b/polybar/cuts/scripts/updates.sh
new file mode 100755
index 0000000..9dcc903
--- /dev/null
+++ b/polybar/cuts/scripts/updates.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+
+NOTIFY_ICON=/usr/share/icons/Papirus/32x32/apps/system-software-update.svg
+
+get_total_updates() { UPDATES=$(checkupdates 2>/dev/null | wc -l); }
+
+while true; do
+ get_total_updates
+
+ # notify user of updates
+ #if hash notify-send &>/dev/null; then
+ # if (( UPDATES > 50 )); then
+ # notify-send -u critical -i $NOTIFY_ICON \
+ # "You really need to update!!" "$UPDATES New packages"
+ # elif (( UPDATES > 25 )); then
+ # notify-send -u normal -i $NOTIFY_ICON \
+ # "You should update soon" "$UPDATES New packages"
+ # elif (( UPDATES > 2 )); then
+ # notify-send -u low -i $NOTIFY_ICON \
+ # "$UPDATES New packages"
+ # fi
+ #fi
+
+ # when there are updates available
+ # every 10 seconds another check for updates is done
+ while (( UPDATES > 0 )); do
+ if (( UPDATES == 1 )); then
+ echo " $UPDATES"
+ elif (( UPDATES > 1 )); then
+ echo " $UPDATES"
+ else
+ echo " None"
+ fi
+ sleep 10
+ get_total_updates
+ done
+
+ # when no updates are available, use a longer loop, this saves on CPU
+ # and network uptime, only checking once every 30 min for new updates
+ while (( UPDATES == 0 )); do
+ echo " None"
+ sleep 1800
+ get_total_updates
+ done
+done
diff --git a/polybar/cuts/user_modules.ini b/polybar/cuts/user_modules.ini
new file mode 100644
index 0000000..a1a250c
--- /dev/null
+++ b/polybar/cuts/user_modules.ini
@@ -0,0 +1,258 @@
+[module/updates]
+type = custom/script
+
+; Available tokens:
+; %counter%
+; Command to be executed (using "/usr/bin/env sh -c [command]")
+exec = ~/.config/polybar/cuts/scripts/updates.sh
+
+; Conditional command that, if defined, needs to exit successfully
+; before the main exec command is invoked.
+; Default: ""
+;;exec-if = ""
+
+; Will the script output continous content?
+; Default: false
+tail = true
+
+; Seconds to sleep between updates
+; Default: 2 (0 if `tail = true`)
+interval = 5
+
+; Available tags:
+; <output> - deprecated
+; <label> (default)
+format = <label>
+format-prefix = 
+format-background = ${color.background}
+format-padding = 1
+
+; Available tokens:
+; %output%
+; Default: %output%
+label = %output%
+
+; Available tokens:
+; %counter%
+; %pid%
+;
+; "click-(left|middle|right)" will be executed using "/usr/bin/env sh -c [command]"
+click-left = exo-open --launch TerminalEmulator &
+click-right = exo-open --launch TerminalEmulator &
+;;double-click-left = echo double left %counter%
+;;double-click-middle = echo double middle %counter%
+;;double-click-right = echo double right %counter%
+
+; Available tokens:
+; %counter%
+; %pid%
+;
+; "scroll-(up|down)" will be executed using "/usr/bin/env sh -c [command]"
+;;scroll-up = echo scroll up %counter%
+;;scroll-down = echo scroll down %counter%
+
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/launcher]
+type = custom/text
+content = 
+
+; "content" has the same properties as "format-NAME"
+content-background = ${color.background}
+content-foreground = ${color.primary}
+content-padding = 1
+
+; "click-(left|middle|right)" will be executed using "/usr/bin/env sh -c $COMMAND"
+click-left = ~/.config/polybar/cuts/scripts/launcher.sh &
+;;click-middle = ~/.config/polybar/cuts/scripts/launcher-full
+click-right = ~/.config/polybar/cuts/scripts/color-switch.sh &
+
+; "scroll-(up|down)" will be executed using "/usr/bin/env sh -c $COMMAND"
+;;scroll-up = ~/.config/polybar/cuts/scripts/launcher.sh &
+;;scroll-down = ~/.config/polybar/cuts/scripts/color-switch.sh &
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/sysmenu]
+type = custom/text
+content = 
+
+content-background = ${color.background}
+content-foreground = ${color.primary}
+content-padding = 1
+
+click-left = ~/.config/polybar/cuts/scripts/powermenu.sh &
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/color-switch]
+type = custom/text
+content = 
+
+content-background = ${color.background}
+content-foreground = ${color.foreground}
+content-padding = 1
+
+click-left = ~/.config/polybar/cuts/scripts/style-switch.sh &
+click-right = ~/.config/polybar/cuts/scripts/color-switch.sh &
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/apps]
+type = custom/text
+content-background = ${color.background}
+content-padding = 1
+
+[module/term]
+inherit = module/apps
+content = 
+content-foreground = #fdd835
+click-left = termite &
+click-middle = urxvt &
+click-right = xfce4-terminal &
+
+[module/files]
+inherit = module/apps
+content-foreground = #1e88e5
+content = 
+click-left = thunar &
+click-right = pcmanfm &
+
+[module/browser]
+inherit = module/apps
+content-foreground = #fb8c00
+content = 
+click-left = firefox &
+click-right = chromium &
+
+[module/settings]
+inherit = module/apps
+content-foreground = #00897b
+content = 
+click-left = xfce4-settings-manager &
+click-right = lxappearance &
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/powermenu]
+type = custom/menu
+
+; If true, <label-toggle> will be to the left of the menu items (default).
+; If false, it will be on the right of all the items.
+expand-right = true
+
+; "menu-LEVEL-N" has the same properties as "label-NAME" with
+; the additional "exec" property
+;
+; Available exec commands:
+; menu-open-LEVEL
+; menu-close
+; Other commands will be executed using "/usr/bin/env sh -c $COMMAND"
+menu-0-0 = reboot
+menu-0-0-exec = menu-open-1
+menu-0-1 = shutdown
+menu-0-1-exec = menu-open-2
+
+menu-1-0 = back
+menu-1-0-exec = menu-open-0
+menu-1-1 = reboot
+menu-1-1-exec = systemctl reboot
+
+menu-2-0 = shutdown
+menu-2-0-exec = systemctl poweroff
+menu-2-1 = back
+menu-2-1-exec = menu-open-0
+
+; Available tags:
+; <label-toggle> (default) - gets replaced with <label-(open|close)>
+; <menu> (default)
+; Note that if you use <label-toggle> you must also include
+; the definition for <label-open>
+
+format = <label-toggle> <menu>
+format-background = ${color.background}
+format-padding = 1
+
+label-open = 
+label-close = 
+
+; Optional item separator
+; Default: none
+label-separator = " | "
+
+label-open-foreground = ${color.primary}
+label-close-foreground = ${color.primary}
+;;label-separator-foreground = ${color.background}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/menu]
+type = custom/menu
+
+; If true, <label-toggle> will be to the left of the menu items (default).
+; If false, it will be on the right of all the items.
+expand-right = true
+
+; "menu-LEVEL-N" has the same properties as "label-NAME" with
+; the additional "exec" property
+;
+; Available exec commands:
+; menu-open-LEVEL
+; menu-close
+; Other commands will be executed using "/usr/bin/env sh -c $COMMAND"
+menu-0-0 = Menu
+menu-0-0-exec = ~/.config/polybar/cuts/scripts/launcher.sh &
+menu-0-1 = Files
+menu-0-1-exec = thunar &
+menu-0-2 = Terminal
+menu-0-2-exec = termite &
+menu-0-3 = Browser
+menu-0-3-exec = firefox &
+
+; Available tags:
+; <label-toggle> (default) - gets replaced with <label-(open|close)>
+; <menu> (default)
+; Note that if you use <label-toggle> you must also include
+; the definition for <label-open>
+
+format = <label-toggle> <menu>
+format-background = ${color.background}
+format-padding = 1
+
+label-open = 
+label-close = 
+
+; Optional item separator
+; Default: none
+label-separator = " | "
+
+label-open-foreground = ${color.primary}
+label-close-foreground = ${color.primary}
+;;label-separator-foreground = ${color.background}
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
+[module/decor-glyph]
+type = custom/text
+content-background = ${color.background-alt}
+content-foreground = ${color.background}
+
+[module/decor1]
+inherit = module/decor-glyph
+content = "%{T3}%{T-}"
+
+[module/decor2]
+inherit = module/decor-glyph
+content = "%{T3}%{T-}"
+
+[module/decor3]
+inherit = module/decor-glyph
+content = "%{T3}%{T-}"
+
+[module/decor4]
+inherit = module/decor-glyph
+content = "%{T3}%{T-}"
+
+;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+
diff --git a/polybar/launch.sh b/polybar/launch.sh
new file mode 100755
index 0000000..f6d8fb0
--- /dev/null
+++ b/polybar/launch.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+dir="$HOME/.config/polybar"
+
+# Terminate already running bar instances
+killall -q polybar
+
+# Wait until the processes have been shut down
+while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
+
+# Launch the bar
+polybar -q top -c "$dir/cuts/config.ini" &
diff --git a/profanity/profrc b/profanity/profrc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/profanity/profrc
diff --git a/rofi/config.rasi b/rofi/config.rasi
new file mode 100644
index 0000000..dacc697
--- /dev/null
+++ b/rofi/config.rasi
@@ -0,0 +1,2 @@
+@theme "/usr/share/rofi/themes/gruvbox-dark-hard.rasi"
+@import "~/.cache/wal/colors-rofi-dark"
diff --git a/tmux/tmux.conf b/tmux/tmux.conf
new file mode 100644
index 0000000..172f59e
--- /dev/null
+++ b/tmux/tmux.conf
@@ -0,0 +1,8 @@
+# Prefix Ctrl+b
+
+bind P paste-buffer
+bind-key -T copy-mode-vi v send-keys -X begin-selection
+bind-key -T copy-mode-vi y send-keys -X copy-selection
+
+bind-key u capture-pane \; save-buffer /tmp/tmux-buffer \; split-window -h '$SHELL -c "urlview < /tmp/tmux-buffer"'
+bind-key z \; split-window -h '$SHELL -c "lf ~/stf"'
diff --git a/urlwview/.urlview b/urlwview/.urlview
new file mode 100644
index 0000000..15bf276
--- /dev/null
+++ b/urlwview/.urlview
@@ -0,0 +1,29 @@
+###############################################################################
+# Urlview configuration file.
+# man urlview <Man page>
+#
+# Put this file in: $HOME/.urlview
+# Put url_handler.sh in: /usr/bin
+#
+# You can call 'urlview' while in 'mutt' by pressing the Ctrl b keys.
+# Put these macros in your $HOME/.muttrc file.
+#
+# macro index \cb |urlview\n
+# macro pager \cb |urlview\n
+#
+# You can call 'urlview' while in 'tin' by pressing | then a for article,
+# put urlview as the pipe command.
+#
+# Regular expression to use to match URLs.
+
+#REGEXP (((http|https|ftp|gopher)|mailto):(//)?[^ >"\t]*|www\.[-a-z0-9.]+)[^ .,;\t>">\):]
+REGEXP (((http|https|ftp|gopher)|mailto)[.:][^ >"\t]*|www\.[-a-z0-9.]+)[^ .,;\t>">\):]
+
+# Command to invoke for selected URL. Use lynx, netscape, or url_handler.sh
+# shell script. Alternatively, you can leave COMMAND unset and set the BROWSER
+# environment variable instead.
+
+#COMMAND lynx %s
+#COMMAND netscape -remote 'openURL(%s)'
+COMMAND urlselect.sh
+
diff --git a/yt-dlp/config b/yt-dlp/config
new file mode 100644
index 0000000..8dce809
--- /dev/null
+++ b/yt-dlp/config
@@ -0,0 +1 @@
+-o '$HOME/stf/vids/%(title)s.%(ext)s'
diff --git a/zathura/zathurarc b/zathura/zathurarc
new file mode 100644
index 0000000..b75b4ad
--- /dev/null
+++ b/zathura/zathurarc
@@ -0,0 +1 @@
+set recolor false
diff --git a/zsh/.zprofile b/zsh/.zprofile
new file mode 100644
index 0000000..93d8d9f
--- /dev/null
+++ b/zsh/.zprofile
@@ -0,0 +1,7 @@
+[[ -f ~/.zshrc ]] && . ~/.zshrc
+
+# xinit
+
+if [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then
+ exec startx
+fi
diff --git a/zsh/.zsh/zsh-autosuggestions b/zsh/.zsh/zsh-autosuggestions
new file mode 160000
+Subproject a411ef3e0992d4839f0732ebeb9823024afaaaa
diff --git a/zsh/.zshenv b/zsh/.zshenv
new file mode 100644
index 0000000..4de5a45
--- /dev/null
+++ b/zsh/.zshenv
@@ -0,0 +1,32 @@
+typeset -U PATH path
+path=("$HOME/.local/bin" ~/stf/scripts/ "$path[@]")
+export PATH
+
+# Programs
+export EDITOR="nvim"
+export TERMINAL="st"
+export BROWSER="firefox"
+
+# Home clean-up
+export XDG_DATA_HOME="$HOME/.local/share"
+export XDG_CONFIG_HOME="$HOME/.config"
+export ZDOTDIR=$HOME/.config/zsh
+export HISTFILE="$XDG_STATE_HOME"/.config/zsh/history
+export WGETRC="$XDG_CONFIG_HOME/wgetrc"
+export WINEPREFIX="$XDG_DATA_HOME"/wineprefixes/default
+export NPM_CONFIG_USERCONFIG=$XDG_CONFIG_HOME/npm/npmrc
+export ELECTRUMDIR="$XDG_DATA_HOME/electrum"
+export GOPATH="$XDG_DATA_HOME/go"
+export PASSWORD_STORE_DIR="$XDG_DATA_HOME"/pass
+export GNUPGHOME="$XDG_DATA_HOME/gnupg"
+export XSERVERRC="$XDG_CONFIG_HOME/X11/xserverrc" vt1
+
+# Personal dirs
+export STUFF_DIR="$HOME/stf"
+export MUSIC_DIR="$HOME/stf/music"
+export VIDS_DIR="$HOME/stf/vids"
+export SS_DIR="$HOME/stf/ss"
+export DLS_DIR="$HOME/stf/dls"
+export SCRIPTS_DIR="$HOME/stf/scripts"
+export WEB_DIR="$HOME/stf/webdev"
+export ROMS_DIR="$HOME/HDD/P2_300G/ROMS"
diff --git a/zsh/.zshrc b/zsh/.zshrc
new file mode 100644
index 0000000..ed60251
--- /dev/null
+++ b/zsh/.zshrc
@@ -0,0 +1,78 @@
+# Export colors
+export TERM=xterm-256color
+
+# Colors and prompt
+autoload -U colors && colors
+PS1='%B %F{245}m%f in %F{088}%f%~ %F{245}$ %f'
+
+# History Files
+HISTFILE=~/.cache/zsh/histfile
+HISTSIZE=1000
+SAVEHIST=1000
+
+zstyle :compinstall filename '/home/monoblanco/.config/zsh/.zshrc'
+
+autoload -Uz compinit
+zstyle ':completion:*' menu select
+zmodload zsh/complist
+compinit
+_comp_options+=(globdots)
+
+# Syntax Highlighting
+source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.plugin.zsh
+
+# Autosuggestions
+source ~/.config/zsh/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
+
+# Alias generales
+alias ytsong="yt-dlp -x --audio-format mp3 -o '$HOME/stf/music/%(title)s.%(ext)s'"
+alias rm="rm -i"
+alias hdmion="xrandr --output HDMI-1 --mode 1360x768 --left-of DVI-D-1 && source '$HOME/.config/feh/.fehbg' && i3-msg restart"
+alias hdmioff="xrandr --output HDMI-1 --off && source '$HOME/.config/feh/.fehbg' && i3-msg restart"
+alias fmpv="setsid -f mpv"
+alias ll="ls -lA"
+alias vim="nvim"
+alias vps="ssh root@drainerdomain.xyz"
+alias t="todo.sh"
+
+# Home clean
+alias wget='wget --hsts-file="$XDG_CACHE_HOME/wget-hsts"'
+alias monerod='monerod --data-dir "$XDG_DATA_HOME"/bitmonero'
+alias gpg2='gpg2 --homedir "$XDG_DATA_HOME"/gnupg'
+
+# VIM TREE
+alias vimweb="nvim ~/stf/webdev"
+
+
+# Alias cfg
+alias ci3="vim $HOME/.config/i3/config"
+alias cpicom="vim $HOME/.config/picom.conf"
+alias cdunst="vim $HOME/.config/dunst/dunstrc"
+alias cmpd="vim $HOME/.config/mpd/mpd.conf"
+alias cmpv="vim $HOME/.config/mpv/mpv.conf"
+alias cncmp="vim $HOME/.config/ncmpcpp/config"
+alias cnewsu="vim $HOME/.config/newsboat/urls"
+alias cnews="vim $HOME/.config/newsboat/config"
+alias cpoly="vim $HOME/.config/polybar/cuts/config.ini"
+alias czsh="vim $HOME/.config/zsh/.zshrc"
+
+# One-time-neofetch
+[ $(pidof st | wc -w) -lt 2 ] && neofetch
+
+# Import colorscheme from 'wal' asynchronously
+# & # Run the process in the background.
+# ( ) # Hide shell job control messages.
+# Not supported in the "fish" shell.
+# (cat ~/.cache/wal/sequences &)
+
+# Alternative (blocks terminal for 0-3ms)
+# cat ~/.cache/wal/sequences
+
+# To add support for TTYs this line can be optionally added.
+source ~/.cache/wal/colors-tty.sh
+
+# Import the colors.
+. "${HOME}/.cache/wal/colors.sh"
+
+# Create the alias.
+alias dmen='dmenu_run -nb "$color0" -nf "$color15" -sb "$color1" -sf "$color15" -fn "Iosevka-11"'