mirror of
https://github.com/vale981/tridactyl
synced 2025-03-05 09:31:41 -05:00
Merge branch 'x_selection' of https://github.com/glacambre/tridactyl into glacambre-x_selection
This commit is contained in:
commit
2a43d0b910
3 changed files with 139 additions and 48 deletions
|
@ -296,6 +296,9 @@ const DEFAULTS = o({
|
|||
// (but we are probably happy to add your terminal to the list if it isn't already there).
|
||||
editorcmd: "auto",
|
||||
browser: "firefox",
|
||||
yankto: "clipboard", // "clipboard", "selection", "both"
|
||||
putfrom: "clipboard", // "clipboard", "selection"
|
||||
externalclipboardcmd: "auto",
|
||||
nativeinstallcmd:
|
||||
"curl -fsSl https://raw.githubusercontent.com/cmcaine/tridactyl/master/native/install.sh | bash",
|
||||
win_nativeinstallcmd:
|
||||
|
|
140
src/excmds.ts
140
src/excmds.ts
|
@ -2118,7 +2118,45 @@ export async function get_current_url() {
|
|||
*/
|
||||
//#background
|
||||
export async function yank(...content: string[]) {
|
||||
await messageActiveTab("commandline_frame", "setClipboard", content)
|
||||
await setclip(content.join(" "))
|
||||
}
|
||||
|
||||
/** Copies a string to the clipboard/selection buffer depending on the user's preferences
|
||||
*
|
||||
* @hidden
|
||||
*/
|
||||
//#background_helper
|
||||
async function setclip(str) {
|
||||
// Functions to avoid retyping everything everywhere
|
||||
let s = () => Native.clipboard("set", str)
|
||||
let c = () => messageActiveTab("commandline_frame", "setClipboard", [str])
|
||||
|
||||
let promises = []
|
||||
switch (await config.getAsync("yankto")) {
|
||||
case "selection":
|
||||
promises = [s()]
|
||||
break
|
||||
case "clipboard":
|
||||
promises = [c()]
|
||||
break
|
||||
case "both":
|
||||
promises = [s(), c()]
|
||||
break
|
||||
}
|
||||
return Promise.all(promises)
|
||||
}
|
||||
|
||||
/** Fetches the content of the clipboard/selection buffer depending on user's preferences
|
||||
*
|
||||
* @hidden
|
||||
*/
|
||||
//#background_helper
|
||||
async function getclip() {
|
||||
if (await config.getAsync("putfrom") == "selection") {
|
||||
return messageActiveTab("commandline_frame", "getClipboard")
|
||||
} else {
|
||||
return Native.clipboard("get", "")
|
||||
}
|
||||
}
|
||||
|
||||
/** Use the system clipboard.
|
||||
|
@ -2135,7 +2173,11 @@ export async function yank(...content: string[]) {
|
|||
|
||||
If `excmd == "yankmd"`, copy the title and url of the open page formatted in Markdown for easy use on sites such as reddit.
|
||||
|
||||
Unfortunately, javascript can only give us the `clipboard` clipboard, not e.g. the X selection clipboard.
|
||||
If you're on Linux and the native messenger is installed, Tridactyl will call an external binary (either xclip or xsel) to read or write to your X selection buffer. If you want another program to be used, set "externalclipboardcmd" to its name and make sure it has the same interface as xsel/xclip ("-i"/"-o" and reading from stdin).
|
||||
|
||||
When doing a read operation (i.e. open or tabopen), if "putfrom" is set to "selection", the X selection buffer will be read instead of the clipboard. Set "putfrom" to "clipboard" to use the clipboard.
|
||||
|
||||
When doing a write operation, if "yankto" is set to "selection", only the X selection buffer will be written to. If "yankto" is set to "both", both the X selection and the clipboard will be written to. If "yankto" is set to "clipboard", only the clipboard will be written to.
|
||||
|
||||
*/
|
||||
//#background
|
||||
|
@ -2143,55 +2185,57 @@ export async function clipboard(excmd: "open" | "yank" | "yankshort" | "yankcano
|
|||
let content = toYank.join(" ")
|
||||
let url = ""
|
||||
let urls = []
|
||||
switch (excmd) {
|
||||
case "yankshort":
|
||||
urls = await geturlsforlinks("rel", "shortlink")
|
||||
if (urls.length == 0) {
|
||||
urls = await geturlsforlinks("rev", "canonical")
|
||||
}
|
||||
if (urls.length > 0) {
|
||||
await yank(urls[0])
|
||||
fillcmdline_tmp("3000", "# " + urls[0] + " copied to clipboard.")
|
||||
try {
|
||||
switch (excmd) {
|
||||
case "yankshort":
|
||||
urls = await geturlsforlinks("rel", "shortlink")
|
||||
if (urls.length == 0) {
|
||||
urls = await geturlsforlinks("rev", "canonical")
|
||||
}
|
||||
if (urls.length > 0) {
|
||||
await yank(urls[0])
|
||||
fillcmdline_tmp("3000", "# " + urls[0] + " copied to clipboard.")
|
||||
break
|
||||
}
|
||||
// Trying yankcanon if yankshort failed...
|
||||
case "yankcanon":
|
||||
urls = await geturlsforlinks("rel", "canonical")
|
||||
if (urls.length > 0) {
|
||||
await yank(urls[0])
|
||||
fillcmdline_tmp("3000", "# " + urls[0] + " copied to clipboard.")
|
||||
break
|
||||
}
|
||||
// Trying yank if yankcanon failed...
|
||||
case "yank":
|
||||
content = content == "" ? (await activeTab()).url : content
|
||||
await yank(content)
|
||||
fillcmdline_tmp("3000", "# " + content + " copied to clipboard.")
|
||||
break
|
||||
}
|
||||
case "yankcanon":
|
||||
urls = await geturlsforlinks("rel", "canonical")
|
||||
if (urls.length > 0) {
|
||||
await yank(urls[0])
|
||||
fillcmdline_tmp("3000", "# " + urls[0] + " copied to clipboard.")
|
||||
case "yanktitle":
|
||||
content = (await activeTab()).title
|
||||
await yank(content)
|
||||
fillcmdline_tmp("3000", "# " + content + " copied to clipboard.")
|
||||
break
|
||||
}
|
||||
case "yank":
|
||||
await messageActiveTab("commandline_content", "focus")
|
||||
content = content == "" ? (await activeTab()).url : content
|
||||
await yank(content)
|
||||
fillcmdline_tmp("3000", "# " + content + " copied to clipboard.")
|
||||
break
|
||||
case "yanktitle":
|
||||
content = (await activeTab()).title
|
||||
await yank(content)
|
||||
fillcmdline_tmp("3000", "# " + content + " copied to clipboard.")
|
||||
break
|
||||
case "yankmd":
|
||||
content = "[" + (await activeTab()).title + "](" + (await activeTab()).url + ")"
|
||||
await yank(content)
|
||||
fillcmdline_tmp("3000", "# " + content + " copied to clipboard.")
|
||||
break
|
||||
case "open":
|
||||
await messageActiveTab("commandline_content", "focus")
|
||||
url = await messageActiveTab("commandline_frame", "getClipboard")
|
||||
url && open(url)
|
||||
break
|
||||
case "tabopen":
|
||||
await messageActiveTab("commandline_content", "focus")
|
||||
url = await messageActiveTab("commandline_frame", "getClipboard")
|
||||
url && tabopen(url)
|
||||
break
|
||||
default:
|
||||
// todo: maybe we should have some common error and error handler
|
||||
throw new Error(`[clipboard] unknown excmd: ${excmd}`)
|
||||
case "yankmd":
|
||||
content = "[" + (await activeTab()).title + "](" + (await activeTab()).url + ")"
|
||||
await yank(content)
|
||||
fillcmdline_tmp("3000", "# " + content + " copied to clipboard.")
|
||||
break
|
||||
case "open":
|
||||
url = await getclip()
|
||||
url && open(url)
|
||||
break
|
||||
case "tabopen":
|
||||
url = await getclip()
|
||||
url && tabopen(url)
|
||||
break
|
||||
default:
|
||||
// todo: maybe we should have some common error and error handler
|
||||
throw new Error(`[clipboard] unknown excmd: ${excmd}`)
|
||||
}
|
||||
} catch (e) {
|
||||
logger.error(e)
|
||||
}
|
||||
CommandLineBackground.hide()
|
||||
}
|
||||
|
||||
/** Change active tab.
|
||||
|
|
|
@ -282,6 +282,50 @@ export async function getenv(variable: string) {
|
|||
return (await sendNativeMsg("env", { var: variable })).content
|
||||
}
|
||||
|
||||
/** Calls an external program, to either set or get the content of the X selection.
|
||||
* When setting the selection or if getting it failed, will return an empty string.
|
||||
**/
|
||||
export async function clipboard(
|
||||
action: "set" | "get",
|
||||
str: string,
|
||||
): Promise<string> {
|
||||
let clipcmd = await config.get("externalclipboardcmd")
|
||||
if (clipcmd == "auto") clipcmd = await firstinpath(["xsel", "xclip"])
|
||||
|
||||
if (clipcmd === undefined) {
|
||||
throw new Error("Couldn't find an external clipboard executable")
|
||||
}
|
||||
|
||||
if (action == "get") {
|
||||
let result = await run(clipcmd + " -o")
|
||||
if (result.code != 0) {
|
||||
throw new Error(
|
||||
`External command failed with code ${result.code}: ${clipcmd}`,
|
||||
)
|
||||
}
|
||||
return result.content
|
||||
} else if (action == "set") {
|
||||
// We're going to need to insert str, which we can't trust, in the clipcmd
|
||||
// In order to do this safely we'll use here documents:
|
||||
// http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_07_04
|
||||
|
||||
// Find a delimiter that isn't in str
|
||||
let heredoc = "TRIDACTYL"
|
||||
while (str.search(heredoc) != -1)
|
||||
heredoc += Math.round(Math.random() * 10)
|
||||
|
||||
// Use delimiter to insert str into clipcmd's stdin
|
||||
clipcmd = `${clipcmd} -i <<'${heredoc}'\n${str}\n${heredoc}\n`
|
||||
let result = await run(clipcmd)
|
||||
if (result.code != 0)
|
||||
throw new Error(
|
||||
`External command failed with code ${result.code}: ${clipcmd}`,
|
||||
)
|
||||
return ""
|
||||
}
|
||||
throw new Error("Unknown action!")
|
||||
}
|
||||
|
||||
/** This returns the commandline that was used to start firefox.
|
||||
You'll get both firefox binary (not necessarily an absolute path) and flags */
|
||||
export async function ffargs(): Promise<string[]> {
|
||||
|
|
Loading…
Add table
Reference in a new issue