1# Copyright 2015 Google Inc. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from __future__ import print_function, division, absolute_import, unicode_literals 16 17import logging 18import re 19 20from glyphsLib.util import cast_to_number_or_bool, reverse_cast_to_number_or_bool 21 22logger = logging.getLogger(__name__) 23 24 25def parse_glyphs_filter(filter_str, is_pre=False): 26 """Parses glyphs custom filter string into a dict object that 27 ufo2ft can consume. 28 29 Reference: 30 ufo2ft: https://github.com/googlei18n/ufo2ft 31 Glyphs 2.3 Handbook July 2016, p184 32 33 Args: 34 filter_str - a string of glyphs app filter 35 36 Return: 37 A dictionary contains the structured filter. 38 Return None if parse failed. 39 """ 40 elements = filter_str.split(";") 41 42 if elements[0] == "": 43 logger.error( 44 "Failed to parse glyphs filter, expecting a filter name: \ 45 %s", 46 filter_str, 47 ) 48 return None 49 50 result = {"name": elements[0]} 51 for idx, elem in enumerate(elements[1:]): 52 if not elem: 53 # skip empty arguments 54 continue 55 if ":" in elem: 56 # Key value pair 57 key, value = elem.split(":", 1) 58 if key.lower() in ["include", "exclude"]: 59 if idx != len(elements[1:]) - 1: 60 logger.error( 61 "{} can only present as the last argument in the filter. " 62 "{} is ignored.".format(key, elem) 63 ) 64 continue 65 result[key.lower()] = re.split("[ ,]+", value) 66 else: 67 if "kwargs" not in result: 68 result["kwargs"] = {} 69 result["kwargs"][key] = cast_to_number_or_bool(value) 70 else: 71 if "args" not in result: 72 result["args"] = [] 73 result["args"].append(cast_to_number_or_bool(elem)) 74 if is_pre: 75 result["pre"] = True 76 return result 77 78 79def write_glyphs_filter(result): 80 elements = [result["name"]] 81 if "args" in result: 82 for arg in result["args"]: 83 elements.append(reverse_cast_to_number_or_bool(arg)) 84 if "kwargs" in result: 85 for key, arg in result["kwargs"].items(): 86 if key.lower() not in ("include", "exclude"): 87 elements.append(key + ":" + reverse_cast_to_number_or_bool(arg)) 88 for key, arg in result["kwargs"].items(): 89 if key.lower() in ("include", "exclude"): 90 elements.append(key + ":" + reverse_cast_to_number_or_bool(arg)) 91 return ";".join(elements) 92