aboutsummaryrefslogtreecommitdiff
path: root/clip2file.py
blob: d62b725f05aa7bd16213044a386ff2a4b8236934 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/bin/env python

import subprocess
import datetime
import sys
import os
import argparse


"""
    This program will write the clipboard to a file.
    The format of the file is determined by the available targets and the
    priority list.
"""

OUTPUT_DIR = "~"

def get_clipboard_content(target):
    # Get the clipboard contents.
    try:
        clipfile = subprocess.check_output(
            ['xclip', '-o', '-t', target, '-selection', 'clipboard']
        )
    except subprocess.CalledProcessError as e:
        print(f"Failed to get clipboard contents: {e}", file=sys.stderr)
        sys.exit(e.returncode)
    # Check if the clipboard contents are empty.
    if not clipfile:
        print("Clipboard is empty.", file=sys.stderr)
        sys.exit(1)

    return clipfile

def get_available_targets():
    # Get the lists of available targets.
    # Executes `xclip -o -t TARGETS -selection clipboard` and get the output
    # as a list of strings.
    try:
        output = subprocess.check_output(
            ['xclip', '-o', '-t', 'TARGETS', '-selection', 'clipboard']
        )
    except subprocess.CalledProcessError as e:
        print(f"xclip failed: {e}", file=sys.stderr)
        sys.exit(e.returncode)

    return output.decode('utf-8').split('\n')
    # The output is a list of strings, each string is a target.

def save_file(clipfile, filename, output_dir, ext):
    # Write the clipboard contents to a file.
    pathfile = os.path.expanduser(f"{output_dir}/{filename}.{ext}")

    try:
        with open(pathfile, 'wb') as f:
            try:
                f.write(clipfile)
            except IOError as e:
                print(f"Failed to write to file {filename} in {output_dir}: {e}", file=sys.stderr)
                sys.exit(e.errno)
    except IOError as e:
        print(f"Failed to open file {filename} in {output_dir}: {e}", file=sys.stderr)


def main(filename, output_dir):
    # The priority of the target.
    # The first target in the list is the most important.
    # The final target will be the first of this list matching the available targets
    priority = [
            ("image/avif", "avif"),
            ("image/png", "png"),
            ("text/plain", "txt"),
            ("UTF8_STRING", "txt"),
    ]

    targets = get_available_targets()

    # Get the first target in the priority list that is available.
    # If no target is found, the script exits.
    target = None
    ext = None
    for f, e in priority:
        if f in targets:
            target, ext = f, e
            break

    if target is None or not isinstance(target, str):
        print("No supported clipboard target found.", file=sys.stderr)
        sys.exit(1)

    clipfile = get_clipboard_content(target)

    save_file(clipfile, filename, output_dir, ext)

    print(f"Saved clipboard contents to {output_dir}/{filename}.{ext}")


if __name__ == '__main__':
    date = datetime.datetime.now().isoformat()
    default_filename = f"{date}_clip"

    parser = argparse.ArgumentParser(
        description="Save clipboard contents to a file."
    )
    # Select the directory
    parser.add_argument(
            '-d', '--directory',
            help="Directory to save the clipboard contents to.",
            default=OUTPUT_DIR,
            type=str
    )
    # Select the filename
    parser.add_argument(
            '-f', '--filename',
            help="Filename to save the clipboard contents to.",
            default=default_filename,
            type=str
    )

    args = parser.parse_args()

    main(args.filename, args.directory)