add CLI to update icns files inplace
This commit is contained in:
25
README.md
25
README.md
@@ -21,6 +21,7 @@ positional arguments:
|
||||
command
|
||||
extract (e) Read and extract contents of icns file(s).
|
||||
compose (c) Create new icns file from provided image files.
|
||||
update (u) Update existing icns file by inserting or removing media entries.
|
||||
print (p) Print contents of icns file(s).
|
||||
test (t) Test if icns file is valid.
|
||||
convert (img) Convert images between PNG, ARGB, or RGB + alpha mask.
|
||||
@@ -31,16 +32,21 @@ positional arguments:
|
||||
|
||||
```sh
|
||||
# extract
|
||||
icnsutil e ExistingIcon.icns -o ./outdir/
|
||||
icnsutil e Existing.icns -o ./outdir/
|
||||
|
||||
# compose
|
||||
icnsutil c NewIcon.icns 16x16.png 16x16@2x.png *.jp2
|
||||
icnsutil c New.icns 16x16.png 16x16@2x.png *.jp2
|
||||
|
||||
# update
|
||||
icnsutil u Existing.icns -rm toc ic04 ic05
|
||||
icnsutil u Existing.icns -set is32=16.rgb dark="dark icon.icns"
|
||||
icnsutil u Existing.icns -rm dark -set ic04=16.argb -o Updated.icns
|
||||
|
||||
# print
|
||||
icnsutil p ExistingIcon.icns
|
||||
icnsutil p Existing.icns
|
||||
|
||||
# verify valid format
|
||||
icnsutil t ExistingIcon.icns
|
||||
icnsutil t Existing.icns
|
||||
|
||||
# convert image
|
||||
icnsutil img 1024.png 512@2x.jp2
|
||||
@@ -57,7 +63,7 @@ icnsutil img png 16.rgb 16.mask
|
||||
import icnsutil
|
||||
|
||||
# extract
|
||||
img = icnsutil.IcnsFile('ExistingIcon.icns')
|
||||
img = icnsutil.IcnsFile('Existing.icns')
|
||||
img.export(out_dir, allowed_ext='png',
|
||||
recursive=True, convert_png=True)
|
||||
|
||||
@@ -65,7 +71,14 @@ img.export(out_dir, allowed_ext='png',
|
||||
img = icnsutil.IcnsFile()
|
||||
img.add_media(file='16x16.png')
|
||||
img.add_media(file='16x16@2x.png')
|
||||
img.write('./new-icon.icns', toc=False)
|
||||
img.write('./new-icon.icns')
|
||||
|
||||
# update
|
||||
img = icnsutil.IcnsFile('Existing.icns')
|
||||
img.add_media('icp4', file='16x16.png', force=True)
|
||||
if img.remove_media('TOC '):
|
||||
print('table of contents removed')
|
||||
img.write('Existing.icns', toc=False)
|
||||
|
||||
# print
|
||||
icnsutil.IcnsFile.description(fname, indent=2)
|
||||
|
||||
@@ -213,6 +213,16 @@ def get(key: Media.KeyT) -> Media:
|
||||
raise NotImplementedError('Unsupported icns type "' + str(key) + '"')
|
||||
|
||||
|
||||
def key_from_readable(key: str) -> Media.KeyT:
|
||||
key_mapping = {
|
||||
'dark': b'\xFD\xD9\x2F\xA8',
|
||||
'selected': 'slct',
|
||||
'template': 'sbtp',
|
||||
'toc': 'TOC ',
|
||||
} # type: Dict[str, Media.KeyT]
|
||||
return key_mapping.get(key.lower(), key)
|
||||
|
||||
|
||||
def match_maxsize(total: int, typ: str) -> Media:
|
||||
assert(typ == 'argb' or typ == 'rgb')
|
||||
ret = [x for x in _TYPES.values() if x.is_type(typ) and x.maxsize == total]
|
||||
|
||||
@@ -9,7 +9,7 @@ from argparse import ArgumentParser, ArgumentTypeError, RawTextHelpFormatter
|
||||
from argparse import Namespace as ArgParams
|
||||
if __name__ == '__main__':
|
||||
sys.path[0] = os.path.dirname(sys.path[0])
|
||||
from icnsutil import __version__, IcnsFile, ArgbImage
|
||||
from icnsutil import __version__, IcnsFile, IcnsType, ArgbImage
|
||||
|
||||
|
||||
def cli_extract(args: ArgParams) -> None:
|
||||
@@ -44,6 +44,33 @@ def cli_compose(args: ArgParams) -> None:
|
||||
img.write(dest, toc=not args.no_toc)
|
||||
|
||||
|
||||
def cli_update(args: ArgParams) -> None:
|
||||
''' Update existing icns file by inserting or removing media entries. '''
|
||||
icns = IcnsFile(args.file)
|
||||
has_changes = False
|
||||
# remove media
|
||||
for x in args.rm or []:
|
||||
has_changes |= icns.remove_media(IcnsType.key_from_readable(x))
|
||||
# add media
|
||||
for key_val in args.set or []:
|
||||
def fail():
|
||||
raise ArgumentTypeError(
|
||||
'Expected arg format KEY=FILE - got "{}"'.format(key_val))
|
||||
if '=' not in key_val:
|
||||
fail()
|
||||
key, val = key_val.split('=', )
|
||||
if not val:
|
||||
fail()
|
||||
if not os.path.isfile(val):
|
||||
raise ArgumentTypeError('File does not exist "{}"'.format(val))
|
||||
|
||||
icns.add_media(IcnsType.key_from_readable(key), file=val, force=True)
|
||||
has_changes = True
|
||||
# write file
|
||||
if has_changes or args.o:
|
||||
icns.write(args.o or args.file, toc=icns.has_toc())
|
||||
|
||||
|
||||
def cli_print(args: ArgParams) -> None:
|
||||
''' Print contents of icns file(s). '''
|
||||
for fname in enum_with_stdin(args.file):
|
||||
@@ -171,6 +198,19 @@ Notes:
|
||||
template, selected, dark
|
||||
'''
|
||||
|
||||
# Update
|
||||
cmd = add_command('update', 'u', cli_update)
|
||||
cmd.add_argument('file', type=PathExist('f', stdin=True),
|
||||
metavar='FILE', help='The icns file to be updated.')
|
||||
cmd.add_argument('-o', '--output', type=str, metavar='OUT_FILE',
|
||||
help='Choose another destination, dont overwrite input.')
|
||||
grp = cmd.add_argument_group('action')
|
||||
grp.add_argument('-rm', type=str, nargs='+', metavar='KEY',
|
||||
help='Remove media keys from icns file')
|
||||
grp.add_argument('-set', type=str, nargs='+', metavar='KEY=FILE',
|
||||
help='Append or replace media in icns file')
|
||||
cmd.epilog = 'KEY supports names like "dark", "selected", and "template"'
|
||||
|
||||
# Print
|
||||
cmd = add_command('print', 'p', cli_print)
|
||||
cmd.add_argument('-v', '--verbose', action='store_true',
|
||||
|
||||
Reference in New Issue
Block a user