#!/usr/bin/env python3 import os import sys import re import subprocess from BaseExtension import BaseExtension # For linting purposes from argparse import ArgumentParser """If syntax error occurs here, change inkscape interpreter to python3""" """I have yet to find a way for an extension to call another extension with parameters, without GUI. This extension can be run as part of a standalone extension (using BaseExtension) or imported for use by another extension. This workaround is done via the 'option' arg in the 'custom_effect' function""" def custom_effect(self: BaseExtension): """Note: The init of the BaseExtension class will set its 'custom_effect' attr to this function. Hence, the self arg is of type BaseExtension.""" selected = self.svg.selected root = self.document.getroot() actions_list = [] proc = subprocess.run("inkscape --verb-list | grep -oP '^.+?(?=:)'", shell=True, capture_output=True) valid_actions_and_verbs = proc.stdout.decode().splitlines() proc = subprocess.run("inkscape --action-list | grep -oP '^.+?(?= *:)'", shell=True, capture_output=True) valid_actions_and_verbs += proc.stdout.decode().splitlines() self.options.dry_run = self.options.dry_run == 'true' def verify_action(action): if ':' in action: action = action.split(':')[0] if action not in valid_actions_and_verbs: raise ValueError(action) def select_do_individually(objs, actions): for obj in objs: actions_list.append("EditDeselect") actions_list.append("select-by-id:" + obj.get_id()) if isinstance(actions, str): actions = [actions] for action in actions: verify_action(action) actions_list.append(action) def select_do_on_all(objs, actions): for obj in objs: actions_list.append("select-by-id:" + obj.get_id()) if isinstance(actions, str): actions = [actions] for action in actions: verify_action(action) actions_list.append(action) effects = [] try: if self.options.tab_effect is None: if self.options.effects is not None: self.options.tab_effect = 'Multi' elif self.options.effect1 is not None: self.options.tab_effect = 'Simple' elif self.options.tab_effect in ('Preset', 'Simple'): for attr in ('effect_' + self.options.tab_effect.lower() + str(i) for i in range(1, 4)): e = getattr(self.options, attr) if e != None: effects += [e.strip()] if effects == []: raise ValueError elif self.options.tab_effect == 'Multi': if self.options.effects is None: raise ValueError for line in self.options.effects.split('\\n'): effects += [e.strip() for e in line.split(';') if e != ''] except ValueError: self.msg("No effects inputted! Quitting...") sys.exit(0) if self.options.target == 'root': objects = self.find(root, '/svg:svg' + self.options.xpath) elif self.options.target == 'selected': objects = self.find(selected, self.options.xpath) if objects == []: self.msg(f"No objects satisfies XPath: '{self.options.xpath}'.") self.msg("Root:", self.show(root)) self.msg("Selected:", self.show(selected)) sys.exit(0) try: if self.options.mode == 'all': select_do_on_all(objects, effects) elif self.options.mode == 'indiv': select_do_individually(objects, effects) except ValueError as e: self.msg(f"'{e.args[0]}' is not a valid action or verb in inkscape.") sys.exit(1) if self.options.dry_run: self.msg(f"{'DRY RUN':=^40}") self.msg("Root:", self.show(self.find(root, '/*'))) self.msg("Selected:", self.show(selected)) self.msg() self.msg("XPath:", self.show(objects)) self.msg() self.msg("Actions:", actions_list) sys.exit(0) return actions_list def args_adder(arg_parser: ArgumentParser): arg_parser.add_argument("--target", default='root', help="Object to apply xpath find on") arg_parser.add_argument("--xpath", default='/*', help="For selection of objects") arg_parser.add_argument("--tab_main", default=None) arg_parser.add_argument("--Simple", default=None) arg_parser.add_argument("--Multi", default=None) arg_parser.add_argument("--mode", default="all", help="Mode to apply effects on objects") arg_parser.add_argument("--tab_effect", default=None) for arg in (*(x + str(y) for x in ('effect_preset', 'effect_simple') for y in range(1, 4)), 'effects'): arg_parser.add_argument(f"--{arg}", default=None, help="Inkscape verb for path op") arg_parser.add_argument("--dry_run", default='false') arg_parser.add_argument("--null_notebook", default='false') #import inkex #for key, value in arg_parser.parse_args()._get_kwargs(): # if value is not None: # inkex.utils.debug("{}={}".format(key, value)) BatchTask = BaseExtension(custom_effect, args_adder=args_adder) if __name__ == '__main__': BatchTask.run() # Namespace(Multi='SelectionDiff', Simple='SelectionDiff', dry_run='false', effect1='SelectionBreakApart', effect2=None, effect3=None, effects=None, ids=['image25'], input_file='/tmp/ink_ext_XXXXXX.svgIDCKU0', mode='all', null='null', output=<_io.BufferedWriter name=''>, selected_nodes=[], tab_effect='Simple', tab_main='Options', target='root', xpath='/*') # Namespace(Multi=None, Simple=None, dry_run='false', effect1='SelectionDelete', effect2=None, effect3=None, effects=None, mode='all', null='false', tab_effect=None, tab_main=None, target='root', xpath='/*')