David vs Goliath, or how to keep custom file associations after each Xcode update
Updating Xcode/macOS usually resets file type associations and requires reassigning default program for them to some other editor that is not as slow and inflexible as Xcode. I personally prefer Sublime Text and would really like Apple to stop constantly messing up my configuration.
lsregister
Using tips from the article lsregister: How Files Are Handled in Mac OS X we can automate assigning Sublime Text for files we need.
Let’s make a soft link to lsregister
for convenience:
1
ln -s /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister
We can now dump Launch Service database, but since it takes some time, let’s dump it to a text file first:
1
./lsregister -dump > lsregister.txt
Now, we can determine which programs are associated with specific file types:
1
cat lsregister.txt | grep -E 'bundle id:|claimed UTIs:'
and for Xcode specifically:
1
2
3
$ cat lsregister.txt | grep -E 'bundle id:|claimed UTIs:' | grep 'Xcode (' -A1
bundle id: Xcode (0x80c)
claimed UTIs: public.shell-script, public.bash-script, public.yaml, public.json, ...
In order to see what Uniform Type Identifier (UTI) corresponds to a given filename extension, we can use metadata list utility mdls
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ mdls Makefile
_kMDItemDisplayNameWithExtensions = "Makefile"
...
kMDItemContentType = "public.make-source"
kMDItemContentTypeTree = (
"public.make-source",
"public.script",
"public.source-code",
"public.plain-text",
"public.text",
"public.data",
"public.item",
"public.content"
)
...
or specifically for kMDItemContentType
:
1
2
$ mdls -name kMDItemContentType Makefile
kMDItemContentType = "public.make-source"
Unregister
The article also suggests that one can unregister Xcode, but it seems not possible anymore:
1
2
3
$ ./lsregister -u /Developer/Applications/Xcode.app
failed to scan /Developer/Applications/Xcode.app: -10814
from spotlight
defaults read
Since the article was published in 2012, the plist has been moved, so instead of old ~/Library/Preferences/com.apple.LaunchServices.plist
one should use ~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist
.
Let’s see what we have there:
1
2
3
4
5
6
7
8
9
10
11
$ defaults read ~/Library/Preferences/com.apple.LaunchServices/com.apple.LaunchServices.secure.plist
{
LSHandlers = (
{
LSHandlerPreferredVersions = {
LSHandlerRoleAll = "-";
};
LSHandlerRoleAll = "us.zoom.xos";
LSHandlerURLScheme = zoomphonecall;
},
...
defaults write
Let’s change default application for Makefile
:
1
2
3
4
5
6
7
8
9
$ defaults write com.apple.LaunchServices/com.apple.LaunchServices.secure LSHandlers \
-array-add '{LSHandlerContentType=public.make-source;LSHandlerRoleAll=com.sublimetext.4;}'
$ defaults read com.apple.LaunchServices/com.apple.LaunchServices.secure | tail -5
LSHandlerContentType = "public.make-source";
LSHandlerRoleAll = "com.sublimetext.4";
}
);
}
Now we have to restart macOS, since relaunching Finder and running the following command does not help:
1
./lsregister -kill -r -domain local -domain system -domain user
Test
The following commands should open Sublime Text instead of Xcode.
1
2
touch Makefile
open Makefile
Now we can make a script for opening all common files via our editor.
TBC