From 16ea302a1abf4ccca6f8aa74678ec32c7ffa7074 Mon Sep 17 00:00:00 2001 From: nojhan Date: Sun, 10 Aug 2025 15:09:57 +0200 Subject: [PATCH] feat: add --cmd --- README.md | 46 +++++++++++++++++++++++++++++++++++++--------- flicksave.py | 35 +++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 416b5ba..f78e739 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,12 @@ and, for instance, create the snapshots by himself each time something happens. Currently, FlickSave can perform the following actions: -- `--save`: save a timestamped snapshot of the watched file(s), -- `--inkscape`: export a timestamped PNG(s) of a watched SVG(s), -- `--git`: commit the modifications of the watched file(s), -- `--log`: print a message stating that the watched file(s) were touched. -- `--dbus`: send a notification to the system's D-Bus. +- `--save`, +- `--inkscape`, +- `--git`, +- `--log`, +- `--dbus`, +- `--cmd [COMMAND]`. You can pass multiple actions. For instance, you can both export a PNG and do a Git commit. @@ -46,20 +47,41 @@ For instance, with a target file named `test.svg`, a snapshot will look like `te ### Optional arguments -* `-h`, `--help`: show this help message and exit. +Actions: + * `--save`: Save a snapshot of the watched file. * `--inkscape`: Save a PNG snpashot of the watched SVG file. * `--git`: Commit the watched file if it has been modified. * `--log`: Print a message when the watched file is touched. * `--dbus`: Send a notification to the system's D-Bus. +* `--cmd [COMMAND]: Run the passed command for each watched file. + You can use tags, which will be replaced by actual data: + - {target} (the current watched file), + - {flick} (the timestamped absolute filename, containing the --directory), + - {directory} (cf. --directory, where to put timestamped files), + - {separator} (cf. --separator), + - {timestamp} (the timestamp formatted by --template), + - {alt_ext} (cf. --alt-ext alternate extension), + - {no_overwrite} (cf. --no-overwrite boolean, 1 if True, 0 if False), + - {event} (the event type, cf. --events). + +Common actions parameters: + +* `-y DELAY`, `--delay DELAY`: The minimum time (in seconds) between running actions. (default: 10) +* `-e {opened,moved,deleted,created,modified,closed}...`, `--events`: The events touching the watched file for which you want your action perfomed. You can pass multiple (space-separated) events, then the action will be performed for each of them. (default: modified) + +Actions parameters affecting only certain actions: + * `-d DIRECTORY`, `--directory DIRECTORY`: The directory in which to copy the saved versions. (default: .) -* `-y DELAY`, `--delay DELAY`: The minimum time (in seconds) between the creation of different saved files. (default: 10) * `-s SEPARATOR`, `--separator SEPARATOR`: Separator character between the file name and the date stamp. (default: _) * `-t TEMPLATE`, `--template TEMPLATE`: Template of the date stamp. (default: %Y-%m-%dT%H:%M:%S) -* `-e {opened,moved,deleted,created,modified,closed}...`, `--events`: The events touching the watched file for which you want your action perfomed. You can pass multiple (space-separated) events, then the action will be performed for each of them. (default: modified) * `-w`, `--no-overwrite`: Do not overwrite snapshots created at the same time, but append a number to their name (especially useful if you watch several events). -* `-v {DEBUG,INFO,WARNING,ERROR}`, `--verbose {DEBUG,INFO,WARNING,ERROR}`: Verbosity level. (default: WARNING) +* `-x EXTENSION`, `--alt-ext EXTENSION`: Alternate extension for the timestamped snapshot (do not forget the dot). (default: ) +Other: + +* `-h`, `--help`: show this help message and exit. +* `-v {DEBUG,INFO,WARNING,ERROR}`, `--verbose {DEBUG,INFO,WARNING,ERROR}`: Verbosity level. (default: WARNING) ## Examples @@ -102,6 +124,12 @@ You can also prepare the list of files to watch by using a subcommand: $ flicksave --log $(find . -type f -name *.png | grep -v test) +If you want to pass your own command: + + $ flicksave --cmd "git commit -a -m 'whatever'" my_file + $ flicksave --cmd "git add {target} ; git commit -m 'Automated commit' ; git tag '{timestamp}'" + $ flicksave --cmd "echo '{flick}' > watching_pipe" *.log + ## Authors diff --git a/flicksave.py b/flicksave.py index 51f6172..1f4d6ea 100755 --- a/flicksave.py +++ b/flicksave.py @@ -216,7 +216,7 @@ class Command(Save): self.no_overwrite = no_overwrite def __repr__(self): - return f"Command(\"{self.cmd}\",{self.save_dir}, {self.date_sep},{self.date_template},{self.alt_ext})" + return f"Command(\"{self.cmd}\",{self.save_dir}, {self.date_sep},{self.date_template},{self.alt_ext},{self.no_overwrite})" def __call__(self, target, flick, event): # Change the extension, if asked. @@ -224,7 +224,16 @@ class Command(Save): if self.alt_ext: flick.ext = self.alt_ext - cmd = self.cmd.format(target=flick.target,flick=self.as_file(flick)) + cmd = self.cmd.format( + target = flick.target, + flick = self.as_file(flick), + directory = self.save_dir, + separator = self.date_sep, + timestamp = flick.date, + alt_ext = self.alt_ext, + no_overwrite = int(self.no_overwrite), + event = event.event_type, + ) logging.info("Run command: %s", cmd) try: # We want the shell because we may call shell command or need environment variables. @@ -349,6 +358,9 @@ if __name__=="__main__": parser.add_argument("-w", "--no-overwrite", action="store_true", help="Do not overwrite snapshots created at the same time, but append a number to their name.") + parser.add_argument("-x", "--alt-ext", metavar="EXTENSION" default='', + help="Alternate extension for the timestamped snapshot (do not forget the dot).") + parser.add_argument("-v","--verbose", choices=['DEBUG','INFO','WARNING','ERROR'], default='INFO', help="Verbosity level.") log_as = { 'DEBUG' :logging.DEBUG, @@ -356,6 +368,8 @@ if __name__=="__main__": 'WARNING':logging.WARNING, 'ERROR' :logging.ERROR } + parser.add_argument("--cmd", metavar="COMMAND", type=str, + help="Execute the provided command as a action. You can use the following tags: {target} (watched file), {flick} (timestamped filename), {directory} (--directory where to put timestamped files), {separator} (--separator), {timestamp} (the timestamp formatted by --template), {alt_ext} (--alt-ext alternate extension), {no_overwrite} (--no-overwrite boolean, 1 if True, 0 if False), {event} (the event type).") existing = { "save": @@ -394,15 +408,16 @@ if __name__=="__main__": available["inkscape"][1] = Command("inkscape {target} --without-gui --export-png={flick} --export-area-page", asked.directory, asked.separator, asked.template, "png", asked.no_overwrite) available["git"][1] = Command("git add {target} ; git commit -m 'Automatic flicksave commit: {flick}'") available["log"][1] = Log() + available["cmd"] = ["", Command(asked.cmd, asked.directory, asked.separator, asked.template, asked.alt_ext, asked.no_overwrite)] + if HAS_DBUS: available["dbus"][1] = DBus() - if __debug__: - # Check that both available and existing are aligned. - for op in existing: - assert op in available - for op in available: - assert op in existing + # Check that both available and existing are aligned. + for op in existing: + assert op in available + for op in available: + assert op in existing logging.debug("Available operators:") for name in available: @@ -411,8 +426,8 @@ if __name__=="__main__": operators = [] requested = vars(asked) def instance(name): - return existing[name][1] - for it in [iz for iz in requested if iz in available and requested[iz]==True]: + return available[name][1] + for it in [iz for iz in requested if iz in available and requested[iz]]: operators.append(instance(it)) if len(operators) == 0: