# Create List Filter via Script

**URL:** <https://forum.glyphsapp.com/t/create-list-filter-via-script/2134>\
**Category:** Scripting\
**Created:** [April 19, 2015, 1:11pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134 "2015-04-19T13:11:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![oneweioranother](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/oneweioranother/32/273_2.png) [@oneweioranother](https://forum.glyphsapp.com/u/oneweioranother)\
**Post date:** [April 19, 2015, 1:11pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/1 "2015-04-19T13:11:26Z")

</div>

Is this possible? Couldn’t find it in the docu.

---

<div class="post-metadata">

**Author:** ![GeorgSeifert](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/georgseifert/32/259_2.png) [@GeorgSeifert](https://forum.glyphsapp.com/u/GeorgSeifert)\
**Post date:** [April 19, 2015, 3:08pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/2 "2015-04-19T15:08:11Z")

</div>

unfortunately not. At least not in a sane way. Can you add a feature request to: [http://bugreport.glyphsapp.com](http://bugreport.glyphsapp.com)

---

<div class="post-metadata">

**Author:** ![diego\_maldonado](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/diego_maldonado/32/1602_2.png) [@diego\_maldonado](https://forum.glyphsapp.com/u/diego_maldonado)\
**Post date:** [July 29, 2020, 1:21pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/3 "2020-07-29T13:21:13Z")

</div>

Still the same answer here?

---

<div class="post-metadata">

**Author:** ![joachimvu](https://forum.glyphsapp.com/letter_avatar_proxy/v4/letter/j/ad7895/32.png) [@joachimvu](https://forum.glyphsapp.com/u/joachimvu)\
**Post date:** [July 29, 2020, 2:47pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/4 "2020-07-29T14:47:05Z")

</div>

not sure if there’s a better way, but I do it like this:

```auto
filterContent = {"Count" : 1,
				 "ShallHaveCount" : 1,
				 "icon" : "CustomFilterListTemplate",
				 "isLeaf" : 1,
				 "list" : ["A"],
				 "name" : "myNewFilter"
				 }

filterController = Font.fontView.glyphsGroupViewController()
filters = filterController.glyphGroups()[2]["subGroup"]
filters.append(filterContent)
filterController.update()

```

---

<div class="post-metadata">

**Author:** ![GeorgSeifert](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/georgseifert/32/259_2.png) [@GeorgSeifert](https://forum.glyphsapp.com/u/GeorgSeifert)\
**Post date:** [July 30, 2020, 12:03pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/5 "2020-07-30T12:03:29Z")

</div>

That looks very good.

---

<div class="post-metadata">

**Author:** ![jkutilek](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/jkutilek/32/29173_2.png) [@jkutilek](https://forum.glyphsapp.com/u/jkutilek)\
**Post date:** [October 19, 2021, 10:57am UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/6 "2021-10-19T10:57:39Z")

</div>

Any updates on this? It doesn’t seem to work anymore with Glyphs 3.

```python
from Foundation import NSMutableDictionary
font = Glyphs.font
filterController = font.fontView.glyphsGroupViewController()
glyphGroups = filterController.glyphGroups()
filters = glyphGroups[3]
print(filters)
flt = NSMutableDictionary.dictionaryWithObjectsAndKeys_(
	True, "isLeaf",
	"MyListFilter", "name",
	["A", "B"], "list",
	"CustomFilterListTemplate", "icon",
	None
)
# Neither of those two options work:
# filters.insertObject_inSubItemsAtIndex_(flt, 0)
# filters.insertSubItems_atIndex_([flt], 0)
filterController.update()

```

Alternatively, is there a way to filter the font view from within a script temporarily without adding a filter to the sidebar?

---

<div class="post-metadata">

**Author:** ![takaakifuji](https://forum.glyphsapp.com/letter_avatar_proxy/v4/letter/t/4bbf92/32.png) [@takaakifuji](https://forum.glyphsapp.com/u/takaakifuji)\
**Post date:** [October 19, 2021, 10:49pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/7 "2021-10-19T22:49:10Z")

</div>

> Alternatively, is there a way to filter the font view from within a script temporarily without adding a filter to the sidebar?

I have thought the same thing a few years ago:

```auto
class SearchState(object):
	ALL = 0
	NAME = 1
	UNICODE = 2
	NOTE = 3
	@staticmethod
	def make_key(key, searchField):
		if Glyphs.versionNumber < 3.0:
			return 'GlyphList{0}'.format(key)
		return searchField.key_(key)
	@classmethod
	def set_state_in_font(cls, font, state, search=False):
		controller = font.fontView
		searchField = controller.glyphSearchField()
		searchField.setStringValue_(state.pattern)
		Glyphs.defaults[cls.make_key('SearchState', searchField)] = state.mode
		Glyphs.defaults[cls.make_key('SearchStateMatchCase', searchField)] = state.match_case
		Glyphs.defaults[cls.make_key('SearchStateRegex', searchField)] = state.regex
		if search:
			controller.filterGlyphs_(searchField)
	@classmethod
	def from_font(cls, font):
		controller = font.fontView
		searchField = controller.glyphSearchField()
		return cls(
			searchField.stringValue(),
			Glyphs.defaults[cls.make_key('SearchState', searchField)],
			bool(Glyphs.defaults[cls.make_key('SearchStateMatchCase', searchField)]),
			bool(Glyphs.defaults[cls.make_key('SearchStateRegex', searchField)])
		)
	def __init__ (self, pattern, mode=0, match_case=False, regex=False):
		self.pattern = pattern
		self.mode = mode if not regex else self.NAME
		self.match_case = match_case
		self.regex = regex
	def perform_temporal_search(self, font):
		prev = self.from_font(font)
		try:
			self.set_state_in_font(font, self, search=True)
		finally:
			self.set_state_in_font(font, prev, search=False)
	@classmethod
	def reset(cls, font):
		cls.set_state_in_font(font, cls.from_font(font), search=True)

if __name__ == ' __main__':
	SearchState('A|B|C', mode=SearchState.NAME, match_case=True, regex=True).perform_temporal_search(Glyphs.font)

```

I came up with the code above. My idea at that time was to perform a regex search, and then restore only the UI state as if nothing happened.

---

<div class="post-metadata">

**Author:** ![GeorgSeifert](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/georgseifert/32/259_2.png) [@GeorgSeifert](https://forum.glyphsapp.com/u/GeorgSeifert)\
**Post date:** [October 20, 2021, 1:18pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/8 "2021-10-20T13:18:12Z")

</div>

To add a new filter:

```auto
GSSidebarItem = objc.lookUpClass("GSSidebarItem")
font = Glyphs.font
filterController = font.fontView.glyphsGroupViewController()
glyphGroups = filterController.glyphGroups()
filters = glyphGroups[3]
print(filters)
newItem = GSSidebarItem.new()
newItem.setName_("MyListFilter1")
newItem.setCoverage_(["A", "B"])
newItem.setIconName_("CustomFilterListTemplate")
newItem.setItemType_(3)
filters.insertObject_inSubItemsAtIndex_(newItem, len(filters.subItems()))
filterController.didChangeSidebarItem_(filters)

```

And to temporarily change the sorting in Font view:

```auto
from AppKit import NSSortDescriptor
font = Glyphs.font
glyphsArrayController = font.fontView.glyphsArrayController()
glyphsArrayController.setSortDescriptors_([NSSortDescriptor.alloc().initWithKey_ascending_("layer0.LSB", True)])

```

And when you like to use a predefined list of names:

```auto
GSSortDescriptorNameList = objc.lookUpClass("GSSortDescriptorNameList")
font = Glyphs.font
glyphsArrayController = font.fontView.glyphsArrayController()
sortDescriptor = GSSortDescriptorNameList.alloc().initWithKey_ascending_("name", True)
sortDescriptor.setReferenceList_(["z", "y", "x"])
glyphsArrayController.setSortDescriptors_([sortDescriptor])

```

---

<div class="post-metadata">

**Author:** ![takaakifuji](https://forum.glyphsapp.com/letter_avatar_proxy/v4/letter/t/4bbf92/32.png) [@takaakifuji](https://forum.glyphsapp.com/u/takaakifuji)\
**Post date:** [October 21, 2021, 5:11pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/9 "2021-10-21T17:11:53Z")

</div>

Whoa. I can even set up a filter smarter than a smart filter:

```auto
newItem = GSSidebarItem.new()
newItem.setName_("MySmartFilter1")
newItem.setPredicate_(NSPredicate.predicateWithFormat_("""\
	NOT (name MATCHES '[A-Z].+')
	AND ((name CONTAINS 'acute') OR (name CONTAINS 'grave'))
	AND (export == 1)
	AND ((layer0.countOfPaths > 0) OR (layer0.countOfComponents > 0))
"""))
newItem.setIconName_('CustomFilterPredicateTemplate')
newItem.setItemType_(3)

```

This will be definitely a time saver for me. Thanks for the snippets!

---

<div class="post-metadata">

**Author:** ![aaronbell](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/aaronbell/32/12997_2.png) [@aaronbell](https://forum.glyphsapp.com/u/aaronbell)\
**Post date:** [November 18, 2021, 11:34pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/10 "2021-11-18T23:34:20Z")

</div>

> [@GeorgSeifert](#):
>
> ```auto
> GSSortDescriptorNameList = objc.lookUpClass("GSSortDescriptorNameList")
> font = Glyphs.font
> glyphsArrayController = font.fontView.glyphsArrayController()
> sortDescriptor = GSSortDescriptorNameList.alloc().initWithKey_ascending_("name", True)
> sortDescriptor.setReferenceList_(["z", "y", "x"])
> glyphsArrayController.setSortDescriptors_([sortDescriptor])
> 
> ```

I am trying to use this code to implement a temporarily change to the sorting in the Font view using a pre-defined list of names. I’m able to see the Font View change successfully, but after a second or two, it updates again and restores back to the standard view. This didn’t happen when I was running the plugin on Glyphs2, so that leads me to think this is something new in Glyphs3. Is there some way to prevent the fontview from updating again or to preserve the predefined sort for longer?

---

<div class="post-metadata">

**Author:** ![aaronbell](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/aaronbell/32/12997_2.png) [@aaronbell](https://forum.glyphsapp.com/u/aaronbell)\
**Post date:** [November 28, 2021, 4:57am UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/11 "2021-11-28T04:57:21Z")

</div>

Following up on this @GeorgSeifert. Any idea why this is happening?

---

<div class="post-metadata">

**Author:** ![GeorgSeifert](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/georgseifert/32/259_2.png) [@GeorgSeifert](https://forum.glyphsapp.com/u/GeorgSeifert)\
**Post date:** [November 28, 2021, 12:21pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/12 "2021-11-28T12:21:27Z")

</div>

I used the script and the sorting is still there even after I worked on the font for some time.

But any selection in the sidebar and adding/removing glyphs will most likely reset it.

---

<div class="post-metadata">

**Author:** ![aaronbell](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/aaronbell/32/12997_2.png) [@aaronbell](https://forum.glyphsapp.com/u/aaronbell)\
**Post date:** [November 30, 2021, 4:36pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/13 "2021-11-30T16:36:18Z")

</div>

Ah, thanks! It seems one of the instances of `Glyphs.font.fontView.glyphsGroupViewController().update()` in my script was being re-run for some reason, clearing the view.

---

<div class="post-metadata">

**Author:** ![TimAhrens](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/timahrens/32/4309_2.png) [@TimAhrens](https://forum.glyphsapp.com/u/TimAhrens)\
**Post date:** [December 17, 2024, 2:46pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/14 "2024-12-17T14:46:10Z")

</div>

I’m working on a Python-based filter using the technique described in this thread. I’d like the order of the subset of glyphs to be as it would be in unfiltered view. Is there a simple way to achieve this?

---

<div class="post-metadata">

**Author:** ![GeorgSeifert](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/georgseifert/32/259_2.png) [@GeorgSeifert](https://forum.glyphsapp.com/u/GeorgSeifert)\
**Post date:** [December 17, 2024, 3:37pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/15 "2024-12-17T15:37:40Z")

</div>

What exactly are you doing. A NSPredicate based filter should not alter the sorting. For list filters, you control the order yourself.

---

<div class="post-metadata">

**Author:** ![TimAhrens](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/timahrens/32/4309_2.png) [@TimAhrens](https://forum.glyphsapp.com/u/TimAhrens)\
**Post date:** [December 17, 2024, 4:34pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/16 "2024-12-17T16:34:09Z")

</div>

I am working on a filter that shows all glyphs not found (by name) in the other opened font (only works with exactly 2 fonts open).

This is what I have got so far:

```auto
#MenuTitle: Glyphset Diff
# encoding: utf-8

__doc__ ='''
Shows the glyphs that are not present in the other font.
'''

from GlyphsApp import *

if (len(Glyphs.documents) == 2):
	thisFont = Glyphs.currentDocument.font
	otherDocument = [doc for doc in Glyphs.documents if doc is not Glyphs.currentDocument][0]
	otherFont = otherDocument.font
	thisGlyphnames = set([glyph.name for glyph in thisFont.glyphs])
	otherGlyphnames = set([glyph.name for glyph in otherFont.glyphs])
	diff = list(thisGlyphnames - otherGlyphnames)
	# https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/7
	GSSortDescriptorNameList = objc.lookUpClass("GSSortDescriptorNameList")
	glyphsArrayController = thisFont.fontView.glyphsArrayController()
	sortDescriptor = GSSortDescriptorNameList.alloc().initWithKey_ascending_("name", True)
	sortDescriptor.setReferenceList_(diff)
	glyphsArrayController.setSortDescriptors_([sortDescriptor])
else:
	Message('Please make sure that\nexactly two fonts are open', '')

```

This works but the order is somewhat random. I’d like the order of the glyphs to be as it would be in unfiltered view.

---

<div class="post-metadata">

**Author:** ![GeorgSeifert](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/georgseifert/32/259_2.png) [@GeorgSeifert](https://forum.glyphsapp.com/u/GeorgSeifert)\
**Post date:** [December 17, 2024, 4:36pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/17 "2024-12-17T16:36:37Z")

</div>

You might not need that `GSSortDescriptorNameList` part.

And have you checked it `diff` is in the order you expect?

---

<div class="post-metadata">

**Author:** ![TimAhrens](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/timahrens/32/4309_2.png) [@TimAhrens](https://forum.glyphsapp.com/u/TimAhrens)\
**Post date:** [December 17, 2024, 5:31pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/18 "2024-12-17T17:31:04Z")

</div>

Oh, now I understand. It was the use of sets that jumbled the order!

I can simply use:

`	diff = [glyph.name for glyph in thisFont.glyphs if not glyph.name in otherGlyphnames]`

Just tried this and it gives me the desired order.

Seems like `GSfont.glyphs` always returns a nicely sorted list, or was I just lucky?

> [@GeorgSeifert](#):
>
> You might not need that `GSSortDescriptorNameList` part.

How would it work without a `GSSortDescriptorNameList`? Can it be simplified?

---

<div class="post-metadata">

**Author:** ![GeorgSeifert](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/georgseifert/32/259_2.png) [@GeorgSeifert](https://forum.glyphsapp.com/u/GeorgSeifert)\
**Post date:** [December 17, 2024, 8:57pm UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/19 "2024-12-17T20:57:48Z")

</div>

If you only set the filter, the underlying order should be preserved.

You were looking at the wrong sample code. It was about sorting, not filtering.

```auto
# MenuTitle: Glyphset Diff
# encoding: utf-8

__doc__ = '''
Shows the glyphs that are not present in the other font.
'''

from GlyphsApp import *

if len(Glyphs.documents) == 2:
	thisFont = Glyphs.documents[0].font
	otherFont = Glyphs.documents[1].font

	otherGlyphnames = set(otherFont.glyphNames())
	diff = [glyph for glyph in thisFont.glyphs if glyph.name not in otherGlyphnames]
	fontView = thisFont.fontView
	glyphsArrayController = fontView.glyphsArrayController()
	
	predicate = fontView.predicateForNameList_negative_(diff, False)
	glyphsArrayController.setFilterPredicate_(predicate)
else:
	Message('Please make sure that\nexactly two fonts are open', '')

```

---

<div class="post-metadata">

**Author:** ![oneweioranother](https://forum.glyphsapp.com/user_avatar/forum.glyphsapp.com/oneweioranother/32/273_2.png) [@oneweioranother](https://forum.glyphsapp.com/u/oneweioranother)\
**Post date:** [December 18, 2024, 3:48am UTC](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/20 "2024-12-18T03:48:16Z")

</div>

Ah this is the original reason why I asked about this API 😅

[Next page](https://forum.glyphsapp.com/t/create-list-filter-via-script/2134.md?page=2)
