commit 78482cbb6ff8654c940b12fbd78a8d2ebdf87c74 Author: juan Date: Sat Jun 25 21:26:38 2022 +0800 Chore | Clean history to save up data diff --git a/.config/kitty/kitty.conf b/.config/kitty/kitty.conf new file mode 100644 index 0000000..c2140b5 --- /dev/null +++ b/.config/kitty/kitty.conf @@ -0,0 +1,29 @@ +#set font and stuff +font_family IBM Plex Mono +bold_font IBM Plex Mono SemiBold +italic_font IBM Plex Mono Italic +bold_italic_font IBM Plex Mono SemiBold Italic + +font_size 13.5 + +symbol_map U+23FB-U+23FE,U+2B58,U+E200-U+E2A9,U+E0A0-U+E0A3,U+E0B0-U+E0BF,U+E0C0-U+E0C8,U+E0CC-U+E0CF,U+E0D0-U+E0D2,U+E0D4,U+E700-U+E7C5,U+F000-U+F2E0,U+2665,U+26A1,U+F400-U+F4A8,U+F67C,U+E000-U+E00A,U+F300-U+F313,U+E5FA-U+E62B Symbols-2048-em Nerd Font Complete + +# shell stuff +shell_integration enabled + +enable_audio_bell no + +visual_bell_duration 0.0 + +window_alert_on_bell yes + +# cosmetics +background_opacity 0.95 + +dynamic_background_opacity yes + +allow_hyperlinks ask + +map kitty_mod+n new_os_window_with_cwd + +include themes/serenade.conf diff --git a/.config/kitty/themes/everforest.conf b/.config/kitty/themes/everforest.conf new file mode 100644 index 0000000..f0f4585 --- /dev/null +++ b/.config/kitty/themes/everforest.conf @@ -0,0 +1,39 @@ +foreground #d8cacc +background #323d43 +selection_foreground #3c474d +selection_background #525c62 +url_color #415c6d +cursor #7fbbb3 + +# black +color0 #4a555b +color8 #525c62 + +# red +color1 #e68183 +color9 #e68183 + +# green +color2 #a7c080 +color10 #a7c080 + +# yellow +color3 #dbbc7f +color11 #dbbc7f + +# blue +color4 #7fbbb3 +color12 #7fbbb3 + +# magenta +color5 #d699b6 +color13 #d699b6 + +# cyan +color6 #83c092 +color14 #83c092 + +# white +color7 #d8caac +color15 #d8caac + diff --git a/.config/kitty/themes/iceberg_dark.conf b/.config/kitty/themes/iceberg_dark.conf new file mode 100644 index 0000000..eb7097d --- /dev/null +++ b/.config/kitty/themes/iceberg_dark.conf @@ -0,0 +1,46 @@ +background #161821 +foreground #c6c8d1 + +selection_background #1e2132 +selection_foreground #c6c8d1 + +cursor #d2d4de + +# black +color0 #161821 +color8 #6b7089 + +# red +color1 #e27878 +color9 #e98989 + +# green +color2 #b4be82 +color10 #c0ca8e + +# yellow/orange +color3 #e2a478 +color11 #e9b189 + +# blue +color4 #84a0c6 +color12 #91acd1 + +# magenta/purple +color5 #a093c7 +color13 #ada0d3 + +# cyan +color6 #89b8c2 +color14 #95c4ce + +# white +color7 #c6c8d1 +color15 #d2d4de + +# tab bar +active_tab_foreground #161821 +active_tab_background #84a0c6 +inactive_tab_foreground #d2d4de +inactive_tab_background #353a50 +tab_bar_background #0f1117 diff --git a/.config/kitty/themes/nord.conf b/.config/kitty/themes/nord.conf new file mode 100644 index 0000000..54f3a96 --- /dev/null +++ b/.config/kitty/themes/nord.conf @@ -0,0 +1,43 @@ +# Nord Colorscheme for Kitty +# Based on: +# - https://gist.github.com/marcusramberg/64010234c95a93d953e8c79fdaf94192 +# - https://github.com/arcticicestudio/nord-hyper + +foreground #D8DEE9 +background #2E3440 +selection_foreground #000000 +selection_background #FFFACD +url_color #0087BD +cursor #81A1C1 + +# black +color0 #3B4252 +color8 #4C566A + +# red +color1 #BF616A +color9 #BF616A + +# green +color2 #A3BE8C +color10 #A3BE8C + +# yellow +color3 #EBCB8B +color11 #EBCB8B + +# blue +color4 #81A1C1 +color12 #81A1C1 + +# magenta +color5 #B48EAD +color13 #B48EAD + +# cyan +color6 #88C0D0 +color14 #8FBCBB + +# white +color7 #E5E9F0 +color15 #ECEFF4 diff --git a/.config/kitty/themes/serenade.conf b/.config/kitty/themes/serenade.conf new file mode 100644 index 0000000..0e33c3a --- /dev/null +++ b/.config/kitty/themes/serenade.conf @@ -0,0 +1,39 @@ +foreground #bfddb2 +background #2A2f33 +selection_foreground #bfddb2 +selection_background #474f54 +url_color #e5a46b +cursor #82abbc + +# black +color0 #2a2f33 +color8 #3f464b + +# red +color1 #d76e6e +color9 #e68183 + +# green +color2 #acb765 +color10 #a7c080 + +# yellow +color3 #e5a46b +color11 #dbbc7f + +# blue +color4 #82abbc +color12 #7fbbb3 + +# magenta +color5 #d39bb6 +color13 #d699b6 + +# cyan +color6 #87c095 +color14 #83c092 + +# white +color7 #d8caac +color15 #d8caac + diff --git a/.config/mpv/mpv.conf b/.config/mpv/mpv.conf new file mode 100644 index 0000000..acd1e79 --- /dev/null +++ b/.config/mpv/mpv.conf @@ -0,0 +1,3 @@ +volume=50 +sub-auto=fuzzy +hwdec=auto-safe diff --git a/.config/mpv/scripts/autosub.lua b/.config/mpv/scripts/autosub.lua new file mode 100644 index 0000000..1866725 --- /dev/null +++ b/.config/mpv/scripts/autosub.lua @@ -0,0 +1,260 @@ +--============================================================================= +-->> SUBLIMINAL PATH: +--============================================================================= +-- This script uses Subliminal to download subtitles, +-- so make sure to specify your system's Subliminal location below: +local subliminal = '/home/juan/.local/bin//subliminal' +--============================================================================= +-->> SUBTITLE LANGUAGE: +--============================================================================= +-- Specify languages in this order: +-- { 'language name', 'ISO-639-1', 'ISO-639-2' } ! +-- (See: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) +local languages = { +-- If subtitles are found for the first language, +-- other languages will NOT be downloaded, +-- so put your preferred language first: + { 'English', 'en', 'eng' }, + { 'Chinese', 'zh', 'chi' }, + { 'Japanese', 'ja', 'jpn' }, +-- { 'Dutch', 'nl', 'dut' }, +-- { 'Spanish', 'es', 'spa' }, +-- { 'French', 'fr', 'fre' }, +-- { 'German', 'de', 'ger' }, +-- { 'Italian', 'it', 'ita' }, +-- { 'Portuguese', 'pt', 'por' }, +-- { 'Polish', 'pl', 'pol' }, +-- { 'Russian', 'ru', 'rus' }, +-- { 'Arabic', 'ar', 'ara' }, +} +--============================================================================= +-->> PROVIDER LOGINS: +--============================================================================= +-- These are completely optional and not required +-- for the functioning of the script! +-- If you use any of these services, simply uncomment it +-- and replace 'USERNAME' and 'PASSWORD' with your own: +local logins = { +-- { '--addic7ed', 'USERNAME', 'PASSWORD' }, +-- { '--legendastv', 'USERNAME', 'PASSWORD' }, +-- { '--opensubtitles', 'USERNAME', 'PASSWORD' }, +-- { '--subscenter', 'USERNAME', 'PASSWORD' }, +} +--============================================================================= +-->> ADDITIONAL OPTIONS: +--============================================================================= +local bools = { + auto = true, -- Automatically download subtitles, no hotkeys required + debug = false, -- Use `--debug` in subliminal command for debug output + force = true, -- Force download; will overwrite existing subtitle files + utf8 = true, -- Save all subtitle files as UTF-8 +} +local excludes = { + -- Movies with a path containing any of these strings/paths + -- will be excluded from auto-downloading subtitles. + -- Full paths are also allowed, e.g.: + -- '/home/david/Videos', + 'no-subs-dl', +} +local includes = { + -- If anything is defined here, only the movies with a path + -- containing any of these strings/paths will auto-download subtitles. + -- Full paths are also allowed, e.g.: + -- '/home/david/Videos', +} +--============================================================================= +local utils = require 'mp.utils' + + +-- Download function: download the best subtitles in most preferred language +function download_subs(language) + language = language or languages[1] + if #language == 0 then + log('No Language found\n') + return false + end + + log('Searching ' .. language[1] .. ' subtitles ...', 30) + + -- Build the `subliminal` command, starting with the executable: + local table = { args = { subliminal } } + local a = table.args + + for _, login in ipairs(logins) do + a[#a + 1] = login[1] + a[#a + 1] = login[2] + a[#a + 1] = login[3] + end + if bools.debug then + -- To see `--debug` output start MPV from the terminal! + a[#a + 1] = '--debug' + end + + a[#a + 1] = 'download' + if bools.force then + a[#a + 1] = '-f' + end + if bools.utf8 then + a[#a + 1] = '-e' + a[#a + 1] = 'utf-8' + end + + a[#a + 1] = '-l' + a[#a + 1] = language[2] + a[#a + 1] = '-d' + a[#a + 1] = directory + a[#a + 1] = filename --> Subliminal command ends with the movie filename. + + local result = utils.subprocess(table) + + if string.find(result.stdout, 'Downloaded 1 subtitle') then + -- When multiple external files are present, + -- always activate the most recently downloaded: + mp.set_property('slang', language[2]) + -- Subtitles are downloaded successfully, so rescan to activate them: + mp.commandv('rescan_external_files') + log(language[1] .. ' subtitles ready!') + return true + else + log('No ' .. language[1] .. ' subtitles found\n') + return false + end +end + +-- Manually download second language subs by pressing 'n': +function download_subs2() + download_subs(languages[2]) +end + +-- Control function: only download if necessary +function control_downloads() + -- Make MPV accept external subtitle files with language specifier: + mp.set_property('sub-auto', 'fuzzy') + -- Set subtitle language preference: + mp.set_property('slang', languages[1][2]) + mp.msg.warn('Reactivate external subtitle files:') + mp.commandv('rescan_external_files') + directory, filename = utils.split_path(mp.get_property('path')) + + if not autosub_allowed() then + return + end + + sub_tracks = {} + for _, track in ipairs(mp.get_property_native('track-list')) do + if track['type'] == 'sub' then + sub_tracks[#sub_tracks + 1] = track + end + end + if bools.debug then -- Log subtitle properties to terminal: + for _, track in ipairs(sub_tracks) do + mp.msg.warn('Subtitle track', track['id'], ':\n{') + for k, v in pairs(track) do + if type(v) == 'string' then v = '"' .. v .. '"' end + mp.msg.warn(' "' .. k .. '":', v) + end + mp.msg.warn('}\n') + end + end + + for _, language in ipairs(languages) do + if should_download_subs_in(language) then + if download_subs(language) then return end -- Download successful! + else return end -- No need to download! + end + log('No subtitles were found') +end + +-- Check if subtitles should be auto-downloaded: +function autosub_allowed() + local duration = tonumber(mp.get_property('duration')) + local active_format = mp.get_property('file-format') + + if not bools.auto then + mp.msg.warn('Automatic downloading disabled!') + return false + elseif duration < 900 then + mp.msg.warn('Video is less than 15 minutes\n' .. + '=> NOT auto-downloading subtitles') + return false + elseif directory:find('^http') then + mp.msg.warn('Automatic subtitle downloading is disabled for web streaming') + return false + elseif active_format:find('^cue') then + mp.msg.warn('Automatic subtitle downloading is disabled for cue files') + return false + else + local not_allowed = {'aiff', 'ape', 'flac', 'mp3', 'ogg', 'wav', 'wv', 'tta'} + + for _, file_format in pairs(not_allowed) do + if file_format == active_format then + mp.msg.warn('Automatic subtitle downloading is disabled for audio files') + return false + end + end + + for _, exclude in pairs(excludes) do + local escaped_exclude = exclude:gsub('%W','%%%0') + local excluded = directory:find(escaped_exclude) + + if excluded then + mp.msg.warn('This path is excluded from auto-downloading subs') + return false + end + end + + for i, include in ipairs(includes) do + local escaped_include = include:gsub('%W','%%%0') + local included = directory:find(escaped_include) + + if included then break + elseif i == #includes then + mp.msg.warn('This path is not included for auto-downloading subs') + return false + end + end + end + + return true +end + +-- Check if subtitles should be downloaded in this language: +function should_download_subs_in(language) + for i, track in ipairs(sub_tracks) do + local subtitles = track['external'] and + 'subtitle file' or 'embedded subtitles' + + if not track['lang'] and (track['external'] or not track['title']) + and i == #sub_tracks then + local status = track['selected'] and ' active' or ' present' + log('Unknown ' .. subtitles .. status) + mp.msg.warn('=> NOT downloading new subtitles') + return false -- Don't download if 'lang' key is absent + elseif track['lang'] == language[3] or track['lang'] == language[2] or + (track['title'] and track['title']:lower():find(language[3])) then + if not track['selected'] then + mp.set_property('sid', track['id']) + log('Enabled ' .. language[1] .. ' ' .. subtitles .. '!') + else + log(language[1] .. ' ' .. subtitles .. ' active') + end + mp.msg.warn('=> NOT downloading new subtitles') + return false -- The right subtitles are already present + end + end + mp.msg.warn('No ' .. language[1] .. ' subtitles were detected\n' .. + '=> Proceeding to download:') + return true +end + +-- Log function: log to both terminal and MPV OSD (On-Screen Display) +function log(string, secs) + secs = secs or 2.5 -- secs defaults to 2.5 when secs parameter is absent + mp.msg.warn(string) -- This logs to the terminal + mp.osd_message(string, secs) -- This logs to MPV screen +end + + +mp.add_key_binding('b', 'download_subs', download_subs) +mp.add_key_binding('n', 'download_subs2', download_subs2) +mp.register_event('file-loaded', control_downloads) diff --git a/.config/mpv/scripts/sponsorblock.lua b/.config/mpv/scripts/sponsorblock.lua new file mode 100644 index 0000000..55fb8ed --- /dev/null +++ b/.config/mpv/scripts/sponsorblock.lua @@ -0,0 +1,564 @@ +-- sponsorblock.lua +-- +-- This script skips sponsored segments of YouTube videos +-- using data from https://github.com/ajayyy/SponsorBlock + +local ON_WINDOWS = package.config:sub(1,1) ~= "/" + +local options = { + server_address = "https://sponsor.ajay.app", + + python_path = ON_WINDOWS and "python" or "python3", + + -- Categories to fetch + categories = "sponsor,intro,outro,interaction,selfpromo", + + -- Categories to skip automatically + skip_categories = "sponsor, selfpromo, interaction", + + -- If true, sponsored segments will only be skipped once + skip_once = true, + + -- Note that sponsored segments may ocasionally be inaccurate if this is turned off + -- see https://blog.ajay.app/voting-and-pseudo-randomness-or-sponsorblock-or-youtube-sponsorship-segment-blocker + local_database = true, + + -- Update database on first run, does nothing if local_database is false + auto_update = true, + + -- How long to wait between local database updates + -- Format: "X[d,h,m]", leave blank to update on every mpv run + auto_update_interval = "6h", + + -- User ID used to submit sponsored segments, leave blank for random + user_id = "", + + -- Name to display on the stats page https://sponsor.ajay.app/stats/ leave blank to keep current name + display_name = "", + + -- Tell the server when a skip happens + report_views = true, + + -- Auto upvote skipped sponsors + auto_upvote = false, + + -- Use sponsor times from server if they're more up to date than our local database + server_fallback = true, + + -- Create chapters at sponsor boundaries for OSC display and manual skipping + make_chapters = true, + + -- Minimum duration for sponsors (in seconds), segments under that threshold will be ignored + min_duration = 1, + + -- Fade audio for smoother transitions + audio_fade = false, + + -- Audio fade step, applied once every 100ms until cap is reached + audio_fade_step = 10, + + -- Audio fade cap + audio_fade_cap = 0, + + -- Fast forward through sponsors instead of skipping + fast_forward = false, + + -- Playback speed modifier when fast forwarding, applied once every second until cap is reached + fast_forward_increase = .2, + + -- Playback speed cap + fast_forward_cap = 2, + + -- Length of the sha256 prefix (3-32) when querying server, 0 to disable + sha256_length = 4, + + -- Pattern for video id in local files, ignored if blank + -- Recommended value for base youtube-dl is "-([%w-_]+)%.[mw][kpe][v4b]m?$" + local_pattern = "", + + -- Legacy option, use skip_categories instead + skip = true +} + +mp.options = require "mp.options" +mp.options.read_options(options, "sponsorblock") + +local legacy = mp.command_native_async == nil +if legacy then + options.local_database = false +end + +local utils = require "mp.utils" +scripts_dir = mp.find_config_file("scripts") + +local sponsorblock = utils.join_path(scripts_dir, "sponsorblock_shared/sponsorblock.py") +local uid_path = utils.join_path(scripts_dir, "sponsorblock_shared/sponsorblock.txt") +local database_file = options.local_database and utils.join_path(scripts_dir, "sponsorblock_shared/sponsorblock.db") or "" +local youtube_id = nil +local ranges = {} +local init = false +local segment = {a = 0, b = 0, progress = 0, first = true} +local retrying = false +local last_skip = {uuid = "", dir = nil} +local speed_timer = nil +local fade_timer = nil +local fade_dir = nil +local volume_before = mp.get_property_number("volume") +local categories = {} +local all_categories = {"sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"} +local chapter_cache = {} + +for category in string.gmatch(options.skip_categories, "([^,]+)") do + categories[category] = true +end + +function file_exists(name) + local f = io.open(name,"r") + if f ~= nil then io.close(f) return true else return false end +end + +function t_count(t) + local count = 0 + for _ in pairs(t) do count = count + 1 end + return count +end + +function time_sort(a, b) + if a.time == b.time then + return string.match(a.title, "segment end") + end + return a.time < b.time +end + +function parse_update_interval() + local s = options.auto_update_interval + if s == "" then return 0 end -- Interval Disabled + + local num, mod = s:match "^(%d+)([hdm])$" + + if num == nil or mod == nil then + mp.osd_message("[sponsorblock] auto_update_interval " .. s .. " is invalid", 5) + return nil + end + + local time_table = { + m = 60, + h = 60 * 60, + d = 60 * 60 * 24, + } + + return num * time_table[mod] +end + +function clean_chapters() + local chapters = mp.get_property_native("chapter-list") + local new_chapters = {} + for _, chapter in pairs(chapters) do + if chapter.title ~= "Preview segment start" and chapter.title ~= "Preview segment end" then + table.insert(new_chapters, chapter) + end + end + mp.set_property_native("chapter-list", new_chapters) +end + +function create_chapter(chapter_title, chapter_time) + local chapters = mp.get_property_native("chapter-list") + local duration = mp.get_property_native("duration") + table.insert(chapters, {title=chapter_title, time=(duration == nil or duration > chapter_time) and chapter_time or duration - .001}) + table.sort(chapters, time_sort) + mp.set_property_native("chapter-list", chapters) +end + +function process(uuid, t, new_ranges) + start_time = tonumber(string.match(t, "[^,]+")) + end_time = tonumber(string.sub(string.match(t, ",[^,]+"), 2)) + for o_uuid, o_t in pairs(ranges) do + if (start_time >= o_t.start_time and start_time <= o_t.end_time) or (o_t.start_time >= start_time and o_t.start_time <= end_time) then + new_ranges[o_uuid] = o_t + return + end + end + category = string.match(t, "[^,]+$") + if categories[category] and end_time - start_time >= options.min_duration then + new_ranges[uuid] = { + start_time = start_time, + end_time = end_time, + category = category, + skipped = false + } + end + if options.make_chapters and not chapter_cache[uuid] then + chapter_cache[uuid] = true + local category_title = (category:gsub("^%l", string.upper):gsub("_", " ")) + create_chapter(category_title .. " segment start (" .. string.sub(uuid, 1, 6) .. ")", start_time) + create_chapter(category_title .. " segment end (" .. string.sub(uuid, 1, 6) .. ")", end_time) + end +end + +function getranges(_, exists, db, more) + if type(exists) == "table" and exists["status"] == "1" then + if options.server_fallback then + mp.add_timeout(0, function() getranges(true, true, "") end) + else + return mp.osd_message("[sponsorblock] database update failed, gave up") + end + end + if db ~= "" and db ~= database_file then db = database_file end + if exists ~= true and not file_exists(db) then + if not retrying then + mp.osd_message("[sponsorblock] database update failed, retrying...") + retrying = true + end + return update() + end + if retrying then + mp.osd_message("[sponsorblock] database update succeeded") + retrying = false + end + local sponsors + local args = { + options.python_path, + sponsorblock, + "ranges", + db, + options.server_address, + youtube_id, + options.categories, + tostring(options.sha256_length) + } + if not legacy then + sponsors = mp.command_native({name = "subprocess", capture_stdout = true, playback_only = false, args = args}) + else + sponsors = utils.subprocess({args = args}) + end + mp.msg.debug("Got: " .. string.gsub(sponsors.stdout, "[\n\r]", "")) + if not string.match(sponsors.stdout, "^%s*(.*%S)") then return end + if string.match(sponsors.stdout, "error") then return getranges(true, true) end + local new_ranges = {} + local r_count = 0 + if more then r_count = -1 end + for t in string.gmatch(sponsors.stdout, "[^:%s]+") do + uuid = string.match(t, "([^,]+),[^,]+$") + if ranges[uuid] then + new_ranges[uuid] = ranges[uuid] + else + process(uuid, t, new_ranges) + end + r_count = r_count + 1 + end + local c_count = t_count(ranges) + if c_count == 0 or r_count >= c_count then + ranges = new_ranges + end +end + +function fast_forward() + if options.fast_forward and options.fast_forward == true then + speed_timer = nil + mp.set_property("speed", 1) + end + local last_speed = mp.get_property_number("speed") + local new_speed = math.min(last_speed + options.fast_forward_increase, options.fast_forward_cap) + if new_speed <= last_speed then return end + mp.set_property("speed", new_speed) +end + +function fade_audio(step) + local last_volume = mp.get_property_number("volume") + local new_volume = math.max(options.audio_fade_cap, math.min(last_volume + step, volume_before)) + if new_volume == last_volume then + if step >= 0 then fade_dir = nil end + if fade_timer ~= nil then fade_timer:kill() end + fade_timer = nil + return + end + mp.set_property("volume", new_volume) +end + +function skip_ads(name, pos) + if pos == nil then return end + local sponsor_ahead = false + for uuid, t in pairs(ranges) do + if (options.fast_forward == uuid or not options.skip_once or not t.skipped) and t.start_time <= pos and t.end_time > pos then + if options.fast_forward == uuid then return end + if options.fast_forward == false then + mp.osd_message("[sponsorblock] " .. t.category .. " skipped") + mp.set_property("time-pos", t.end_time) + else + mp.osd_message("[sponsorblock] skipping " .. t.category) + end + t.skipped = true + last_skip = {uuid = uuid, dir = nil} + if options.report_views or options.auto_upvote then + local args = { + options.python_path, + sponsorblock, + "stats", + database_file, + options.server_address, + youtube_id, + uuid, + options.report_views and "1" or "", + uid_path, + options.user_id, + options.auto_upvote and "1" or "" + } + if not legacy then + mp.command_native_async({name = "subprocess", playback_only = false, args = args}, function () end) + else + utils.subprocess_detached({args = args}) + end + end + if options.fast_forward ~= false then + options.fast_forward = uuid + if speed_timer ~= nil then speed_timer:kill() end + speed_timer = mp.add_periodic_timer(1, fast_forward) + end + return + elseif (not options.skip_once or not t.skipped) and t.start_time <= pos + 1 and t.end_time > pos + 1 then + sponsor_ahead = true + end + end + if options.audio_fade then + if sponsor_ahead then + if fade_dir ~= false then + if fade_dir == nil then volume_before = mp.get_property_number("volume") end + if fade_timer ~= nil then fade_timer:kill() end + fade_dir = false + fade_timer = mp.add_periodic_timer(.1, function() fade_audio(-options.audio_fade_step) end) + end + elseif fade_dir == false then + fade_dir = true + if fade_timer ~= nil then fade_timer:kill() end + fade_timer = mp.add_periodic_timer(.1, function() fade_audio(options.audio_fade_step) end) + end + end + if options.fast_forward and options.fast_forward ~= true then + options.fast_forward = true + speed_timer:kill() + speed_timer = nil + mp.set_property("speed", 1) + end +end + +function vote(dir) + if last_skip.uuid == "" then return mp.osd_message("[sponsorblock] no sponsors skipped, can't submit vote") end + local updown = dir == "1" and "up" or "down" + if last_skip.dir == dir then return mp.osd_message("[sponsorblock] " .. updown .. "vote already submitted") end + last_skip.dir = dir + local args = { + options.python_path, + sponsorblock, + "stats", + database_file, + options.server_address, + youtube_id, + last_skip.uuid, + "", + uid_path, + options.user_id, + dir + } + if not legacy then + mp.command_native_async({name = "subprocess", playback_only = false, args = args}, function () end) + else + utils.subprocess({args = args}) + end + mp.osd_message("[sponsorblock] " .. updown .. "vote submitted") +end + +function update() + mp.command_native_async({name = "subprocess", playback_only = false, args = { + options.python_path, + sponsorblock, + "update", + database_file, + options.server_address + }}, getranges) +end + +function file_loaded() + local initialized = init + ranges = {} + segment = {a = 0, b = 0, progress = 0, first = true} + last_skip = {uuid = "", dir = nil} + chapter_cache = {} + local video_path = mp.get_property("path", "") + mp.msg.debug("Path: " .. video_path) + local video_referer = string.match(mp.get_property("http-header-fields", ""), "Referer:([^,]+)") or "" + mp.msg.debug("Referer: " .. video_referer) + + local urls = { + "https?://youtu%.be/([%w-_]+).*", + "https?://w?w?w?%.?youtube%.com/v/([%w-_]+).*", + "/watch.*[?&]v=([%w-_]+).*", + "/embed/([%w-_]+).*" + } + youtube_id = nil + for i,url in ipairs(urls) do + youtube_id = youtube_id or string.match(video_path, url) or string.match(video_referer, url) + end + youtube_id = youtube_id or string.match(video_path, options.local_pattern) + + if not youtube_id or string.len(youtube_id) < 11 or (local_pattern and string.len(youtube_id) ~= 11) then return end + youtube_id = string.sub(youtube_id, 1, 11) + mp.msg.debug("Found YouTube ID: " .. youtube_id) + init = true + if not options.local_database then + getranges(true, true) + else + local exists = file_exists(database_file) + if exists and options.server_fallback then + getranges(true, true) + mp.add_timeout(0, function() getranges(true, true, "", true) end) + elseif exists then + getranges(true, true) + elseif options.server_fallback then + mp.add_timeout(0, function() getranges(true, true, "") end) + end + end + if initialized then return end + if options.skip then + mp.observe_property("time-pos", "native", skip_ads) + end + if options.display_name ~= "" then + local args = { + options.python_path, + sponsorblock, + "username", + database_file, + options.server_address, + youtube_id, + "", + "", + uid_path, + options.user_id, + options.display_name + } + if not legacy then + mp.command_native_async({name = "subprocess", playback_only = false, args = args}, function () end) + else + utils.subprocess_detached({args = args}) + end + end + if not options.local_database or (not options.auto_update and file_exists(database_file)) then return end + + if file_exists(database_file) then + local db_info = utils.file_info(database_file) + local cur_time = os.time(os.date("*t")) + local upd_interval = parse_update_interval() + if upd_interval == nil or os.difftime(cur_time, db_info.mtime) < upd_interval then return end + end + + update() +end + +function set_segment() + if not youtube_id then return end + local pos = mp.get_property_number("time-pos") + if pos == nil then return end + if segment.progress > 1 then + segment.progress = segment.progress - 2 + end + if segment.progress == 1 then + segment.progress = 0 + segment.b = pos + mp.osd_message("[sponsorblock] segment boundary B set, press again for boundary A", 3) + else + segment.progress = 1 + segment.a = pos + mp.osd_message("[sponsorblock] segment boundary A set, press again for boundary B", 3) + end + if options.make_chapters and not segment.first then + local start_time = math.min(segment.a, segment.b) + local end_time = math.max(segment.a, segment.b) + if end_time - start_time ~= 0 and end_time ~= 0 then + clean_chapters() + create_chapter("Preview segment start", start_time) + create_chapter("Preview segment end", end_time) + end + end + segment.first = false +end + +function select_category(selected) + for category in string.gmatch(options.categories, "([^,]+)") do + mp.remove_key_binding("select_category_"..category) + mp.remove_key_binding("kp_select_category_"..category) + end + submit_segment(selected) +end + +function submit_segment(category) + if not youtube_id then return end + local start_time = math.min(segment.a, segment.b) + local end_time = math.max(segment.a, segment.b) + if end_time - start_time == 0 or end_time == 0 then + mp.osd_message("[sponsorblock] empty segment, not submitting") + elseif segment.progress <= 1 then + segment.progress = segment.progress + 2 + local category_list = "" + for category_id, category in pairs(all_categories) do + local category_title = (category:gsub("^%l", string.upper):gsub("_", " ")) + category_list = category_list .. category_id .. ": " .. category_title .. "\n" + mp.add_forced_key_binding(tostring(category_id), "select_category_"..category, function() select_category(category) end) + mp.add_forced_key_binding("KP"..tostring(category_id), "kp_select_category_"..category, function() select_category(category) end) + end + mp.osd_message(string.format("[sponsorblock] press a number to select category for segment: %.2d:%.2d:%.2d to %.2d:%.2d:%.2d\n\n" .. category_list .. "\nyou can press Shift+G again for default (Sponsor) or hide this message with g", math.floor(start_time/(60*60)), math.floor(start_time/60%60), math.floor(start_time%60), math.floor(end_time/(60*60)), math.floor(end_time/60%60), math.floor(end_time%60)), 30) + else + mp.osd_message("[sponsorblock] submitting segment...", 30) + local submit + local args = { + options.python_path, + sponsorblock, + "submit", + database_file, + options.server_address, + youtube_id, + tostring(start_time), + tostring(end_time), + uid_path, + options.user_id, + category or "sponsor" + } + if not legacy then + submit = mp.command_native({name = "subprocess", capture_stdout = true, playback_only = false, args = args}) + else + submit = utils.subprocess({args = args}) + end + if string.match(submit.stdout, "success") then + segment = {a = 0, b = 0, progress = 0, first = true} + mp.osd_message("[sponsorblock] segment submitted") + if options.make_chapters then + clean_chapters() + create_chapter("Submitted segment start", start_time) + create_chapter("Submitted segment end", end_time) + end + elseif string.match(submit.stdout, "error") then + mp.osd_message("[sponsorblock] segment submission failed, server may be down. try again", 5) + elseif string.match(submit.stdout, "502") then + mp.osd_message("[sponsorblock] segment submission failed, server is down. try again", 5) + elseif string.match(submit.stdout, "400") then + mp.osd_message("[sponsorblock] segment submission failed, impossible inputs", 5) + segment = {a = 0, b = 0, progress = 0, first = true} + elseif string.match(submit.stdout, "429") then + mp.osd_message("[sponsorblock] segment submission failed, rate limited. try again", 5) + elseif string.match(submit.stdout, "409") then + mp.osd_message("[sponsorblock] segment already submitted", 3) + segment = {a = 0, b = 0, progress = 0, first = true} + else + mp.osd_message("[sponsorblock] segment submission failed", 5) + end + end +end + +mp.register_event("file-loaded", file_loaded) +mp.add_key_binding("g", "set_segment", set_segment) +mp.add_key_binding("G", "submit_segment", submit_segment) +mp.add_key_binding("h", "upvote_segment", function() return vote("1") end) +mp.add_key_binding("H", "downvote_segment", function() return vote("0") end) +-- Bindings below are for backwards compatibility and could be removed at any time +mp.add_key_binding(nil, "sponsorblock_set_segment", set_segment) +mp.add_key_binding(nil, "sponsorblock_submit_segment", submit_segment) +mp.add_key_binding(nil, "sponsorblock_upvote", function() return vote("1") end) +mp.add_key_binding(nil, "sponsorblock_downvote", function() return vote("0") end) diff --git a/.config/sway/config b/.config/sway/config new file mode 100644 index 0000000..f13d50d --- /dev/null +++ b/.config/sway/config @@ -0,0 +1,157 @@ +output * bg $(find ~/Pictures/Wallpapers/serenade/ -type f | shuf -n1) fill + +bar swaybar_command waybar + +set $mod Mod4 +set $left h +set $down j +set $up k +set $right l +set $term kitty -1 +set $menu wofi | xargs swaymsg exec -- + +###CUSTOMIZATION START### + +##starting userspace software +exec wlsunset -l 30.4 -L 104.0 -T 6500 -t 3500 +exec light -S 70 +exec gentoo-pipewire-launcher +exec swaync +exec playerctld daemon +exec dbus-update-activation-environment --all + +#my keybinds + +bindsym $mod+Ctrl+l exec ~/.config/sway/scripts/logout.sh +bindsym $mod+Print exec ~/.config/sway/scripts/grimshot-ui.sh +bindsym $mod+m exec swaync-client -t -sw + +#set gtk theme + +set $gnome-schema org.gnome.desktop.interface +exec_always { + gsettings set $gnome-schema gtk-theme 'Adwaita-dark' + gsettings set $gnome-schema icon-theme 'Papirus-Light' + gsettings set $gnome-schema cursor-theme 'Adwaita' + gsettings set $gnome-schema font-name 'ibm-plex 12' + gsettings set org.gtk.Settings.FileChooser startup-mode cwd +} + +#set colour + +#color class border backgr. text indicator child_border +client.focused #87c095 #2a2f33 #bfddb2 #415c6d #bfddb2 +client.focused_inactive #3f464b #2a2f33 #bfddb2 #415c6d #3f464b +client.unfocused #3f464b #2a2f33 #bfddb2 #415c6d #3f464b +client.urgent #d76e6e #2a2f33 #bfddb2 #415c6d #e68183 +client.placeholder #3f464b #2a2f33 #bfddb2 #415c6d #3f464b +client.background #3f464b #2a2f33 + +#bind fn keys + +bindsym XF86AudioMicMute exec amixer set Capture toggle +exec mkfifo $SWAYSOCK.wob && tail -f $SWAYSOCK.wob | wob -p 1 -b 2 -a top -M 48 --border-color '#474f54F0' --background-color '#2a2f33F0' --bar-color '#bfddb2F0' --overflow-mode wrap --overflow-background-color '#2a2f33F0' --overflow-bar-color '#d76e6ef0' --overflow-border-color '#474f54F0' +bindsym XF86AudioRaiseVolume exec amixer sset Master 2048+ | sed -En 's/.*\[([0-9]+)%\].*/\1/p' | head -1 > $SWAYSOCK.wob +bindsym XF86AudioLowerVolume exec amixer sset Master 2048- | sed -En 's/.*\[([0-9]+)%\].*/\1/p' | head -1 > $SWAYSOCK.wob +bindsym XF86AudioMute exec amixer sset Master toggle | sed -En '/\[on\]/ s/.*\[([0-9]+)%\].*/\1/ p; /\[off\]/ s/.*/0/p' | head -1 > $SWAYSOCK.wob +bindsym XF86MonBrightnessUp exec light -A 5 && light -G | cut -d'.' -f1 > $SWAYSOCK.wob +bindsym XF86MonBrightnessDown exec light -U 5 && light -G | cut -d'.' -f1 > $SWAYSOCK.wob + +bindsym XF86AudioPause exec 'playerctl pause' +bindsym XF86AudioPlay exec 'playerctl play' +bindsym XF86AudioStop exec 'playerctl stop' +bindsym XF86AudioNext exec 'playerctl next' +bindsym XF86AudioPrev exec 'playerctl previous' + +#borders stuff + +default_border pixel 1 +#workspace_auto_back_and_forth yes +force_display_urgency_hint 500 ms +smart_borders no_gaps + +#floating thingys +bindsym $mod+Shift+s floating toggle ; sticky toggle ; resize set 800 600 ; move position 55ppt 5ppt + +###END### + +# Start a terminal +bindsym $mod+Return exec $term +bindsym $mod+n exec $term +# Kill focused window +bindsym $mod+w kill +# Start your launcher +bindsym $mod+Shift+Return exec $menu +bindsym $mod+Shift+n exec $menu + +floating_modifier $mod normal + +bindsym $mod+Ctrl+r reload +bindsym $mod+Ctrl+q exit + +# Change fcitx IME +bindsym $mod+Ctrl+space exec fcitx5-remote -t + +# Move your focus around +bindsym $mod+$left focus left +bindsym $mod+$down focus down +bindsym $mod+$up focus up +bindsym $mod+$right focus right +# Move the focused window with the same, but add Shift +bindsym $mod+Shift+$left move left +bindsym $mod+Shift+$down move down +bindsym $mod+Shift+$up move up +bindsym $mod+Shift+$right move right +# resize windows +bindsym $mod+less resize shrink width 20px +bindsym $mod+greater resize grow width 20px +bindsym $mod+minus resize shrink height 20px +bindsym $mod+plus resize grow height 20px +# Switch to workspace +bindsym $mod+1 workspace number 1 +bindsym $mod+2 workspace number 2 +bindsym $mod+3 workspace number 3 +bindsym $mod+4 workspace number 4 +bindsym $mod+5 workspace number 5 +bindsym $mod+6 workspace number 6 +bindsym $mod+7 workspace number 7 +bindsym $mod+8 workspace number 8 +bindsym $mod+9 workspace number 9 +# Move focused container to workspace +bindsym $mod+Shift+1 move container to workspace number 1 +bindsym $mod+Shift+2 move container to workspace number 2 +bindsym $mod+Shift+3 move container to workspace number 3 +bindsym $mod+Shift+4 move container to workspace number 4 +bindsym $mod+Shift+5 move container to workspace number 5 +bindsym $mod+Shift+6 move container to workspace number 6 +bindsym $mod+Shift+7 move container to workspace number 7 +bindsym $mod+Shift+8 move container to workspace number 8 +bindsym $mod+Shift+9 move container to workspace number 9 +# +# Layout stuff: +# +# You can "split" the current object of your focus with +# $mod+b or $mod+v, for horizontal and vertical splits +# respectively. +bindsym $mod+c splith +bindsym $mod+v splitv +# Switch the current container between different layout styles +bindsym $mod+s layout stacking +bindsym $mod+t layout tabbed +bindsym $mod+e layout toggle split +# Make the current focus fullscreen +bindsym $mod+f fullscreen +# Toggle the current focus between tiling and floating mode +bindsym $mod+Shift+space floating toggle +# Swap focus between the tiling area and the floating area +bindsym $mod+space focus mode_toggle +# Move focus to the parent or child container +bindsym $mod+a focus parent +bindsym $mod+z focus child + +# Move the currently focused window to the scratchpad +bindsym $mod+Shift+0 move scratchpad +bindsym $mod+0 scratchpad show + +include ~/.config/sway/config.d/* +include /etc/sway/config.d/* diff --git a/.config/sway/scripts/boxshadow.sh b/.config/sway/scripts/boxshadow.sh new file mode 100755 index 0000000..719548e --- /dev/null +++ b/.config/sway/scripts/boxshadow.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Take $1 as input, add a box shadow, output to $2 + +# you can change background color here +background_color=none + +convert $1 \ + \( -clone 0 -background black -shadow 40x5+12+16 \) \ + \( -clone 0 -background black -shadow 40x5-4-4 \) \ + \( -clone 0 -background black -shadow 40x12+12-4 \) \ + \( -clone 0 -background black -shadow 40x12-4+16 \) \ + -reverse -background $background_color -layers merge +repage \ + $2 diff --git a/.config/sway/scripts/grimshot-ui.sh b/.config/sway/scripts/grimshot-ui.sh new file mode 100755 index 0000000..7160d0e --- /dev/null +++ b/.config/sway/scripts/grimshot-ui.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +SCRIPT_LOC=~/.config/sway/scripts/ +FILE="/tmp/share/screenshots/`date +'%y%m%d%H%M.png'`" + +action=`echo "copy\nsave" | wofi -d -Oalphabetical --prompt="Select your action"` +target=`echo "active\nscreen\noutput\narea\nwindow" | wofi -d -Oalphabetical --prompt="Select the target"` + +test $action || exit +test $target || exit + +test -d /tmp/share/screenshot || mkdir -p /tmp/share/screenshots + +# TODO, add box shadows + +XDG_SCREENSHOTS_DIR=/tmp/share/screenshots ~/.config/sway/scripts/grimshot.sh --notify $action $target $FILE + +if [ $target = "active" ] || [ $target = "window" ] || [ $target = "area" ] +then + $SCRIPT_LOC/boxshadow.sh "$FILE" "$FILE" || die "Unable to save screenshot" + echo "saved file" +fi diff --git a/.config/sway/scripts/grimshot.sh b/.config/sway/scripts/grimshot.sh new file mode 100755 index 0000000..7b65c9c --- /dev/null +++ b/.config/sway/scripts/grimshot.sh @@ -0,0 +1,156 @@ +#!/bin/sh + +## TAKEN FROM https://github.com/swaywm/sway/blob/master/contrib/grimshot +## +## Grimshot: a helper for screenshots within sway +## Requirements: +## - `grim`: screenshot utility for wayland +## - `slurp`: to select an area +## - `swaymsg`: to read properties of current window +## - `wl-copy`: clipboard utility +## - `jq`: json utility to parse swaymsg output +## - `notify-send`: to show notifications +## Those are needed to be installed, if unsure, run `grimshot check` +## +## See `man 1 grimshot` or `grimshot usage` for further details. + +getTargetDirectory() { + test -f ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs && \ + . ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs + + echo ${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}} +} + +if [ "$1" = "--notify" ]; then + NOTIFY=yes + shift 1 +else + NOTIFY=no +fi + +ACTION=${1:-usage} +SUBJECT=${2:-screen} +FILE=${3:-$(getTargetDirectory)/$(date +'%y%m%d%H%M.png')} + +if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then + echo "Usage:" + echo " grimshot [--notify] (copy|save) [active|screen|output|area|window] [FILE|-]" + echo " grimshot check" + echo " grimshot usage" + echo "" + echo "Commands:" + echo " copy: Copy the screenshot data into the clipboard." + echo " save: Save the screenshot to a regular file or '-' to pipe to STDOUT." + echo " check: Verify if required tools are installed and exit." + echo " usage: Show this message and exit." + echo "" + echo "Targets:" + echo " active: Currently active window." + echo " screen: All visible outputs." + echo " output: Currently active output." + echo " area: Manually select a region." + echo " window: Manually select a window." + exit +fi + +notify() { + notify-send -t 3000 -a grimshot "$@" +} +notifyOk() { + [ "$NOTIFY" = "no" ] && return + + TITLE=${2:-"Screenshot"} + MESSAGE=${1:-"OK"} + notify-send "$TITLE" "$MESSAGE" +} +notifyError() { + if [ $NOTIFY = "yes" ]; then + TITLE=${2:-"Screenshot"} + MESSAGE=${1:-"Error taking screenshot with grim"} + notify -u critical "$TITLE" "$MESSAGE" + else + echo $1 + fi +} + +die() { + MSG=${1:-Bye} + notifyError "Error: $MSG" + exit 2 +} + +check() { + COMMAND=$1 + if command -v "$COMMAND" > /dev/null 2>&1; then + RESULT="OK" + else + RESULT="NOT FOUND" + fi + echo " $COMMAND: $RESULT" +} + +takeScreenshot() { + FILE=$1 + GEOM=$2 + OUTPUT=$3 + if [ ! -z "$OUTPUT" ]; then + grim -o "$OUTPUT" "$FILE" || die "Unable to invoke grim" + elif [ -z "$GEOM" ]; then + grim "$FILE" || die "Unable to invoke grim" + else + grim -g "$GEOM" "$FILE" || die "Unable to invoke grim" + fi +} + +if [ "$ACTION" = "check" ] ; then + echo "Checking if required tools are installed. If something is missing, install it to your system and make it available in PATH..." + check grim + check slurp + check swaymsg + check wl-copy + check jq + check notify-send + exit +elif [ "$SUBJECT" = "area" ] ; then + GEOM=$(slurp -d) + # Check if user exited slurp without selecting the area + if [ -z "$GEOM" ]; then + exit 1 + fi + WHAT="Area" +elif [ "$SUBJECT" = "active" ] ; then + FOCUSED=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused)') + GEOM=$(echo "$FOCUSED" | jq -r '.rect | "\(.x),\(.y) \(.width)x\(.height)"') + APP_ID=$(echo "$FOCUSED" | jq -r '.app_id') + WHAT="$APP_ID window" +elif [ "$SUBJECT" = "screen" ] ; then + GEOM="" + WHAT="Screen" +elif [ "$SUBJECT" = "output" ] ; then + GEOM="" + OUTPUT=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused)' | jq -r '.name') + WHAT="$OUTPUT" +elif [ "$SUBJECT" = "window" ] ; then + GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp) + # Check if user exited slurp without selecting the area + if [ -z "$GEOM" ]; then + exit 1 + fi + WHAT="Window" +else + die "Unknown subject to take a screen shot from" "$SUBJECT" +fi + +if [ "$ACTION" = "copy" ] ; then + takeScreenshot - "$GEOM" "$OUTPUT" | wl-copy --type image/png || die "Clipboard error" + notifyOk "$WHAT copied to buffer" +else + if takeScreenshot "$FILE" "$GEOM" "$OUTPUT"; then + TITLE="Screenshot of $SUBJECT" + MESSAGE=$(basename "$FILE") + notifyOk "$MESSAGE" "$TITLE" + echo $FILE + else + notifyError "Error taking screenshot with grim" + fi +fi diff --git a/.config/sway/scripts/logout.sh b/.config/sway/scripts/logout.sh new file mode 100755 index 0000000..90fe787 --- /dev/null +++ b/.config/sway/scripts/logout.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +choice=`echo "suspend\nshutdown\npoweroff\nreboot\nlock\nhibernate" | wofi -d -Oalphabetical` +if test "$choice" = lock ; then + bright=`light` + swayidle -w \ + timeout 5 "light -S 1" resume "light -S $bright" \ + timeout 10 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \ + & + idlepid=$! + swaylock -e -c 2a2f33 --inside-color 00000003 + kill $idlepid + swaymsg "output * dpms on" + light -S $bright + return 0 +fi +loginctl $choice diff --git a/.config/swaync/config.json b/.config/swaync/config.json new file mode 100644 index 0000000..fc8f790 --- /dev/null +++ b/.config/swaync/config.json @@ -0,0 +1,25 @@ +{ + "$schema": "/etc/xdg/swaync/configSchema.json", + "positionX": "right", + "positionY": "top", + "control-center-margin-top": 12, + "control-center-margin-bottom": 256, + "control-center-margin-right": 8, + "control-center-margin-left": 8, + "timeout": 10, + "timeout-low": 5, + "timeout-critical": 0, + "notification-window-width": 500, + "keyboard-shortcuts": true, + "image-visibility": "always", + "transition-time": 200, + "hide-on-clear": true, + "hide-on-action": true, + "script-fail-notify": true, + "scripts": { + "example-script": { + "exec": "echo 'Do something...'", + "urgency": "Normal" + } + } +} diff --git a/.config/swaync/style.css b/.config/swaync/style.css new file mode 100644 index 0000000..88654fb --- /dev/null +++ b/.config/swaync/style.css @@ -0,0 +1,157 @@ +/* + * vim: ft=less + */ + +@define-color border-color #7f868c; +@define-color bg #2e3338; +@define-color bg-trans rgba(46, 51, 56, 0.9); +@define-color bg-hover #373d41; +@define-color bg-focus #474f54; +@define-color bg-selected #3f464b; +@define-color fg #bfddb2; +@define-color orange #e5a46b; +@define-color blue #82abbc; + +.notification-row { + outline: none; + background: transparent; +} +.notification-row:focus, +.notification-row:hover { + background: @bg-hover; +} + +.notification { + border-radius: 2px; + margin: 6px 12px; + box-shadow: 0px 2px 4px 2px rgba(0, 0, 0, 0.3); + padding: 0; +} + +.notification-content { + background: transparent; + padding: 6px; + border-radius: 3px; +} + +.close-button { + background: black; + color: white; + text-shadow: none; + padding: 0 2px; + box-shadow: 0px 2px 4px 2px rgba(0, 0, 0, 0.3); + border-radius: 50%; +} +.close-button:hover { + background: rgb(30, 30, 30); + transition: all 0.15s ease-in-out; +} + +.notification-default-action, +.notification-action { + padding: 4px; + margin: 0; + box-shadow: none; + background: @bg; + border: 1px solid @border-color; +} + +.notification-default-action:hover, +.notification-action:hover { + background: @bg-hover; +} + +.notification-default-action { + border-radius: 3px; +} + +/* When alternative actions are visible */ +.notification-default-action:not(:only-child) { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; +} + +.notification-action { + border-radius: 0px; + border-top: none; + border-right: none; +} + +/* add bottom border radius to eliminate clipping */ +.notification-action:first-child { + border-bottom-left-radius: 10px; +} +.notification-action:last-child { + border-bottom-right-radius: 10px; + border-right: 1px solid @border-color; +} + +.body-image { + margin-top: 6px; + background-color: white; + border-radius: 3px; +} + +.summary { + color: @fg; + text-shadow: none; +} + +.time { + color: @fg; + text-shadow: none; +} + +.body { + background: transparent; + color: @fg; + text-shadow: none; +} + +.top-action-title { + color: @fg; + text-shadow: none; +} + +.control-center-clear-all { + color: @orange; + text-shadow: none; + background: @bg; + border: 1px solid @border-color; + box-shadow: none; + border-radius: 3px; +} +.control-center-clear-all:hover { + background: @bg-hover; +} + +.control-center-dnd { + border-radius: 3px; + background: @bg; + border: 1px solid @border-color; + box-shadow: none; +} + +.control-center-dnd:checked { + background: @blue; +} +.control-center-dnd slider { + border-radius: 3px; + background: @bg-hover; + border: 1px solid @border-color; +} + +.control-center { + background: @bg-trans; + border-radius: 5px; + border: 1px solid @border-color; +} +.control-center-list { + background: @bg-trans; + border: 1px @border-color; + border-style: dashed solid hidden solid; +} + +.floating-notifications { + background: transparent; +} diff --git a/.config/task/taskrc b/.config/task/taskrc new file mode 100644 index 0000000..ff37f35 --- /dev/null +++ b/.config/task/taskrc @@ -0,0 +1,33 @@ +# [Created by task 2.5.3 9/17/2021 21:55:33] +# Taskwarrior program configuration file. +# For more documentation, see http://taskwarrior.org or try 'man task', 'man task-color', +# 'man task-sync' or 'man taskrc' + +# Here is an example of entries that use the default, override and blank values +# variable=foo -- By specifying a value, this overrides the default +# variable= -- By specifying no value, this means no default +# #variable=foo -- By commenting out the line, or deleting it, this uses the default + +# Use the command 'task show' to see all defaults and overrides + +verbose=blank,header,footnote,label,new-id,affected,edit,special,project,sync,unwait,recur + +# Files +data.location=~/.config/task/tasks + +# Color theme (uncomment one to use) +#include /usr/share/task/rc/light-16.theme +#include /usr/share/task/rc/light-256.theme +include /usr/share/task/rc/dark-16.theme +#include /usr/share/task/rc/dark-256.theme +#include /usr/share/task/rc/dark-red-256.theme +#include /usr/share/task/rc/dark-green-256.theme +#include /usr/share/task/rc/dark-blue-256.theme +#include /usr/share/task/rc/dark-violets-256.theme +#include /usr/share/task/rc/dark-yellow-green.theme +#include /usr/share/task/rc/dark-gray-256.theme +#include /usr/share/task/rc/dark-gray-blue-256.theme +#include /usr/share/task/rc/solarized-dark-256.theme +#include /usr/share/task/rc/solarized-light-256.theme +#include /usr/share/task/rc/no-color.theme + diff --git a/.config/tmux/tmux.conf b/.config/tmux/tmux.conf new file mode 100644 index 0000000..bf6b6dc --- /dev/null +++ b/.config/tmux/tmux.conf @@ -0,0 +1,41 @@ +# plugins +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' +#set -g @plugin "arcticicestudio/nord-tmux" +#set -g @plugin 'tmux-plugins/tmux-prefix-highlight' + +# FILE: iceberg_minimal.tmux.conf +# REPO: https://github.com/gkeep/iceberg-dark +# MAINTAINER: gkeep + +set -g status-position bottom +set -g status-justify centre +set -g status-style "bg=#474f54" +set -g window-style "" +set -g window-active-style "" + +# modules +module_left_1="#h" +module_left_2="#{client_width}x#{client_height}" + +module_right_1="%a %d %b" +module_right_2="%R %Z" + +set -g status-left " #[fg=#bfddb2]$module_left_1 #[fg=#767b82]$module_left_2" +set -g status-left-style "" +set -g status-left-length 50 + +set -g status-right "$module_right_1 #[fg=#bfddb2]$module_right_2 " +set -g status-right-style "fg=#767b82" +set -g status-right-length 25 + +set -g window-status-current-style "bold" +set -g window-status-style "fg=#767b82" +set -g window-status-format " #[fg=#bfddb2]#{?#{==:#W,fish},#{b:pane_current_path},#W}#F " +set -g window-status-current-format " #[fg=#bfddb2]#{?#{==:#W,fish},#{b:pane_current_path},#W}#F " +set -g window-status-separator "" + +set -g pane-active-border-style "fg=#767b82" +set -g pane-border-style "fg=#767b82" + +run '~/.tmux/plugins/tpm/tpm' diff --git a/.config/waybar/config b/.config/waybar/config new file mode 100644 index 0000000..e7589e2 --- /dev/null +++ b/.config/waybar/config @@ -0,0 +1,88 @@ +{ + "layer": "top", + "modules-left": [ + "sway/workspaces" + ], + "fixed-center": false, + "modules-center": [ + "sway/window" + ], + "modules-right": [ + "tray", + "custom/notification", + "custom/player", + "cpu", + "memory", + "network", + "battery", + "clock" + ], + "sway/window": { + "max-length": 50 + }, + "tray": { + "spacing": 10 + }, + "cpu": { + "format": " {load}" + }, + "memory": { + "format": " {used:0.1f}G / {total:0.1f}G" + }, + "network": { + "format-wifi": " {essid} ({signalStrength}%)", + "format-ethernet": " {ifname}: {ipaddr}/{cidr}", + "format-linked": " {ifname} (No IP)", + "format-disconnected": " Disconnected", + "format-alt": "{ifname}: {ipaddr}/{cidr}" + }, + "battery": { + "states": { + "good": 80, + "warning": 30, + "critical": 15 + }, + "format": "{icon} {capacity}%", + "format-charging": " {capacity}%", + "format-plugged": " {capacity}%", + "format-alt": "{icon} {time}", + "format-icons": [ + "", + "", + "", + "", + "" + ] + }, + "clock": { + "format": "{: %H:%M\t %m-%d}", + "tooltip-format": "{:%Y %B}\n{calendar}", + }, + "custom/notification": { + "tooltip": false, + "format": "{icon}", + "format-icons": { + "notification": " There is new notification", + "none": " No notifications", + "dnd-notification": " There is notification", + "dnd-none": " DND is on" + }, + "return-type": "json", + "exec-if": "which swaync-client", + "exec": "swaync-client -swb", + "on-click": "swaync-client -t -sw", + "on-click-right": "swaync-client -d -sw", + "escape": true + }, + "custom/player": { + "format": "{icon} {}", + "format-icons": { + "Playing": " ", + "Paused": " " + }, + "return-type": "json", + "exec": "playerctl -a metadata --format '{\"text\": \"{{uc(playerName)}}: {{artist}} - {{markup_escape(title)}}\", \"tooltip\": \"{{playerName}} : {{markup_escape(title)}}\", \"alt\": \"{{status}}\", \"class\": \"{{status}}\"}' -F", + "max-length": 35, + "on-click": "playerctl play-pause && sleep 0.2 && notify-send `playerctl status` -t 1000" + } +} diff --git a/.config/waybar/serenade.css b/.config/waybar/serenade.css new file mode 100644 index 0000000..240e27b --- /dev/null +++ b/.config/waybar/serenade.css @@ -0,0 +1,20 @@ +@define-color background #2a2f33; +@define-color selection_background #474f54; +@define-color foreground #bfddb2; +@define-color blue #82abbc; +@define-color cyan #87c095; +@define-color green #acb765; +@define-color magenta #d39bb6; +@define-color red #d76e6e; +@define-color white #d8caac; +@define-color yellow #e5a46b; + +@define-color background_b #767b82; +@define-color blue_b #7fbbb3; +@define-color cyan_b #83c092; +@define-color green_b #a7c080; +@define-color magenta_b #d699b6; +@define-color orange_b #e5a46b; +@define-color red_b #e68183; +@define-color white_b #d8caac; +@define-color yellow_b #dbbc7f; diff --git a/.config/waybar/style.css b/.config/waybar/style.css new file mode 100644 index 0000000..bd9fb9a --- /dev/null +++ b/.config/waybar/style.css @@ -0,0 +1,99 @@ +/* + * vim: ft=less + */ + +* { + border: none; + border-radius: 1; + font-size: 13px; + min-height: 0; +} + +@import "serenade.css"; + +window#waybar { + background: @background; + border-bottom: 1px solid @selection_background; +} + +#workspaces { + margin: 5px 10px; +} + +#workspaces button { + padding: 0 2px; + background: transparent; + color: @background_b; +} + +#workspaces button.focused { + color: @foreground; + font-weight: bold; +} + +#workspaces button.urgent { + color: @magenta; +} + +#custom-player, +#custom-notification, +#memory, +#cpu, +#window { + color: @background_b; +} + +#clock { + color: @magenta; +} + +#battery { + color: @blue; +} + +#battery.charging { + color: @green; +} + +@keyframes blink { + to { + color: @red; + background-color: transparent; + } +} + +#battery.warning:not(.charging) { + color: @background; + background-color: red; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#network.disconnected, +#network.disabled { + color: @red; +} + +#network.wifi { + color: @green; +} + +#clock, +#cpu, +#memory, +#battery, +#network, +#custom-notification, +#tray, +#custom-player { + padding: 0px 5px; + margin: 0px 5px; +} + +#clock { + margin-left: 10px; + margin-right: 10px; +} diff --git a/.config/wofi/config b/.config/wofi/config new file mode 100644 index 0000000..0afedb0 --- /dev/null +++ b/.config/wofi/config @@ -0,0 +1,15 @@ +# style +style=/home/juan/.config/wofi/style.css +xoffset=660 +yoffset=275 +width=600 +height=500 + +# opts +show=drun +always_parse_args=true +show_all=true +print_command=true +layer=overlay +insensitive=true +prompt= diff --git a/.config/wofi/style.css b/.config/wofi/style.css new file mode 100644 index 0000000..09ea091 --- /dev/null +++ b/.config/wofi/style.css @@ -0,0 +1,57 @@ +window { + margin: 0px; + border: 1px solid #7f868c; + border-radius: 3px; + background-color: #2a2f33; + font-family: monospace; + font-size: 14px; +} + +#input { + margin: 5px; + border: 1px solid #bfddb2; + color: #c1bf89; + background-color: #2e3338; +} + +#input image { + color: #bfddb2; +} + +#inner-box { + margin: 5px; + border: none; + background-color: #2a2f33; +} + +#outer-box { + margin: 5px; + border: none; + background-color: #2a2f33; +} + +#scroll { + margin: 0px; + border: none; +} + +#text { + margin: 5px; + border: none; + color: #bfddb2; +} + +#entry:selected { + background-color: #474f54; + color: #c1bf89; + border-radius: 3px; + font-weight: normal; +} + +#text:selected { + background-color: #474f54; + color: #c1bf89; + border-radius: 3px; + font-weight: bold; +} + diff --git a/.config/zathura/zathurarc b/.config/zathura/zathurarc new file mode 100644 index 0000000..e03aa58 --- /dev/null +++ b/.config/zathura/zathurarc @@ -0,0 +1,33 @@ +set window-title-basename "true" +set selection-clipboard "clipboard" + +set default-bg "#2a2f33" +set default-fg "#bfddb2" + +set statusbar-fg "#767b82" +set statusbar-bg "#2e3338" + +set inputbar-bg "#2e3338" +set inputbar-fg "#acb765" + +set notification-bg "#2a2f33" +set notification-fg "#82abbc" + +set notification-error-bg "#614b51" +set notification-error-fg "#d76e6e" + +set notification-warning-bg "#5d5c50" +set notification-warning-fg "#e5a46b" + +set highlight-color "#474f54" +set highlight-active-color "#d38bb6" + +set completion-bg "#474f54" +set completion-fg "#acb765" + +set completion-highlight-fg "#d39bb6" +set completion-highlight-bg "#31363b" + +set recolor-lightcolor "#2a2f33" +set recolor-darkcolor "#bfddb2" + diff --git a/.zshrc b/.zshrc new file mode 100644 index 0000000..8fee4a3 --- /dev/null +++ b/.zshrc @@ -0,0 +1,121 @@ +cat ~/.config/splash 2> /dev/null || true +echo +echo '\033[0;35m /w '$(awk -F "=" '/^NAME/ {print $2}' 2> /dev/null < /etc/os-release || uname -o) +echo '\033[0;34m @ '$HOST + +#Install zinit if no zinit is present +ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git" +if [[ ! -f $ZINIT_HOME/zinit.zsh ]]; then + print -P "%F{33}▓▒░ %F{220}Installing %F{33}DHARMA%F{220} Initiative Plugin Manager (%F{33}zdharma/zinit%F{220})…%f" + mkdir -p "$(dirname $ZINIT_HOME)" + git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME" + print -P "%F{33}▓▒░ %F{34}Installation successful.%f%b" || \ + print -P "%F{160}▓▒░ The clone has failed.%f%b" +fi +source "$ZINIT_HOME/zinit.zsh" + +zinit ice lucid wait +zinit light zdharma-continuum/fast-syntax-highlighting +zinit ice lucid wait +zinit light agkozak/zsh-z +zinit ice lucid wait +zinit light juancldcmt/colorize +zinit ice lucid wait +zinit light juancldcmt/shortify.zsh +zinit ice lucid wait +zinit light juancldcmt/direnv.zsh + +zinit ice compile'(pure|async).zsh' pick'async.zsh' src'pure.zsh' +zinit light sindresorhus/pure +zinit light zsh-users/zsh-autosuggestions +zinit light hlissner/zsh-autopair +zinit light zsh-users/zsh-history-substring-search + +autoload -Uz _zinit +(( ${+_comps} )) && _comps[zinit]=_zinit + +# Load LS_COLORS if not present +test -n "$LS_COLORS" || eval $(dircolors) || echo 'Warning: Unable to set LS_COLORS' + +# The following lines were added by compinstall + +zstyle ':completion:*' auto-description '%F{green}Specify%f: %F{cyan}%d%f' +zstyle ':completion:*' completer _oldlist _expand _complete _ignored _match _correct _approximate _prefix +zstyle ':completion:*' completions 1 +zstyle ':completion:*' expand prefix suffix +zstyle ':completion:*' file-sort access +zstyle ':completion:*' format '%F{green}Completing%f %F{yellow}%d%f' +zstyle ':completion:*' glob 1 +zstyle ':completion:*' group-name '' +zstyle ':completion:*' ignore-parents parent pwd .. +zstyle ':completion:*' insert-unambiguous true +zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} +zstyle ':completion:*' list-prompt %S%F{green}At %p%f: Hit TAB for more, or the character to insert%s +zstyle ':completion:*' matcher-list '' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|[._-]=** r:|=**' +zstyle ':completion:*' max-errors 8 numeric +zstyle ':completion:*' menu select=1 +zstyle ':completion:*' original false +zstyle ':completion:*' preserve-prefix '//[^/]##/' +zstyle ':completion:*' prompt '%F{green}Completing%f, with %F{red}%e%f errors' +zstyle ':completion:*' select-prompt %S%F{green}Scrolling%f active: current selection at %F{blue}%p%f%s +zstyle ':completion:*' substitute 1 +zstyle ':completion:*' use-compctl true +zstyle :compinstall filename ~/.zshrc + +autoload -Uz compinit +compinit +# End of lines added by compinstall +# Lines configured by zsh-newuser-install +HISTFILE=~/.cache/zhistory +HISTSIZE=8192 +SAVEHIST=8192 +setopt autocd extendedglob nomatch notify auto_pushd +unsetopt beep +bindkey -v +# End of lines configured by zsh-newuser-install + +export KEYTIMEOUT=1 + +#edit in vim +autoload edit-command-line +zle -N edit-command-line +bindkey '' edit-command-line + +zmodload zsh/complist +bindkey -M menuselect 'h' vi-backward-char +bindkey -M menuselect 'k' vi-up-line-or-history +bindkey -M menuselect 'l' vi-forward-char +bindkey -M menuselect 'j' vi-down-line-or-history + +bindkey '^[[A' history-substring-search-up +bindkey '^[[B' history-substring-search-down +bindkey '' history-substring-search-up +bindkey '' history-substring-search-down + +bindkey ' ' magic-space + +bindkey '' autosuggest-execute + +#config location +export GOPATH=$HOME/.cache/go +export LESSHISTFILE=/dev/null +export LYNX_CFG=$HOME/.config/lynx/lynxrc +export XDG_CACHE_HOME=$HOME/.cache +export XDG_CONFIG_HOME=$HOME/.config + +#settings for software +export FZF_DEFAULT_OPTS="--reverse --cycle --height=40% --border sharp --prompt=🔎" +export GPG_TTY=$(tty) # fixes gpg + +#colored output +export MANWIDTH=${MANWIDTH:-78} +export MANLESS="Manual\ \$MAN_PN\ ?ltline\ %lt?L/%L.:byte\ %bB?s/%s..?\:?pB\ %pB\\%.." +export LESS="-RSM~" + +#local path +export PATH="${PATH}:${HOME}/.local/bin:${HOME}/.scripts:${HOME}/cargo/bin:${HOME}/.cache/go/bin" +export MANPATH="${MANPATH}:${HOME}/.local/share/man" + +#ccache support +export USE_CCACHE=1 +export PATH="/usr/lib/ccache/bin${PATH:+:}$PATH" diff --git a/Pictures/Wallpapers/serenade/rainy_nights_by_yuumei_derp5i1.jpg b/Pictures/Wallpapers/serenade/rainy_nights_by_yuumei_derp5i1.jpg new file mode 100644 index 0000000..db070fa Binary files /dev/null and b/Pictures/Wallpapers/serenade/rainy_nights_by_yuumei_derp5i1.jpg differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..9b0ec82 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# Dotfiles + +This is my dot files on a Gentoo Linux laptop, with SwayWM and pipewire. + +# Software that this dotfile includes + +| Name | Description | +|------|-------------| +|swayWM|Tiling WM| +|waybar|Custom bar for sway| +|swayNC|Notification center| +|wofi|App launcher| +|kitty|Terminal emulator| +|zsh|Interactive Shell| +|mpv|Video player| +|tmux|Split terminal| +|zathura|PDF viewer| + +# Depencencies + +|Name|Description| +|----|-----------| +|wlsunset|Shift blue color based on time| +|light|CLI for managing backlight| +|pipewire|Sound deamon| +|wireplumber|media session management (remember to replace it in sway's config if using non-gentoo)| +|playerctld|Control players| +|grim|Take screenshots| + +# Screenshots + +![2206252110](https://user-images.githubusercontent.com/72336775/175775155-45624b81-2d73-4ad8-832d-6248aa8e8cdc.png)