diff --git a/native/native_main.py b/native/native_main.py index 5d559c0c..d270aae2 100755 --- a/native/native_main.py +++ b/native/native_main.py @@ -14,7 +14,7 @@ import time import unicodedata DEBUG = False -VERSION = "0.1.10" +VERSION = "0.1.11" class NoConnectionError(Exception): @@ -468,10 +468,21 @@ def handleMessage(message): reply["code"] = 2 elif cmd == "write": - path = os.path.expanduser(message["file"]) with open(path, "w") as file: file.write(message["content"]) + elif cmd == "writerc": + path = os.path.expanduser(message["file"]) + if not os.path.isfile(path) or message["force"]: + try: + with open(path, "w") as file: + file.write(message["content"]) + reply["code"] = 0 # Success. + except EnvironmentError: + reply["code"] = 2 # Some OS related error. + else: + reply["code"] = 1 # File exist, send force="true" or try another filename. + elif cmd == "temp": prefix = message.get("prefix") if prefix is None: diff --git a/src/background/config_rc.ts b/src/background/config_rc.ts index 528a4377..f1696619 100644 --- a/src/background/config_rc.ts +++ b/src/background/config_rc.ts @@ -20,7 +20,7 @@ export async function writeRc(conf: string, force = false, filename = "auto") { } else { path = filename } - return await Native.write(path, conf) + return await Native.writerc(path, force, conf) } export async function runRc(rc: string) { diff --git a/src/excmds.ts b/src/excmds.ts index 1539280d..0d20df26 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -691,7 +691,7 @@ export async function mktridactylrc(...argArr: string[]) { const file = argParse(argArr).join(" ") || undefined const conf = config.parseConfig() - if (await Native.nativegate("0.1.3") && (!await rc.writeRc(conf, overwrite, file))) logger.error("Could not write RC file") + if (await Native.nativegate("0.1.11") && (!await rc.writeRc(conf, overwrite, file))) logger.error("Could not write RC file") return conf } diff --git a/src/lib/config.ts b/src/lib/config.ts index efe7e0a5..5c24fe13 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -936,7 +936,7 @@ const DEFAULTS = o(new default_config()) @param target path of properties as an array @hidden -*/ + */ function getDeepProperty(obj, target: string[]) { if (obj !== undefined && target.length) { return getDeepProperty(obj[target[0]], target.slice(1)) @@ -951,7 +951,7 @@ function getDeepProperty(obj, target: string[]) { @param target path of properties as an array @hidden -*/ + */ function setDeepProperty(obj, value, target) { if (target.length > 1) { // If necessary antecedent objects don't exist, create them. @@ -990,15 +990,15 @@ export function getURL(url: string, target: string[]) { // Keep only the ones that have a match .filter( k => - url.match(k) && - getDeepProperty(conf.subconfigs[k], target) !== - undefined, + url.match(k) && + getDeepProperty(conf.subconfigs[k], target) !== + undefined, ) // Sort them from lowest to highest priority, default to a priority of 10 .sort( (k1, k2) => - (conf.subconfigs[k1].priority || 10) - - (conf.subconfigs[k2].priority || 10), + (conf.subconfigs[k1].priority || 10) - + (conf.subconfigs[k2].priority || 10), ) // Merge their corresponding value if they're objects, otherwise return the last value .reduce( @@ -1029,7 +1029,7 @@ export function getURL(url: string, target: string[]) { If the user has not specified a key, use the corresponding key from defaults, if one exists, else undefined. @hidden -*/ + */ export function get(target_typed?: keyof default_config, ...target: string[]) { if (target_typed === undefined) { target = [] @@ -1062,7 +1062,7 @@ export function get(target_typed?: keyof default_config, ...target: string[]) { /** Get the value of the key target. Please only use this with targets that will be used at runtime - it skips static checks. Prefer [[get]]. -*/ + */ export function getDynamic(...target: string[]) { return get(target[0] as keyof default_config, ...target.slice(1)) } @@ -1070,7 +1070,7 @@ export function getDynamic(...target: string[]) { /** Get the value of the key target. Please only use this with targets that will be used at runtime - it skips static checks. Prefer [[getAsync]]. -*/ + */ export async function getAsyncDynamic(...target: string[]) { return getAsync(target[0] as keyof default_config, ...target.slice(1)) } @@ -1080,7 +1080,7 @@ export async function getAsyncDynamic(...target: string[]) { This is useful if you are a content script and you've just been loaded. @hidden -*/ + */ export async function getAsync(target_typed?: keyof default_config, ...target: string[]) { if (INITIALISED) { return get(target_typed, ...target) @@ -1105,7 +1105,7 @@ export function setURL(pattern, ...args) { set("aucmd", "BufRead", "memrise.com", "open memrise.com") @hidden -*/ + */ export function set(...args) { if (args.length < 2) { throw "You must provide at least two arguments!" @@ -1139,7 +1139,7 @@ export function unset(...target) { sometime after this happens. @hidden -*/ + */ export async function save(storage: "local" | "sync" = get("storageloc")) { // let storageobj = storage === "local" ? browser.storage.local : browser.storage.sync // storageobj.set({CONFIGNAME: USERCONFIG}) @@ -1159,7 +1159,7 @@ export async function save(storage: "local" | "sync" = get("storageloc")) { When adding updaters, don't forget to set("configversion", newversionnumber)! @hidden -*/ + */ export async function update() { // Updates a value both in the main config and in sub (=site specific) configs const updateAll = (setting: any[], fn: (any) => any) => { @@ -1225,19 +1225,19 @@ export async function update() { mapname, getDeepProperty(USERCONFIG, [mapname]), ]) - // mapobj is undefined if the user didn't define any bindings + // mapobj is undefined if the user didn't define any bindings .filter(([mapname, mapobj]) => mapobj) .forEach(([mapname, mapobj]) => { // For each mapping Object.keys(mapobj) - // Keep only the ones with im_* functions + // Keep only the ones with im_* functions .filter( key => - mapobj[key].search( - "^im_|([^a-zA-Z0-9_-])im_", - ) >= 0, + mapobj[key].search( + "^im_|([^a-zA-Z0-9_-])im_", + ) >= 0, ) - // Replace the prefix + // Replace the prefix .forEach(key => setDeepProperty( USERCONFIG, @@ -1322,7 +1322,7 @@ export async function update() { asynchronous calls generated by getAsync. @hidden -*/ + */ async function init() { const syncConfig = await browser.storage.sync.get(CONFIGNAME) schlepp(syncConfig[CONFIGNAME]) @@ -1460,7 +1460,7 @@ const parseConfigHelper = (pconf, parseobj) => { parseobj.binds.push(`unbind --mode=hint ${e}`) } } else if (i === "subconfigs") { - parseobj.subconfigs.push(`js tri.config.set("${i}, {"${e}": ${JSON.stringify(pconf[i][e])}})`) + parseobj.subconfigs.push(`js tri.config.set("${i}", {"${e}": ${JSON.stringify(pconf[i][e])}})`) } else if (i === "exaliases") { // Only really useful if mapping the entire config and not just pconf. if (e === "alias") { @@ -1512,19 +1512,19 @@ browser.storage.onChanged.addListener(async (changes, areaname) => { // A key has been :unset if it exists in USERCONFIG and doesn't in changes and if its value in USERCONFIG is different from the one it has in default_config const unsetKeys = Object.keys(USERCONFIG).filter( k => - changes[CONFIGNAME].newValue[k] === undefined && - JSON.stringify(USERCONFIG[k]) !== - JSON.stringify(defaultConf[k]), + changes[CONFIGNAME].newValue[k] === undefined && + JSON.stringify(USERCONFIG[k]) !== + JSON.stringify(defaultConf[k]), ) // A key has changed if it is defined in USERCONFIG and its value in USERCONFIG is different from the one in `changes` or if the value in defaultConf is different from the one in `changes` const changedKeys = Object.keys(changes[CONFIGNAME].newValue).filter( k => - JSON.stringify( - USERCONFIG[k] !== undefined - ? USERCONFIG[k] - : defaultConf[k], - ) !== JSON.stringify(changes[CONFIGNAME].newValue[k]), + JSON.stringify( + USERCONFIG[k] !== undefined + ? USERCONFIG[k] + : defaultConf[k], + ) !== JSON.stringify(changes[CONFIGNAME].newValue[k]), ) USERCONFIG = changes[CONFIGNAME].newValue diff --git a/src/lib/native.ts b/src/lib/native.ts index f95cc5fb..d4e4a04a 100644 --- a/src/lib/native.ts +++ b/src/lib/native.ts @@ -15,6 +15,7 @@ type MessageCommand = | "run" | "read" | "write" + | "writerc" | "temp" | "list_dir" | "mkdir" @@ -273,6 +274,12 @@ export async function write(file: string, content: string) { }) } +export async function writerc(file: string, force: boolean, content: string) { + return sendNativeMsg("writerc", { file, force, content }).catch(e => { + throw `Failed to write '${content}' to '${file}'. ${e}` + }) +} + export async function mkdir(dir: string, exist_ok: boolean) { return sendNativeMsg("mkdir", { dir, exist_ok }).catch(e => { throw `Failed to create directory '${dir}'. ${e}`