mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-02-28 00:22:41 -08:00
update
This commit is contained in:
@@ -4,9 +4,22 @@
|
||||
"pr": ""
|
||||
},
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(npm run lint)",
|
||||
"Bash(npm run test *)",
|
||||
"Read(~/.zshrc)",
|
||||
"Bash(git * main)",
|
||||
"Bash(ls *)",
|
||||
"Bash(pnpm build *)"
|
||||
],
|
||||
"deny": [
|
||||
"Read(.env)",
|
||||
"Read(~/.aws/**)"
|
||||
"Bash(curl *)",
|
||||
"Read(./.env)",
|
||||
"Read(./.env.*)",
|
||||
"Read(./secrets/**)",
|
||||
"Read(~/.aws/**)",
|
||||
"Bash(git push *)",
|
||||
"Bash(yadm push *)"
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
@@ -25,19 +38,20 @@
|
||||
"enabledPlugins": {
|
||||
"pyright-lsp@claude-plugins-official": true,
|
||||
"typescript-lsp@claude-plugins-official": true,
|
||||
"clangd-lsp@claude-plugins-official": true
|
||||
"clangd-lsp@claude-plugins-official": true,
|
||||
"claude-mem@thedotmack": true,
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"code-review@claude-plugins-official": true,
|
||||
"code-simplifier@claude-plugins-official": true,
|
||||
"playwright@claude-plugins-official": true
|
||||
},
|
||||
"sandbox": {
|
||||
"enabled": false,
|
||||
"autoAllowBashIfSandboxed": true,
|
||||
"network": {
|
||||
"allowUnixSockets": [
|
||||
"/var/run/docker.sock"
|
||||
],
|
||||
"allowUnixSockets": ["/var/run/docker.sock"],
|
||||
"allowLocalBinding": true
|
||||
},
|
||||
"excludedCommands": [
|
||||
"docker"
|
||||
]
|
||||
"excludedCommands": ["docker"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
|
||||
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
|
||||
color_theme = "TTY"
|
||||
color_theme = "/home/sudacode/.config/btop/themes/catppuccin_macchiato.theme"
|
||||
|
||||
#* If the theme set background should be shown, set to False if you want terminal background transparency.
|
||||
theme_background = true
|
||||
|
||||
@@ -271,3 +271,10 @@ debug {
|
||||
disable_logs = true
|
||||
enable_stdout_logs = false
|
||||
}
|
||||
|
||||
|
||||
layerrule {
|
||||
name = fix-rofi
|
||||
match:namespace = rofi
|
||||
no_anim = true
|
||||
}
|
||||
|
||||
@@ -152,4 +152,3 @@ bind = $mainMod, a, exec, ~/.config/rofi/scripts/rofi-anki-script.sh
|
||||
bindl = , mouse:275, exec, xdotool key alt+w # top mouse to texthooker
|
||||
bindl = , mouse:276, exec, xdotool key alt+grave # bottom mouse to overlay
|
||||
bind = ALT, g, exec, /opt/mpv-yomitan/mpv-yomitan.AppImage --toggle
|
||||
# bind = ALT SHIFT, Y, exec, "$HOME/.config/rofi/scripts/rofi-mpv-yomitan.sh"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../submodules/animecards/animecards
|
||||
@@ -1,388 +0,0 @@
|
||||
// Go to https://jimaku.cc/login and create a new account.
|
||||
// Then go to https://jimaku.cc/account and click the `Generate` button to create a new API key
|
||||
// Click the `Copy` button and paste it below
|
||||
var API_KEY = "";
|
||||
|
||||
// Configuration options
|
||||
var CONFIG = {
|
||||
// Filter the response to only have the specified episode
|
||||
prompt_episode: true,
|
||||
|
||||
// Subtitle suffix (e.g., ".JA" for Japanese subtitles)
|
||||
subtitle_suffix: ".JA",
|
||||
|
||||
// Preferred subtitle format (order matters, first is most preferred)
|
||||
preferred_formats: ["ass", "srt", "vtt"],
|
||||
|
||||
// Automatically load the subtitle after download
|
||||
auto_load: true,
|
||||
|
||||
// Default subtitle delay in seconds (can be positive or negative)
|
||||
default_delay: 0,
|
||||
|
||||
// Default subtitle font size
|
||||
default_font_size: 16,
|
||||
|
||||
// Automatically rename the subtitle file after download
|
||||
auto_rename: true,
|
||||
|
||||
// Automatically run autosubsync-mpv after downloading the subtitle
|
||||
run_auto_subsync: true
|
||||
};
|
||||
|
||||
// Keybindings
|
||||
// var MANUAL_SEARCH_KEY = "g";
|
||||
var FILENAME_AUTO_SEARCH_KEY = "ctrl+J";
|
||||
var PARENT_FOLDER_AUTO_SEARCH_KEY = "n";
|
||||
|
||||
function api(url, extraArgs) {
|
||||
var baseArgs = [
|
||||
"curl",
|
||||
"-s",
|
||||
"--url",
|
||||
url,
|
||||
"--header",
|
||||
"Authorization: " + API_KEY
|
||||
];
|
||||
|
||||
var args = Array.prototype.concat.apply(baseArgs, extraArgs);
|
||||
|
||||
var res = mp.command_native({
|
||||
name: "subprocess",
|
||||
playback_only: false,
|
||||
capture_stdout: true,
|
||||
capture_stderr: true,
|
||||
args: args
|
||||
});
|
||||
|
||||
if (res.stdout) return JSON.parse(res.stdout);
|
||||
}
|
||||
|
||||
function downloadSub(sub) {
|
||||
return api(sub.url, ["--output", sub.name]);
|
||||
}
|
||||
|
||||
function showMessage(message, persist) {
|
||||
var ass_start = mp.get_property_osd("osd-ass-cc/0");
|
||||
var ass_stop = mp.get_property_osd("osd-ass-cc/1");
|
||||
|
||||
mp.osd_message(
|
||||
ass_start + "{\\fs16}" + message + ass_stop,
|
||||
persist ? 999 : 2
|
||||
);
|
||||
}
|
||||
|
||||
// The timeout is neccessary due to a weird bug in mpv
|
||||
function inputGet(args) {
|
||||
mp.input.terminate();
|
||||
setTimeout(function () {
|
||||
mp.input.get(args);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
// The timeout is neccessary due to a weird bug in mpv
|
||||
function inputSelect(args) {
|
||||
mp.input.terminate();
|
||||
setTimeout(function () {
|
||||
mp.input.select(args);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
// Taken from mpv-subversive
|
||||
// https://github.com/nairyosangha/mpv-subversive/blob/master/backend/backend.lua#L146
|
||||
function sanitize(text) {
|
||||
var subPatterns = [
|
||||
/\.[a-zA-Z]+$/, // extension
|
||||
/\./g,
|
||||
/-/g,
|
||||
/_/g,
|
||||
/\[[^\]]+\]/g, // [] bracket
|
||||
/\([^\)]+\)/g, // () bracket
|
||||
/720[pP]/g,
|
||||
/480[pP]/g,
|
||||
/1080[pP]/g,
|
||||
/[xX]26[45]/g,
|
||||
/[bB]lu[-]?[rR]ay/g,
|
||||
/^[\s]*/,
|
||||
/[\s]*$/,
|
||||
/1920x1080/g,
|
||||
/1920X1080/g,
|
||||
/Hi10P/g,
|
||||
/FLAC/g,
|
||||
/AAC/g
|
||||
];
|
||||
|
||||
var result = text;
|
||||
|
||||
subPatterns.forEach(function (subPattern) {
|
||||
var newResult = result.replace(subPattern, " ");
|
||||
if (newResult.length > 0) {
|
||||
result = newResult;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Adapted from mpv-subversive
|
||||
// https://github.com/nairyosangha/mpv-subversive/blob/master/backend/backend.lua#L164
|
||||
function extractTitle(text) {
|
||||
var matchers = [
|
||||
{ regex: /^([\w\s\d]+)[Ss]\d+[Ee]?\d+/, group: 1 },
|
||||
{ regex: /^([\w\s\d]+)-[\s]*\d+[\s]*[^\w]*$/, group: 1 },
|
||||
{ regex: /^([\w\s\d]+)[Ee]?[Pp]?[\s]+\d+$/, group: 1 },
|
||||
{ regex: /^([\w\s\d]+)[\s]\d+.*$/, group: 1 },
|
||||
{ regex: /^\d+[\s]*(.+)$/, group: 1 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < matchers.length; i++) {
|
||||
var matcher = matchers[i];
|
||||
var match = text.match(matcher.regex);
|
||||
if (match) {
|
||||
return match[matcher.group].trim();
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
function getNames(results) {
|
||||
return results.map(function (item) {
|
||||
return item.name;
|
||||
});
|
||||
}
|
||||
|
||||
function runAutoSubSyncMPV() {
|
||||
try {
|
||||
mp.command_native(["script-binding", "autosubsync-menu"]);
|
||||
} catch (e) {
|
||||
showMessage("autosubsync-mpv not installed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function selectSub(selectedSub) {
|
||||
showMessage("Downloading: " + selectedSub.name);
|
||||
|
||||
try {
|
||||
downloadSub(selectedSub);
|
||||
|
||||
// Get current video filename without extension
|
||||
var videoPath = mp.get_property("path");
|
||||
if (!videoPath) {
|
||||
throw new Error("No video file is currently playing");
|
||||
}
|
||||
var videoName = videoPath.substring(0, videoPath.lastIndexOf("."));
|
||||
|
||||
// Get subtitle extension
|
||||
var subExt = selectedSub.name.substring(selectedSub.name.lastIndexOf("."));
|
||||
|
||||
var newSubName = selectedSub.name;
|
||||
if (CONFIG.auto_rename) {
|
||||
// Create new subtitle filename
|
||||
newSubName = videoName + CONFIG.subtitle_suffix + subExt;
|
||||
|
||||
// Rename the downloaded subtitle file
|
||||
var renameResult = mp.command_native({
|
||||
name: "subprocess",
|
||||
playback_only: false,
|
||||
args: ["mv", selectedSub.name, newSubName]
|
||||
});
|
||||
|
||||
if (renameResult.error) {
|
||||
throw new Error(
|
||||
"Failed to rename subtitle file: " + renameResult.error
|
||||
);
|
||||
}
|
||||
|
||||
showMessage(newSubName + " downloaded and renamed");
|
||||
} else {
|
||||
showMessage(newSubName + " downloaded");
|
||||
}
|
||||
|
||||
if (CONFIG.auto_load) {
|
||||
mp.commandv("sub_add", newSubName);
|
||||
showMessage(newSubName + " added");
|
||||
|
||||
// Apply subtitle settings if configured
|
||||
if (CONFIG.default_delay !== 0) {
|
||||
mp.commandv("sub_delay", CONFIG.default_delay);
|
||||
}
|
||||
if (CONFIG.default_font_size !== 16) {
|
||||
mp.commandv("sub_font_size", CONFIG.default_font_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (CONFIG.run_auto_subsync) {
|
||||
runAutoSubSyncMPV();
|
||||
}
|
||||
|
||||
mp.set_property("pause", "no");
|
||||
} catch (error) {
|
||||
showMessage("Error: " + error.message, true);
|
||||
mp.set_property("pause", "no");
|
||||
}
|
||||
}
|
||||
|
||||
function sortByPreferredFormat(files) {
|
||||
return files.sort(function (a, b) {
|
||||
var extA = a.name.substring(a.name.lastIndexOf(".") + 1).toLowerCase();
|
||||
var extB = b.name.substring(b.name.lastIndexOf(".") + 1).toLowerCase();
|
||||
|
||||
var indexA = CONFIG.preferred_formats.indexOf(extA);
|
||||
var indexB = CONFIG.preferred_formats.indexOf(extB);
|
||||
|
||||
if (indexA === -1) return 1;
|
||||
if (indexB === -1) return -1;
|
||||
return indexA - indexB;
|
||||
});
|
||||
}
|
||||
|
||||
function selectEpisode(anime, episode) {
|
||||
mp.input.terminate();
|
||||
var episodeResults;
|
||||
|
||||
if (episode) {
|
||||
showMessage("Fetching subs for: " + anime.name + " episode " + episode);
|
||||
episodeResults = api(
|
||||
"https://jimaku.cc/api/entries/" + anime.id + "/files?episode=" + episode
|
||||
);
|
||||
} else {
|
||||
showMessage("Fetching all subs for: " + anime.name);
|
||||
episodeResults = api(
|
||||
"https://jimaku.cc/api/entries/" + anime.id + "/files"
|
||||
);
|
||||
}
|
||||
|
||||
if (episodeResults.error) {
|
||||
showMessage("Error: " + animeResults.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (episodeResults.length === 0) {
|
||||
showMessage("No results found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort results by preferred format
|
||||
episodeResults = sortByPreferredFormat(episodeResults);
|
||||
|
||||
if (episodeResults.length === 1) {
|
||||
var selectedEpisode = episodeResults[0];
|
||||
selectSub(selectedEpisode);
|
||||
return;
|
||||
}
|
||||
|
||||
var items = getNames(episodeResults);
|
||||
|
||||
inputSelect({
|
||||
prompt: "Select episode: ",
|
||||
items: items,
|
||||
submit: function (id) {
|
||||
var selectedEpisode = episodeResults[id - 1];
|
||||
selectSub(selectedEpisode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onAnimeSelected(anime) {
|
||||
if (CONFIG.prompt_episode) {
|
||||
inputGet({
|
||||
prompt: "Episode (leave blank for all): ",
|
||||
submit: function (episode) {
|
||||
selectEpisode(anime, episode);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
selectEpisode(anime);
|
||||
}
|
||||
}
|
||||
|
||||
function search(searchTerm, isAuto) {
|
||||
mp.input.terminate();
|
||||
showMessage('Searching for: "' + searchTerm + '"');
|
||||
|
||||
var animeResults = api(
|
||||
encodeURI(
|
||||
"https://jimaku.cc/api/entries/search?anime=true&query=" + searchTerm
|
||||
)
|
||||
);
|
||||
|
||||
if (animeResults.error) {
|
||||
showMessage("Error: " + animeResults.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (animeResults.length === 0) {
|
||||
showMessage("No results found");
|
||||
if (isAuto) {
|
||||
manualSearch(searchTerm);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (animeResults.length === 1) {
|
||||
var selectedAnime = animeResults[0];
|
||||
onAnimeSelected(selectedAnime);
|
||||
return;
|
||||
}
|
||||
|
||||
var items = getNames(animeResults);
|
||||
|
||||
inputSelect({
|
||||
prompt: "Select anime: ",
|
||||
items: items,
|
||||
submit: function (id) {
|
||||
var selectedAnime = animeResults[id - 1];
|
||||
showMessage(selectedAnime.name, true);
|
||||
onAnimeSelected(selectedAnime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function manualSearch(defaultText) {
|
||||
inputGet({
|
||||
prompt: "Search term: ",
|
||||
submit: search,
|
||||
default_text: defaultText
|
||||
});
|
||||
|
||||
mp.set_property("pause", "yes");
|
||||
showMessage("Manual Jimaku Search", true);
|
||||
}
|
||||
|
||||
function autoSearch() {
|
||||
var filename = mp.get_property("filename");
|
||||
var sanitizedFilename = sanitize(filename);
|
||||
var currentAnime = extractTitle(sanitizedFilename);
|
||||
|
||||
mp.set_property("pause", "yes");
|
||||
|
||||
search(currentAnime, true);
|
||||
}
|
||||
|
||||
function autoSearchParentFolder() {
|
||||
var path = mp.get_property("stream-open-filename");
|
||||
var pathSplit = path.split(path.indexOf("/") >= 0 ? "/" : "\\");
|
||||
var filename =
|
||||
pathSplit.length === 1 ? pathSplit[0] : pathSplit[pathSplit.length - 2];
|
||||
|
||||
var sanitizedFilename = sanitize(filename);
|
||||
var currentAnime = extractTitle(sanitizedFilename);
|
||||
|
||||
mp.set_property("pause", "yes");
|
||||
|
||||
search(currentAnime, true);
|
||||
}
|
||||
|
||||
// mp.add_key_binding(MANUAL_SEARCH_KEY, "jimaku-manual-search", manualSearch);
|
||||
mp.add_key_binding(
|
||||
FILENAME_AUTO_SEARCH_KEY,
|
||||
"jimaku-filename-auto-search",
|
||||
autoSearch
|
||||
);
|
||||
mp.add_key_binding(
|
||||
PARENT_FOLDER_AUTO_SEARCH_KEY,
|
||||
"jimaku-parent-folder-auto-search",
|
||||
autoSearchParentFolder
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
../submodules/mpvacious
|
||||
@@ -37,7 +37,8 @@ window {
|
||||
location: center;
|
||||
anchor: center;
|
||||
fullscreen: false;
|
||||
width: 37%;
|
||||
width: 46.65%;
|
||||
height: 44%;
|
||||
x-offset: 0px;
|
||||
y-offset: 0px;
|
||||
|
||||
@@ -58,9 +59,9 @@ mainbox {
|
||||
}
|
||||
|
||||
imagebox {
|
||||
padding: 20px;
|
||||
padding: 24px;
|
||||
background-color: transparent;
|
||||
background-image: url("~/.config/rofi/images/oshinoko.png", height);
|
||||
background-image: url("~/.config/rofi/images/oshinoko.png", both);
|
||||
orientation: vertical;
|
||||
children: [ "inputbar", "dummy", "mode-switcher" ];
|
||||
}
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
{
|
||||
"subtitlePosition": {
|
||||
"yPercent": 17.38459152016546
|
||||
},
|
||||
"keybindings": [
|
||||
{
|
||||
"key": "Space",
|
||||
"command": [
|
||||
"cycle",
|
||||
"pause"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "ArrowRight",
|
||||
"command": [
|
||||
"seek",
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "ArrowLeft",
|
||||
"command": [
|
||||
"seek",
|
||||
-5
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "ArrowRight",
|
||||
"command": [
|
||||
"seek",
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "ArrowUp",
|
||||
"command": [
|
||||
"seek",
|
||||
60
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "ArrowDown",
|
||||
"command": [
|
||||
"seek",
|
||||
-60
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "KeyQ",
|
||||
"command": [
|
||||
"quit"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "Ctrl+KeyW",
|
||||
"command": [
|
||||
"quit"
|
||||
]
|
||||
}
|
||||
],
|
||||
"texthooker": {
|
||||
"openBrowser": false
|
||||
},
|
||||
"websocket": {
|
||||
"enabled": "auto",
|
||||
"port": 6677
|
||||
},
|
||||
"ankiConnect": {
|
||||
"enabled": true,
|
||||
"url": "http://127.0.0.1:8765",
|
||||
"deck": "Minecraft",
|
||||
"pollingRate": 200,
|
||||
"audioField": "ExpressionAudio",
|
||||
"imageField": "Picture",
|
||||
"sentenceField": "Sentence",
|
||||
"generateAudio": true,
|
||||
"generateImage": true,
|
||||
"imageType": "avif",
|
||||
"imageFormat": "webp",
|
||||
"miscInfoPattern": "[mpv-yomitan] %f (%t)",
|
||||
"overwriteAudio": false,
|
||||
"overwriteImage": true,
|
||||
"highlightWord": true,
|
||||
"showNotificationOnUpdate": true,
|
||||
"notificationType": "system",
|
||||
"audioPadding": 0.5,
|
||||
"fallbackDuration": 3,
|
||||
"animatedFps": 24,
|
||||
"animatedMaxWidth": 640,
|
||||
"animatedMaxHeight": null,
|
||||
"animatedCrf": 35,
|
||||
"autoUpdateNewCards": false,
|
||||
"sentenceCardModel": "Lapis Morph",
|
||||
"sentenceCardSentenceField": "Sentence",
|
||||
"sentenceCardAudioField": "SentenceAudio",
|
||||
"isLapis": true,
|
||||
"mediaInsertMode": "append",
|
||||
"auto_start_overlay": false,
|
||||
"secondarySub": {
|
||||
"autoLoadSecondarySub": true,
|
||||
"secondarySubLanguages": [
|
||||
"en",
|
||||
"eng"
|
||||
]
|
||||
}
|
||||
},
|
||||
"subtitleStyle": {
|
||||
"ontFamily": "Noto Sans CJK JP Regular, Noto Sans CJK JP, Arial Unicode MS, Arial, sans-serif",
|
||||
"fontSize": 35,
|
||||
"fontColor": "#cad3f5",
|
||||
"fontWeight": "normal",
|
||||
"fontStyle": "normal",
|
||||
"backgroundColor": "rgb(30, 32, 48, 0.88)",
|
||||
"secondary": {
|
||||
"fontSize": 24,
|
||||
"fontColor": "#cad3f5",
|
||||
"backgroundColor": "transparent"
|
||||
}
|
||||
},
|
||||
"shortcuts": {
|
||||
"copySubtitle": "CommandOrControl+C",
|
||||
"copySubtitleMultiple": "CommandOrControl+Shift+C",
|
||||
"updateLastCardFromClipboard": "CommandOrControl+V",
|
||||
"mineSentence": "CommandOrControl+S",
|
||||
"mineSentenceMultiple": "CommandOrControl+Shift+S",
|
||||
"toggleSecondarySub": "CommandOrControl+Shift+V",
|
||||
"multiCopyTimeoutMs": 3000
|
||||
}
|
||||
}
|
||||
@@ -73,3 +73,5 @@ zstyle ':url-quote-magic:*' url-quotes ''
|
||||
# bind it to both typing and pasting
|
||||
zle -N self-insert url-quote-magic
|
||||
zle -N bracketed-paste bracketed-paste-magic
|
||||
|
||||
alias claude-mem='bun "/home/sudacode/.claude/plugins/marketplaces/thedotmack/plugin/scripts/worker-service.cjs"'
|
||||
|
||||
Reference in New Issue
Block a user