Greatly reduce code duplication in clipboard implementations

This commit is contained in:
2024-03-03 23:26:39 -05:00
parent 6fecf5a686
commit 24b899a83a
7 changed files with 112 additions and 140 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ func main() {
default: default:
cli.HelpCopy() cli.HelpCopy()
} }
offline.CopyField(targetLocation, field, args[0]) offline.CopyArgument(targetLocation, field, args[0])
case "edit": case "edit":
var field rune var field rune
field = field // TODO temporary to avoid unused variable error field = field // TODO temporary to avoid unused variable error
+1 -3
View File
@@ -65,9 +65,7 @@ func EntryReader(decryptedEntry []string, hidePassword bool) {
} }
func EntryReaderShortcut(targetLocation string, hidePassword bool) { func EntryReaderShortcut(targetLocation string, hidePassword bool) {
if isFile, _ := offline.TargetIsFile(targetLocation, true); isFile { if isFile, _ := offline.TargetIsFile(targetLocation, true, 2); isFile {
EntryReader(offline.DecryptGPG(targetLocation), hidePassword) EntryReader(offline.DecryptGPG(targetLocation), hidePassword)
} else {
fmt.Println(offline.AnsiError + "Failed to read \"" + targetLocation + "\" - it is a directory" + offline.AnsiReset)
} }
} }
+43
View File
@@ -0,0 +1,43 @@
package offline
import (
"bufio"
"fmt"
"os"
)
func CopyArgument(targetLocation string, field int, executableName string) {
if isFile, _ := TargetIsFile(targetLocation, true, 2); isFile {
decryptedEntry := DecryptGPG(targetLocation)
var copySubject string // will store data to be copied
// ensure field exists in entry
if len(decryptedEntry) > field {
copySubject = decryptedEntry[field]
} else {
fmt.Println(AnsiError + "Field does not exist in entry" + AnsiReset)
os.Exit(1)
}
// ensure field is not blank
if copySubject == "" {
fmt.Println(AnsiError + "Field is empty" + AnsiReset)
os.Exit(1)
}
// copy field to clipboard, launch clipboard clearing process
copyField(copySubject, executableName)
}
}
func ClipClearArgument() {
// read previous clipboard contents from stdin
clipScanner := bufio.NewScanner(os.Stdin)
if clipScanner.Scan() {
oldContents := clipScanner.Text()
clipClear(oldContents)
} else {
os.Exit(0)
}
}
+16 -38
View File
@@ -13,50 +13,28 @@ import (
// TODO MacOS support is entirely untested - I would appreciate feedback on this implementation // TODO MacOS support is entirely untested - I would appreciate feedback on this implementation
// CopyField copies a field from an entry to the clipboard // CopyField copies a field from an entry to the clipboard
func CopyField(targetLocation string, field int, executableName string) { func copyField(copySubject string, executableName string) {
if isFile, _ := TargetIsFile(targetLocation, true); isFile { cmd := exec.Command("pbcopy")
decryptedEntry := DecryptGPG(targetLocation) writeToStdin(cmd, copySubject)
var copySubject string // will store data to be copied err := cmd.Run()
if err != nil {
// ensure field exists in entry fmt.Println(AnsiError + "Failed to copy to clipboard: " + err.Error() + AnsiReset)
if len(decryptedEntry) > field {
copySubject = decryptedEntry[field]
} else {
fmt.Println(AnsiError + "Field does not exist in entry" + AnsiReset)
os.Exit(1)
}
// ensure field is not blank
if copySubject == "" {
fmt.Println(AnsiError + "Field is empty" + AnsiReset)
os.Exit(1)
}
cmd := exec.Command("pbcopy")
writeToStdin(cmd, copySubject)
err := cmd.Run()
if err != nil {
fmt.Println(AnsiError + "Failed to copy to clipboard: " + err.Error() + AnsiReset)
os.Exit(1)
}
cmd = exec.Command(executableName, "clipclear")
writeToStdin(cmd, copySubject)
err = cmd.Start()
if err != nil {
fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset)
os.Exit(1)
}
} else {
fmt.Println(AnsiError + "Failed to read \"" + targetLocation + "\" - it is a directory" + AnsiReset)
os.Exit(1) os.Exit(1)
} }
cmd = exec.Command(executableName, "clipclear")
writeToStdin(cmd, copySubject)
err = cmd.Start()
if err != nil {
fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset)
os.Exit(1)
}
os.Exit(0) os.Exit(0)
} }
// ClipClear is called in a separate process to clear the clipboard after 30 seconds // ClipClear is called in a separate process to clear the clipboard after 30 seconds
func ClipClear(oldContents string) { func clipClear(oldContents string) {
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
cmd := exec.Command("pbpaste") cmd := exec.Command("pbpaste")
+26 -48
View File
@@ -13,61 +13,39 @@ import (
// TODO Implement support for Termux via termux-clipboard-set (in separate file) // TODO Implement support for Termux via termux-clipboard-set (in separate file)
// CopyField copies a field from an entry to the clipboard // CopyField copies a field from an entry to the clipboard
func CopyField(targetLocation string, field int, executableName string) { func copyField(copySubject string, executableName string) {
if isFile, _ := TargetIsFile(targetLocation, true); isFile { var envSet bool // track whether environment variables are set
decryptedEntry := DecryptGPG(targetLocation) var cmd *exec.Cmd
var copySubject string // will store data to be copied // determine whether to use wl-copy (Wayland) or xclip (X11)
if _, envSet = os.LookupEnv("WAYLAND_DISPLAY"); envSet {
// ensure field exists in entry cmd = exec.Command("wl-copy")
if len(decryptedEntry) > field { } else if _, envSet = os.LookupEnv("DISPLAY"); envSet {
copySubject = decryptedEntry[field] cmd = exec.Command("xclip", "-sel", "c")
} else {
fmt.Println(AnsiError + "Field does not exist in entry" + AnsiReset)
os.Exit(1)
}
// ensure field is not blank
if copySubject == "" {
fmt.Println(AnsiError + "Field is empty" + AnsiReset)
os.Exit(1)
}
var envSet bool // track whether environment variables are set
var cmd *exec.Cmd
// determine whether to use wl-copy (Wayland) or xclip (X11)
if _, envSet = os.LookupEnv("WAYLAND_DISPLAY"); envSet {
cmd = exec.Command("wl-copy")
} else if _, envSet = os.LookupEnv("DISPLAY"); envSet {
cmd = exec.Command("xclip", "-sel", "c")
} else {
fmt.Println(AnsiError + "Clipboard platform could not be determined - note that the clipboard does not function in a raw TTY" + AnsiReset)
os.Exit(1)
}
writeToStdin(cmd, copySubject)
err := cmd.Run()
if err != nil {
fmt.Println(AnsiError + "Failed to copy to clipboard: " + err.Error() + AnsiReset)
os.Exit(1)
}
cmd = exec.Command(executableName, "clipclear")
writeToStdin(cmd, copySubject)
err = cmd.Start()
if err != nil {
fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset)
os.Exit(1)
}
} else { } else {
fmt.Println(AnsiError + "Failed to read \"" + targetLocation + "\" - it is a directory" + AnsiReset) fmt.Println(AnsiError + "Clipboard platform could not be determined - note that the clipboard does not function in a raw TTY" + AnsiReset)
os.Exit(1) os.Exit(1)
} }
writeToStdin(cmd, copySubject)
err := cmd.Run()
if err != nil {
fmt.Println(AnsiError + "Failed to copy to clipboard: " + err.Error() + AnsiReset)
os.Exit(1)
}
cmd = exec.Command(executableName, "clipclear")
writeToStdin(cmd, copySubject)
err = cmd.Start()
if err != nil {
fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset)
os.Exit(1)
}
os.Exit(0) os.Exit(0)
} }
// ClipClear is called in a separate process to clear the clipboard after 30 seconds // ClipClear is called in a separate process to clear the clipboard after 30 seconds
func ClipClear(oldContents string) { func clipClear(oldContents string) {
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
var envSet bool // track whether environment variables are set var envSet bool // track whether environment variables are set
+15 -37
View File
@@ -11,49 +11,27 @@ import (
) )
// CopyField copies a field from an entry to the clipboard // CopyField copies a field from an entry to the clipboard
func CopyField(targetLocation string, field int, executableName string) { func copyField(copySubject string, executableName string) {
if isFile, _ := TargetIsFile(targetLocation, true); isFile { cmd := exec.Command("powershell.exe", "-c", fmt.Sprintf("echo '%s' | Set-Clipboard", copySubject))
decryptedEntry := DecryptGPG(targetLocation) err := cmd.Run()
var copySubject string // will store data to be copied if err != nil {
fmt.Println(AnsiError + "Failed to copy to clipboard: " + err.Error() + AnsiReset)
// ensure field exists in entry
if len(decryptedEntry) > field {
copySubject = decryptedEntry[field]
} else {
fmt.Println(AnsiError + "Field does not exist in entry" + AnsiReset)
os.Exit(1)
}
// ensure field is not blank
if copySubject == "" {
fmt.Println(AnsiError + "Field is empty" + AnsiReset)
os.Exit(1)
}
cmd := exec.Command("powershell.exe", "-c", fmt.Sprintf("echo '%s' | Set-Clipboard", copySubject))
err := cmd.Run()
if err != nil {
fmt.Println(AnsiError + "Failed to copy to clipboard: " + err.Error() + AnsiReset)
os.Exit(1)
}
cmd = exec.Command(executableName, "clipclear")
writeToStdin(cmd, copySubject)
err = cmd.Start()
if err != nil {
fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset)
os.Exit(1)
}
} else {
fmt.Println(AnsiError + "Failed to read \"" + targetLocation + "\" - it is a directory" + AnsiReset)
os.Exit(1) os.Exit(1)
} }
cmd = exec.Command(executableName, "clipclear")
writeToStdin(cmd, copySubject)
err = cmd.Start()
if err != nil {
fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset)
os.Exit(1)
}
os.Exit(0) os.Exit(0)
} }
// ClipClear is called in a separate process to clear the clipboard after 30 seconds // ClipClear is called in a separate process to clear the clipboard after 30 seconds
func ClipClear(oldContents string) { func clipClear(oldContents string) {
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
cmd := exec.Command("powershell.exe", "-c", "Get-Clipboard") cmd := exec.Command("powershell.exe", "-c", "Get-Clipboard")
@@ -1,7 +1,6 @@
package offline package offline
import ( import (
"bufio"
"fmt" "fmt"
"io" "io"
"os" "os"
@@ -9,8 +8,9 @@ import (
) )
// TargetIsFile TargetStatusCheck checks if the targetLocation is a file, directory, or is inaccessible // TargetIsFile TargetStatusCheck checks if the targetLocation is a file, directory, or is inaccessible
// failCondition: 0 = fail on inaccessible, 1 = fail on inaccessible/file, 2 = fail on inaccessible/directory
// returns: isFile, isAccessible // returns: isFile, isAccessible
func TargetIsFile(targetLocation string, errorOnFail bool) (bool, bool) { func TargetIsFile(targetLocation string, errorOnFail bool, failCondition uint8) (bool, bool) {
targetInfo, err := os.Stat(targetLocation) targetInfo, err := os.Stat(targetLocation)
if err != nil { if err != nil {
if errorOnFail { if errorOnFail {
@@ -21,8 +21,16 @@ func TargetIsFile(targetLocation string, errorOnFail bool) (bool, bool) {
} }
} }
if targetInfo.IsDir() { if targetInfo.IsDir() {
if errorOnFail && failCondition == 2 {
fmt.Println(AnsiError + "\"" + targetLocation + "\" is a directory" + AnsiReset)
os.Exit(1)
}
return false, true return false, true
} else { } else {
if errorOnFail && failCondition == 1 {
fmt.Println(AnsiError + "\"" + targetLocation + "\" is a file" + AnsiReset)
os.Exit(1)
}
return true, true return true, true
} }
} }
@@ -35,14 +43,3 @@ func writeToStdin(cmd *exec.Cmd, input string) {
io.WriteString(stdin, input) io.WriteString(stdin, input)
}() }()
} }
func ClipClearArgument() {
// read previous clipboard contents from stdin
clipScanner := bufio.NewScanner(os.Stdin)
if clipScanner.Scan() {
oldContents := clipScanner.Text()
ClipClear(oldContents)
} else {
os.Exit(0)
}
}