diff --git a/.config/ags/modules/.configuration/default_options.jsonc b/.config/ags/modules/.configuration/default_options.jsonc new file mode 100644 index 000000000..d76705a7d --- /dev/null +++ b/.config/ags/modules/.configuration/default_options.jsonc @@ -0,0 +1,241 @@ +// This file is parsed with a custom JSONC parser. +// Don't expect every JSONC feature in... say, vscode, to work. +{ + // General stuff + "ai": { + "defaultGPTProvider": "openai", + "defaultTemperature": 0.9, + "enhancements": true, + "useHistory": false, + "safety": true, + "writingCursor": " ...", // Warning: Using weird characters can mess up Markdown rendering + "proxyUrl": null // Can be "socks5://127.0.0.1:9050" or "http://127.0.0.1:8080" for example. Leave it blank if you don't need it. + }, + "animations": { + "choreographyDelay": 35, + "durationSmall": 110, + "durationLarge": 180 + }, + "appearance": { + "autoDarkMode": { // Turns on dark mode in certain hours. Time in 24h format + "enabled": false, + "from": "18:10", + "to": "6:10" + }, + "borderless": false, // Uhm experimental... + "keyboardUseFlag": false, // Use flag emoji instead of abbreviation letters + "layerSmoke": false, + "layerSmokeStrength": 0.2, + "barRoundCorners": 1, // 0: No, 1: Yes + "fakeScreenRounding": 2 // 0: None | 1: Always | 2: When not fullscreen + }, + "apps": { + "bluetooth": "blueberry", + "imageViewer": "loupe", + "network": "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center wifi", + "settings": "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center", + "taskManager": "gnome-usage", + "terminal": "foot" // This is only for shell actions + }, + "battery": { + "low": 20, + "critical": 10, + "warnLevels": [20, 15, 5], + "warnTitles": ["Low battery", "Very low battery", "Critical Battery"], + "warnMessages": ["Plug in the charger", "You there?", "PLUG THE CHARGER ALREADY"], + "suspendThreshold": 3 + }, + "brightness": { + // Object of controller names for each monitor, either "brightnessctl" or "ddcutil" or "auto" + // "default" one will be used if unspecified + // Examples + // "eDP-1": "brightnessctl", + // "DP-1": "ddcutil", + "controllers": { + "default": "auto" + } + }, + "cheatsheet": { + "keybinds": { + "configPath": "" // Path to hyprland keybind config file. Leave empty for default (~/.config/hypr/hyprland/keybinds.conf) + } + }, + "gaming": { + "crosshair": { + "size": 20, + "color": "rgba(113,227,32,0.9)" + } + }, + "i18n": { + "langCode": "", //Customize the locale, such as zh_CN,Optional value references "~/.config/ags/i18n/locales/" + "extraLogs": false + }, + "monitors": { + "scaleMethod": "division" // Either "division" [default] or "gdk" + }, + "music": { + "preferredPlayer": "plasma-browser-integration" + }, + "onScreenKeyboard": { + "layout": "qwerty_full" // See modules/onscreenkeyboard/onscreenkeyboard.js for available layouts + }, + "overview": { + "scale": 0.18, // Relative to screen size + "numOfRows": 2, + "numOfCols": 5, + "wsNumScale": 0.09, + "wsNumMarginScale": 0.07 + }, + "sidebar": { + "ai": { + "extraGptModels": { + "oxygen3": { + "name": "Oxygen (GPT-3.5)", + "logo_name": "ai-oxygen-symbolic", + "description": "An API from Tornado Softwares\nPricing: Free: 100/day\nRequires you to join their Discord for a key", + "base_url": "https://app.oxyapi.uk/v1/chat/completions", + "key_get_url": "https://discord.com/invite/kM6MaCqGKA", + "key_file": "oxygen_key.txt", + "model": "gpt-3.5-turbo" + } + } + }, + "image": { + "columns": 2, + "batchCount": 20, + "allowNsfw": false, + "saveInFolderByTags": false + }, + "pages": { + "order": ["apis", "tools"], + "apis": { + "order": ["gemini", "gpt", "waifu", "booru"] + } + }, + "quickToggles": { + "order": ["wifi", "bluetooth", "nightlight", "gamemode", "idleinhibitor", "cloudflarewarp"] + }, + "calendar": { + "expandByDefault": true + } + }, + "search": { + "enableFeatures": { + "actions": true, + "commands": true, + "mathResults": true, + "directorySearch": true, + "aiSearch": true, + "webSearch": true + }, + "engineBaseUrl": "https://www.google.com/search?q=", + "excludedSites": ["quora.com"] + }, + "time": { + // See https://docs.gtk.org/glib/method.DateTime.format.html + // Here's the 12h format: "%I:%M%P" + // For seconds, add "%S" and set interval to 1000 + "format": "%H:%M", + "interval": 5000, + "dateFormatLong": "%A, %d/%m", // On bar + "dateInterval": 5000, + "dateFormat": "%d/%m", // On notif time + "calendarDateFormat": "%d %B %Y" + }, + "weather": { + "city": "", + "preferredUnit": "C" // Either C or F + }, + "workspaces": { + "shown": 10 + }, + "dock": { + "enabled": false, + "hiddenThickness": 5, + "pinnedApps": ["firefox", "org.gnome.Nautilus"], + "layer": "top", + "monitorExclusivity": true, // Dock will move to other monitor along with focus if enabled + "searchPinnedAppIcons": false, // Try to search for the correct icon if the app class isn't an icon name + "trigger": ["client-added", "client-removed"], // client_added, client_move, workspace_active, client_active + // Automatically hide dock after `interval` ms since trigger + "autoHide": [ + { + "trigger": "client-added", + "interval": 500 + }, + { + "trigger": "client-removed", + "interval": 500 + } + ] + }, + // Longer stuff + "icons": { + // Find the window's icon by its class with levenshteinDistance + // The file names are processed at startup, so if there + // are too many files in the search path it'll affect performance + // Example: ["/usr/share/icons/Tela-nord/scalable/apps"] + "searchPaths": [""], + "symbolicIconTheme": { + "dark": "Adwaita", + "light": "Adwaita" + }, + "substitutions": { + "code-url-handler": "visual-studio-code", + "Code": "visual-studio-code", + "GitHub Desktop": "github-desktop", + "Minecraft* 1.20.1": "minecraft", + "gnome-tweaks": "org.gnome.tweaks", + "pavucontrol-qt": "pavucontrol", + "wps": "wps-office2019-kprometheus", + "wpsoffice": "wps-office2019-kprometheus", + "footclient": "foot", + "": "image-missing" + }, + "regexSubstitutions": [ + { + "regex": "/^steam_app_(\\d+)$/", + "replace": "steam_icon_$1" + } + ] + }, + "keybinds": { + // Format: Mod1+Mod2+key. CaSe SeNsItIvE! + // Modifiers: Shift Ctrl Alt Hyper Meta + // See https://docs.gtk.org/gdk3/index.html#constants for the other keys (they are listed as KEY_key) + "overview": { + "altMoveLeft": "Ctrl+b", + "altMoveRight": "Ctrl+f", + "deleteToEnd": "Ctrl+k" + }, + "sidebar": { + "apis": { + "nextTab": "Page_Down", + "prevTab": "Page_Up" + }, + "options": { // Right sidebar + "nextTab": "Page_Down", + "prevTab": "Page_Up" + }, + "pin": "Ctrl+p", + "cycleTab": "Ctrl+Tab", + "nextTab": "Ctrl+Page_Down", + "prevTab": "Ctrl+Page_Up" + }, + "cheatsheet": { + "keybinds": { + "nextTab": "Page_Down", + "prevTab": "Page_Up" + }, + "nextTab": "Ctrl+Page_Down", + "prevTab": "Ctrl+Page_Up", + "cycleTab": "Ctrl+Tab" + } + }, + "bar": { + // Array of bar modes for each monitor. Hit Ctrl+Alt+Slash to cycle. + // Modes: "normal", "focus" (workspace indicator only), "nothing" + // Example for four monitors: ["normal", "focus", "normal", "nothing"] + "modes": ["normal"] + } +} \ No newline at end of file diff --git a/.config/ags/modules/.configuration/user_options.js b/.config/ags/modules/.configuration/user_options.js index eb87825d1..c0e4f04c1 100644 --- a/.config/ags/modules/.configuration/user_options.js +++ b/.config/ags/modules/.configuration/user_options.js @@ -1,250 +1,7 @@ -import GLib from 'gi://GLib'; +import App from 'resource:///com/github/Aylur/ags/app.js'; import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' -import userOverrides from '../../user_options.js'; +import { parseJSONC } from '../.miscutils/jsonc.js'; -// Default options. -// Add overrides in ~/.config/ags/user_options.js -let configOptions = { - // General stuff - 'ai': { - 'defaultGPTProvider': "openai", - 'defaultTemperature': 0.9, - 'enhancements': true, - 'useHistory': false, - 'safety': true, - 'writingCursor': " ...", // Warning: Using weird characters can mess up Markdown rendering - 'proxyUrl': null, // Can be "socks5://127.0.0.1:9050" or "http://127.0.0.1:8080" for example. Leave it blank if you don't need it. - }, - 'animations': { - 'choreographyDelay': 35, - 'durationSmall': 110, - 'durationLarge': 180, - }, - 'appearance': { - 'autoDarkMode': { // Turns on dark mode in certain hours. Time in 24h format - 'enabled': false, - 'from': "18:10", - 'to': "6:10", - }, - 'borderless': false, // Uhm experimental... - 'keyboardUseFlag': false, // Use flag emoji instead of abbreviation letters - 'layerSmoke': false, - 'layerSmokeStrength': 0.2, - 'barRoundCorners': 1, // 0: No, 1: Yes - 'fakeScreenRounding': 2, // 0: None | 1: Always | 2: When not fullscreen - }, - 'apps': { - 'bluetooth': "blueberry", - 'imageViewer': "loupe", - 'network': "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center wifi", - 'settings': "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center", - 'taskManager': "gnome-usage", - 'terminal': "foot", // This is only for shell actions - }, - 'battery': { - 'low': 20, - 'critical': 10, - 'warnLevels': [20, 15, 5], - 'warnTitles': ["Low battery", "Very low battery", 'Critical Battery'], - 'warnMessages': ["Plug in the charger", "You there?", 'PLUG THE CHARGER ALREADY'], - 'suspendThreshold': 3, - }, - 'brightness': { - // Object of controller names for each monitor, either "brightnessctl" or "ddcutil" or "auto" - // 'default' one will be used if unspecified - // Examples - // 'eDP-1': "brightnessctl", - // 'DP-1': "ddcutil", - 'controllers': { - 'default': "auto", - }, - }, - 'cheatsheet': { - 'keybinds': { - 'configPath': "" // Path to hyprland keybind config file. Leave empty for default (~/.config/hypr/hyprland/keybinds.conf) - } - }, - 'gaming': { - 'crosshair': { - 'size': 20, - 'color': 'rgba(113,227,32,0.9)', - }, - }, - 'i18n': { - 'langCode': "",//Customize the locale, such as zh_CN,Optional value references "~/.config/ags/i18n/locales/" - 'extraLogs': false - }, - 'monitors': { - 'scaleMethod': "division", // Either "division" [default] or "gdk" - }, - 'music': { - 'preferredPlayer': "plasma-browser-integration", - }, - 'onScreenKeyboard': { - 'layout': "qwerty_full", // See modules/onscreenkeyboard/onscreenkeyboard.js for available layouts - }, - 'overview': { - 'scale': 0.18, // Relative to screen size - 'numOfRows': 2, - 'numOfCols': 5, - 'wsNumScale': 0.09, - 'wsNumMarginScale': 0.07, - }, - 'sidebar': { - 'ai': { - 'extraGptModels': { - 'oxygen3': { - 'name': 'Oxygen (GPT-3.5)', - 'logo_name': 'ai-oxygen-symbolic', - 'description': 'An API from Tornado Softwares\nPricing: Free: 100/day\nRequires you to join their Discord for a key', - 'base_url': 'https://app.oxyapi.uk/v1/chat/completions', - 'key_get_url': 'https://discord.com/invite/kM6MaCqGKA', - 'key_file': 'oxygen_key.txt', - 'model': 'gpt-3.5-turbo', - }, - } - }, - 'image': { - 'columns': 2, - 'batchCount': 20, - 'allowNsfw': false, - 'saveInFolderByTags': false, - }, - 'pages': { - 'order': ["apis", "tools"], - 'apis': { - 'order': ["gemini", "gpt", "waifu", "booru"], - } - }, - 'quickToggles': { - 'order': ["wifi", "bluetooth", "nightlight", "gamemode", "idleinhibitor", "cloudflarewarp"], - }, - 'calendar': { - 'expandByDefault': true, - }, - }, - 'search': { - 'enableFeatures': { - 'actions': true, - 'commands': true, - 'mathResults': true, - 'directorySearch': true, - 'aiSearch': true, - 'webSearch': true, - }, - 'engineBaseUrl': "https://www.google.com/search?q=", - 'excludedSites': ["quora.com"], - }, - 'time': { - // See https://docs.gtk.org/glib/method.DateTime.format.html - // Here's the 12h format: "%I:%M%P" - // For seconds, add "%S" and set interval to 1000 - 'format': "%H:%M", - 'interval': 5000, - 'dateFormatLong': "%A, %d/%m", // On bar - 'dateInterval': 5000, - 'dateFormat': "%d/%m", // On notif time - 'calendarDateFormat': "%d %B %Y" - }, - 'weather': { - 'city': "", - 'preferredUnit': "C", // Either C or F - }, - 'workspaces': { - 'shown': 10, - }, - 'dock': { - 'enabled': false, - 'hiddenThickness': 5, - 'pinnedApps': ['firefox', 'org.gnome.Nautilus'], - 'layer': 'top', - 'monitorExclusivity': true, // Dock will move to other monitor along with focus if enabled - 'searchPinnedAppIcons': false, // Try to search for the correct icon if the app class isn't an icon name - 'trigger': ['client-added', 'client-removed'], // client_added, client_move, workspace_active, client_active - // Automatically hide dock after `interval` ms since trigger - 'autoHide': [ - { - 'trigger': 'client-added', - 'interval': 500, - }, - { - 'trigger': 'client-removed', - 'interval': 500, - }, - ], - }, - // Longer stuff - 'icons': { - // Find the window's icon by its class with levenshteinDistance - // The file names are processed at startup, so if there - // are too many files in the search path it'll affect performance - // Example: ['/usr/share/icons/Tela-nord/scalable/apps'] - 'searchPaths': [''], - 'symbolicIconTheme': { - "dark": "Adwaita", - "light": "Adwaita", - }, - substitutions: { - 'code-url-handler': "visual-studio-code", - 'Code': "visual-studio-code", - 'GitHub Desktop': "github-desktop", - 'Minecraft* 1.20.1': "minecraft", - 'gnome-tweaks': "org.gnome.tweaks", - 'pavucontrol-qt': "pavucontrol", - 'wps': "wps-office2019-kprometheus", - 'wpsoffice': "wps-office2019-kprometheus", - 'footclient': "foot", - '': "image-missing", - }, - regexSubstitutions: [ - { - regex: /^steam_app_(\d+)$/, - replace: "steam_icon_$1", - } - ] - }, - 'keybinds': { - // Format: Mod1+Mod2+key. CaSe SeNsItIvE! - // Modifiers: Shift Ctrl Alt Hyper Meta - // See https://docs.gtk.org/gdk3/index.html#constants for the other keys (they are listed as KEY_key) - 'overview': { - 'altMoveLeft': "Ctrl+b", - 'altMoveRight': "Ctrl+f", - 'deleteToEnd': "Ctrl+k", - }, - 'sidebar': { - 'apis': { - 'nextTab': "Page_Down", - 'prevTab': "Page_Up", - }, - 'options': { // Right sidebar - 'nextTab': "Page_Down", - 'prevTab': "Page_Up", - }, - 'pin': "Ctrl+p", - 'cycleTab': "Ctrl+Tab", - 'nextTab': "Ctrl+Page_Down", - 'prevTab': "Ctrl+Page_Up", - }, - 'cheatsheet': { - 'keybinds': { - 'nextTab': "Page_Down", - 'prevTab': "Page_Up", - }, - 'nextTab': "Ctrl+Page_Down", - 'prevTab': "Ctrl+Page_Up", - 'cycleTab': "Ctrl+Tab", - } - }, - 'bar': { - // Array of bar modes for each monitor. Hit Ctrl+Alt+Slash to cycle. - // Modes: "normal", "focus" (workspace indicator only), "nothing" - // Example for four monitors: ["normal", "focus", "normal", "nothing"] - 'modes': ["normal"] - }, -} - -// Override defaults with user's options function overrideConfigRecursive(userOverrides, configOptions = {}) { for (const [key, value] of Object.entries(userOverrides)) { if (typeof value === 'object' && !(value instanceof Array)) { @@ -255,6 +12,14 @@ function overrideConfigRecursive(userOverrides, configOptions = {}) { } } } + +// Load default options from ~/.config/ags/modules/.configuration/default_options.jsonc +const configFileContents = Utils.readFile(`${App.configDir}/modules/.configuration/default_options.jsonc`); +let configOptions = parseJSONC(configFileContents); +const userOverrideContents = Utils.readFile(`${App.configDir}/user_options.jsonc`); +let userOverrides = parseJSONC(userOverrideContents); + +// Override defaults with user's options overrideConfigRecursive(userOverrides, configOptions); globalThis['userOptions'] = configOptions; diff --git a/.config/ags/modules/.miscutils/jsonc.js b/.config/ags/modules/.miscutils/jsonc.js new file mode 100644 index 000000000..689332880 --- /dev/null +++ b/.config/ags/modules/.miscutils/jsonc.js @@ -0,0 +1,58 @@ +export function parseJSONC(jsoncString) { + let result = ""; + let inString = false; + let inSingleQuote = false; + let inMultiLineComment = false; + let inSingleLineComment = false; + + for (let i = 0; i < jsoncString.length; i++) { + let char = jsoncString[i]; + let nextChar = jsoncString[i + 1]; + + // Handle string start/end + if (!inSingleLineComment && !inMultiLineComment) { + if (char === '"' && !inSingleQuote) { + inString = !inString; + } else if (char === "'" && !inString) { + inSingleQuote = !inSingleQuote; + } + } + + // Handle single-line comments // + if (!inString && !inSingleQuote && !inMultiLineComment && char === '/' && nextChar === '/') { + inSingleLineComment = true; + i++; // Skip next '/' + continue; + } + + // Handle multi-line comments /* + if (!inString && !inSingleQuote && !inSingleLineComment && char === '/' && nextChar === '*') { + inMultiLineComment = true; + i++; // Skip next '*' + continue; + } + + // End single-line comment at newline + if (inSingleLineComment && (char === '\n' || char === '\r')) { + inSingleLineComment = false; + } + + // End multi-line comment */ + if (inMultiLineComment && char === '*' && nextChar === '/') { + inMultiLineComment = false; + i++; // Skip next '/' + continue; + } + + // Only append characters if not inside a comment + if (!inSingleLineComment && !inMultiLineComment) { + result += char; + } + } + + // Remove trailing commas from objects and arrays + result = result.replace(/,\s*([\]}])/g, '$1'); + + // Parse as JSON + return JSON.parse(result); +} diff --git a/.config/ags/user_options.js b/.config/ags/user_options.js deleted file mode 100644 index 03e76202e..000000000 --- a/.config/ags/user_options.js +++ /dev/null @@ -1,9 +0,0 @@ -// For every option, see ~/.config/ags/modules/.configuration/user_options.js -// (vscode users ctrl+click this: file://./modules/.configuration/user_options.js) -// (vim users: `:vsp` to split window, move cursor to this path, press `gf`. `Ctrl-w` twice to switch between) -// options listed in this file will override the default ones in the above file - -const userConfigOptions = { -} - -export default userConfigOptions; diff --git a/.config/ags/user_options.jsonc b/.config/ags/user_options.jsonc new file mode 100644 index 000000000..0a568a549 --- /dev/null +++ b/.config/ags/user_options.jsonc @@ -0,0 +1,16 @@ +// Options in this file override the defaults in: +// ~/.config/ags/modules/.configuration/default_options.jsonc +// +// vscode: ctrl+click this: file://./modules/.configuration/default_options.jsonc +// vim: `:vsp` to split window, move cursor to the path, press `gf`. +// `Ctrl-w` twice to switch between the files +// +// This file is parsed with a custom JSONC parser. +// Don't expect every JSONC feature in... say, vscode, to work. + +{ + // Example: Uncomment the following 3 lines to show 8 (instead of 10) workspaces on the bar + // "workspaces": { + // "shown": 8 + // } +}