Skip to content

Docklib is too dependent upon labels, which makes it difficult to write language-independent dock scripts #32

Closed
@homebysix

Description

@homebysix

Problem

I'm using docklib to configure the dock upon login after end users walk through the macOS Setup Assistant. In order to make my script idempotent, I'm searching for existing dock items in order to dynamically determine whether the dock requires customization. Some of the items I'm searching for are Apple default apps: Notes, Messages, Music, Reminders, etc.

This works fine as long as the user has selected English as their preferred language. However, when another language is selected, the Dock item labels are localized in that language — e.g. Notas, Mensajes, Música, Recordatorios — and my script fails.

image

My workaround has been to use the _CFURLString of the dock items for the basis of comparison, since the apps' path on disk is not affected by localization. However, docklib doesn't make this easy for me, since its current functions are focused on finding, removing, and replacing items based on file-label.

Proposed Solution

I would propose making a new findExistingEntry function that allows finding items by either label (default), path, or basename:

    def findExistingEntry(self, search_str, by="label", section="persistent-apps"):
        section_items = self.items[section]
        if section_items:
            for index, item in enumerate(section_items):
                urlstring = unquote(
                    item["tile-data"].get("file-data", {}).get("_CFURLString", "")
                )
                if by == "label":
                    # Most dock items use "file-label", but URLs use "label"
                    for label_key in ("file-label", "label"):
                        if item["tile-data"].get(label_key) == search_str:
                            return index
                elif by == "path" and urlstring:
                    if urlparse(urlstring.rstrip("/")).path == search_str:
                        return index
                elif by == "basename" and urlstring:
                    if (
                        os.path.basename(urlparse(urlstring.rstrip("/")).path)
                        == search_str
                    ):
                        return index

        return -1

And modifying the findExistingLabel function to serve as a pointer to the new function:

    def findExistingLabel(self, test_label, section="persistent-apps"):
        return self.findExistingEntry(test_label, by="label", section=section)

I’m still thinking about how removeDockEntry, replaceDockEntry, and other label-centric functions should be adapted. Open to feedback if anybody has strong opinions.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions