Editor or way to print plist in a clean way without Xcode - xcode

I need to share information from a plist with someone who is not technically inclined. Is there a common free editor that one can use to view plist info in a similar way in which it is presented in Xcode? Or is there a way to print it out?
In other words I would like to view the plist without all the xml-like mark up and without the use of Xcode.

Command-line options for viewing Plist files:
For viewing only: Use plutil -p, which prints the content of a property-list in JSON-like format (the format is meant for human consumption only).
Example (append | open -tf to view output in a text editor):
plutil -p ~/Library/Preferences/com.apple.sidebarlists.plist
Alternative: Use /usr/libexec/PlistBuddy -c print, which outputs in JavaScript-object-literal-like format:
Example:
/usr/libexec/PlistBuddy -c print ~/Library/Preferences/com.apple.airplay.plist
Caveat:
If the plist has properties containing binary data, PlistBuddy will include it in raw form (by contrast, non-binary properties in the same file are printed properly). If XML output is desired, add option -x.
Note that PlistBuddy:
can be used to extract properties selectively using :-separated, case-sensitive property paths; e.g., /usr/libexec/PlistBuddy -c 'print :favorites:ShowRemovable' ~/Library/Preferences/com.apple.sidebarlists.plist
is also capable of modifying Plist files from the command line (including, with limitations, importing from previously exported-to XML files).
See /usr/libexec/PlistBuddy -h for details.

The standalone "Property List Editor" is gone since Xcode 4, you can use Pref Setter which is free but last updated 4 years ago.
To save the contents without the xml tags see this example:
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:[#"~/Library/Preferences/loginwindow.plist" stringByExpandingTildeInPath]];
[[dict description] writeToURL:[NSURL fileURLWithPath:[#"~/Desktop/loginwindow.txt" stringByExpandingTildeInPath]] atomically:YES encoding:NSUTF8StringEncoding error:nil];

You can use visual studio code to open and edit Plist files.
Just need to install an extension in the visual studio code called Binary Plist:
Binary Plist
Publisher: David Nicolson
Marketplace Link: https://marketplace.visualstudio.com/items?itemName=dnicolson.binary-plist

There is a way to get the old Property List Editor working on Mac OS X Lion, if you don't want to use bloated XCode 4 for this.

There is a "Property List Editor" app as part of OS X (or there used to be, I'm away from my machine at the moment so can't check).
Failing that, you could write one in about half an hour!

Related

File.read "[Invalid encoding]" in ruby

I want to read content of file in ruby
The following code works fine for most of files I tried, But for one of them fails to read the file due to invalid encoding problem.
The file contains xml string (is a plist file)
content_of_file = File.read(#path_to_file)
Also
content_of_file = File.read(#path_to_file, :encoding => 'utf-8')
How to fix this issue ?
Answer : https://apple.stackexchange.com/questions/101719/trouble-opening-plist-files-in-text-editor
plist files are not necessarily plain text so they need to be run through a converter. Finder and Xcode (which has a plist editor) do this without telling the user
The binary format is documented in this C code so any application can convert it and someone has written a format description in English and more Apple documentation here but note that it references old paths in /Developer/Documentation
The command line program plutil can convert to and from XML
e.g. to view a binary property list in XML format on stdout:
plutil -convert xml1 -o - <file name>
Also to convert a binary to a XML plist in place and then leave it so that the user program can read either.
plutil -convert xml1 <file name>

Export app for localization not including strings created with NSLocalizedString in Xcode 6 Xliff

I'm trying to localize my app, and I have the following code:
self.arrayLabels = [NSArray arrayWithObjects:NSLocalizedString(#"This is a test", "this is a test"), NSLocalizedString(#"I want my strings to get added to localizable strings file", "strings comment") , nil];
So, basically, from what I understand, this should be it, I click Editor > Export for Localization and the strings should be there on my XLiff file. But, they aren't.
I have two languages, english and portuguese, both localizable.strings files are empty.
Am I missing something?
I discovered that I had a few errors and that is why I could not export from the menu.
I suspect that the error messages are not being returned.
It turns out that the menu is calling existing command line tools so by a process of elimination you may be able to fix your export.
Here are the steps I took to fix my issues. Hopefully they will help you.
Run the command line equivalent
xcodebuild -exportLocalizations
If you have errors xcodebuild may give file names and line numbers so you should be able to fix the issues.
I had one error that did not have any details.
I then switched to using genstrings as that is what xcodebuild appears to be using in a loop.
find . -name '*.m' | xargs genstrings -o somePath/en.lproj
this gave the same error
To get the file with the problem I ran each file separately in a loop.
for f in `find . -name '*.m'`; do
echo "processing $f ...";
genstrings -o somePath/en.lproj $f
done
That gave me the name of the file that had an issue.
It turned out that genstrings did not like a special character I was trying to print using a unicode character \U000000B2.
For the exported XLIFF to contain your localized strings, a few conditions have to be met:
The keys must be present in your localized strings file. In your case these files are empty. Which will explain the problem.
You must use the keys as string literal with the NSLocalizedString macro. For example:
This is the correct way:
NSLocalizedString("some_key", "")
This will not work:
let key = "some_key"
NSLocalizedString(key, "")
In Xcode, use the Editor-->"Extract for Localization" menu which will generate the .xliff files (one per language selected). The .xliff files are sent to a translation service for translation. Once the .xliff files are updated by the translation service, you need to import it back into the app using Editor-->"Import Localizations". Once this step is done, for each language, you will find a xx.lproj/ folder with the results of the translation.

xcode 5 localize storyboard with script delete *.strings file?

sorry to make another bother.
I'm implement an app, with localization of English and Japanese in xcode 5, using the script file created by André Pinto, based on SIngle Storyboard for multiple languages. Well, before upgrade to xcode 5 (xcode 4.6, I mean), things work properly. But since xcode 5, this error occurs when run the script file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.ibtool.errors</key>
<array>
<dict>
<key>description</key>
<string>Interface Builder could not open the document "xx.storyboard" because it does not exist.</string>
</dict>
</array>
</dict>
</plist>
Iconv: ./xx/Base.lproj/xx.strings.new: No such file or directory
Rm: ./xx/Base.lproj/xx.strings.new: No such file or directory
Merging xx.strings changes for en.lproj...
Merging xx.strings changes for ja.lproj...
Command /bin/sh emitted errors but did not return a nonzero exit code to indicate failure
In the storyboard, there are 2 sub-files: xx.storyboard(Base) and xx.storyboard(Japanese)
In the first build, no error occur. Everything went fine. App localize so good.
In the second build, I made somechange in storyboard (add some new feature), then error occur. Also, the xx.storyboard(Japanese) become blank, and this is weird. I put lots of effort translate those things, and now I have to do it again...
I think there's some problem with the script, the strings.new and strings.old...
Here's the script:
#!/bin/sh
# Update storyboard string files
#
# by 2013 André Pinto andredsp#gmail.com
# based on http://forums.macrumors.com/showthread.php?t=1467446
storyboardExt=".storyboard"
stringsExt=".strings"
newStringsExt=".strings.new"
oldStringsExt=".strings.old"
localeDirExt=".lproj"
baselprojName="Base.lproj"
# Find Base internationalization folders
find . -name "$baselprojName" | while read baselprojPath
do
# Get Base project dir
baselprojDir=$(dirname "$baselprojPath")
# Find storyboard file full path inside base project folder
find "$baselprojPath" -name "*$storyboardExt" | while read storyboardPath
do
# Get Base strings file full path
baseStringsPath=$(echo "$storyboardPath" | sed "s/$storyboardExt/$stringsExt/")
# Get storyboard file name and folder
storyboardFile=$(basename "$storyboardPath")
storyboardDir=$(dirname "$storyboardPath")
# Create strings file only when storyboard file newer
newer=$(find "$storyboardPath" -prune -newer "$baseStringsPath")
[ -f "$baseStringsPath" -a -z "$newer" ] && {
echo "$storyboardFile file not modified."
continue
}
# Get New Base strings file full path and strings file name
newBaseStringsPath=$(echo "$storyboardPath" | sed "s/$storyboardExt/$newStringsExt/")
stringsFile=$(basename "$baseStringsPath")
echo "Creating default $stringsFile for $storyboardFile..."
ibtool --export-strings-file "$newBaseStringsPath" "$storyboardPath"
iconv -f UTF-16 -t UTF-8 "$newBaseStringsPath" > "$baseStringsPath"
rm "$newBaseStringsPath"
# Get all locale strings folder with same parent as Base
ls -d "$baselprojDir/"*"$localeDirExt" | while read localeStringsDir
do
# Skip Base strings folder
[ "$localeStringsDir" = "$storyboardDir" ] && continue
localeDir=$(basename "$localeStringsDir")
localeStringsPath="$localeStringsDir/$stringsFile"
# Just copy base strings file on first time
if [ ! -e "$localeStringsPath" ]; then
echo "Copying default $stringsFile for $localeDir..."
cp "$baseStringsPath" "$localeStringsPath"
else
echo "Merging $stringsFile changes for $localeDir..."
oldLocaleStringsPath=$(echo "$localeStringsPath" | sed "s/$stringsExt/$oldStringsExt/")
cp "$localeStringsPath" "$oldLocaleStringsPath"
# Merge baseStringsPath to localeStringsPath
awk '
NR == FNR && /^\/\*/ {
x=$0
getline
a[x]=$0
next
}
/^\/\*/ {
x=$0
print
getline
$0=a[x]?a[x]:$0
printf $0"\n\n"
}' "$oldLocaleStringsPath" "$baseStringsPath" > "$localeStringsPath"
rm "$oldLocaleStringsPath"
fi
done
done
done
Localizable.strings and InfoPlist.strings are still good.
Anyone has experience with this kind of things help me please... Is that something with xcode, or script file or xx.strings file? I don't get it...
I may ask it directly the script's creator, but I think post the question here will be better. I'm a SO lover :)
I was using same script as you, and had the same issues as you. Then I found these articles from AppliedIS, detailing their process of I18n and L10n. They used an updated version of this script that seems to be slightly more robust.
They also have a script for extracting keys from NSLocalizedString statements and generate Localizable.strings for every locale as well. This script uses the comment as the value when generating the new entries, which is quite clever.
I have switched to these now, and it seems faster (that might be just me; ooh, new == faster), has more output (nice for debugging) and it also works without the Run script only when installing.
Check it out! (I'm not associated with them in any way, just a happy user)
I think this is the solution:
go to xx.xcodeproj-> Target-> Build phases-> Run Script-> Tick on "Run script only when installing"
I don't know how, why but this seems to solve the problem... I think because the script run when install on ios simulator, so when I build, it can't find the xx.storyboard...
Any other answers are still welcome. I still can't satisfy with this one, because there's no guarantee with this solution.
I believe localization only occurs during the install of an app. Therefore your workaround has every reason to work since the script deals with localizing resources. Please note that many things in localization have changed and it would be worthwhile to review the linked internationalization guide located on the Apple developer website. The link contains specific videos and programming topics that provider further explanations. Some things worth considering is that you should use Autolayout if you only plan on using a single view controller. This will ensure your translations size correctly in each language.

How to get HTML data out of of the OS X pasteboard / clipboard?

I do have to send a report regarding pasting some clipboard content into a web rich editor and I need a way to dump/restore the clipboard content to (probably) HTML.
How can I do this?
It seems that pbcopy / pbpaste do alway give me text even if I use the pbpaste -P rtf or pbpaste -P HTML
Three years later, in more civilized times, we have Swift. You can write a short Swift script to pull exactly what you need off of OS X's pasteboard.
Put the following Swift 4 snippet into a new text file. I named mine pbpaste.swift:
import Cocoa
let type = NSPasteboard.PasteboardType.html
if let string = NSPasteboard.general.string(forType:type) {
print(string)
}
else {
print("Could not find string data of type '\(type)' on the system pasteboard")
exit(1)
}
Then, copy some html, and run swift pbpaste.swift from the directory where you put that file.
Yay, html! Uggh, OS X added a ton of custom markup (and a <meta> tag?!) — but hey, at least it's not plain text!
Notes:
NSPasteboard.PasteboardType.html is a special global that evaluates to the string "public.html"
Obviously this is html specific, so you'd probably want to either:
Name it pbpaste-html.swift, or
Read the desired type from the command line arguments
It's kind of slow, because it's being interpreted on the fly, not compiled and executed. Compilation gives me a 10x speed-up:
xcrun -sdk macosx swiftc pbpaste.swift -o pbpaste-html
Then just call ./pbpaste-html instead of swift pbpaste.swift.
I realise you've already found this, but for the benefit of people who turn up here from Google, the solution given for RTF data at Getting RTF data out of Mac OS X pasteboard (clipboard) works fine for getting HTML out of the clipboard, too.
That is, the command
osascript -e 'the clipboard as «class HTML»' | perl -ne 'print chr foreach unpack("C*",pack("H*",substr($_,11,-3)))'

Programming a Filter/Backend to 'Print to PDF' with CUPS from any Mac OS X application

Okay so here is what I want to do. I want to add a print option that prints whatever the user's document is to a PDF and adds some headers before sending it off to a device.
I guess my questions are: how do I add a virtual "printer" driver for the user that will launch the application I've been developing that will make the PDF (or make the PDF and launch my application with references to the newly generated PDF)? How do I interface with CUPS to generate the PDF? I'm not sure I'm being clear, so let me know if more information would be helpful.
I've worked through this printing with CUPS tutorial and seem to get everything set up okay, but the file never seems to appear in the appropriate temporary location. And if anyone is looking for a user-end PDF-printer, this cups-pdf-for-mac-os-x is one that works through the installer, however I have the same issue of no file appearing in the indicated directory when I download the source and follow the instructions in the readme. If anyone can get either of these to work on a mac through the terminal, please let me know step-by-step how you did it.
The way to go is this:
Set up a print queue with any driver you like. But I recommend to use a PostScript driver/PPD. (A PostScript PPD is one which does not contain any *cupsFilter: ... line.):
Initially, use the (educational) CUPS backend named 2dir. That one can be copied from this website: KDE Printing Developer Tools Wiki. Make sure when copying that you get the line endings right (Unix-like).
Commandline to set up the initial queue:
lpadmin \
-p pdfqueue \
-v 2dir:/tmp/pdfqueue \
-E \
-P /path/to/postscript-printer.ppd
The 2dir backend now will write all output to directory /tmp/pdfqueue/ and it will use a uniq name for each job. Each result should for now be a PostScript file. (with none of the modifications you want yet).
Locate the PPD used by this queue in /etc/cups/ppd/ (its name should be pdfqueue.ppd).
Add the following line (best, near the top of the PPD):
*cupsFilter: "application/pdf 0 -" (Make sure the *cupsFilter starts at the very beginning of the line.) This line tells cupsd to auto-setup a filtering chain that produces PDF and then call the last filter named '-' before it sends the file via a backend to a printer. That '-' filter is a special one: it does nothing, it is a passthrough filter.
Re-start the CUPS scheduler:sudo launchctl unload /System/Library/LaunchDaemons/org.cups.cupsd.plist
sudo launchctl load /System/Library/LaunchDaemons/org.cups.cupsd.plist
From now on your pdfqueue will cause each job printed to it to end up as PDF in /tmp/pdfqueue/*.pdf.
Study the 2dir backend script. It's simple Bash, and reasonably well commented.
Modify the 2dir in a way that adds your desired modifications to your PDF before saving on the result in /tmp/pdfqueue/*.pdf...
Update: Looks like I forgot 2 quotes in my originally prescribed *cupsFilter: ... line above. Sorry!
I really wish I could accept two answers because I don't think I could have done this without all of #Kurt Pfeifle 's help for Mac specifics and just understanding printer drivers and locations of files. But here's what I did:
Download the source code from codepoet cups-pdf-for-mac-os-x. (For non-macs, you can look at http://www.cups-pdf.de/) The readme is greatly detailed and if you read all of the instructions carefully, it will work, however I had a little trouble getting all the pieces, so I will outline exactly what I did in the hopes of saving someone else some trouble. For this, the directory with the source code is called "cups-pdfdownloaddir".
Compile cups-pdf.c contained in the src folder as the readme specifies:
gcc -09 -s -lcups -o cups-pdf cups-pdf.c
There may be a warning: ld: warning: option -s is obsolete and being ignored, but this posed no issue for me. Copy the binary into /usr/libexec/cups/backend. You will likely have to the sudo command, which will prompt you for your password. For example:
sudo cp /cups-pdfdownloaddir/src/cups-pdf /usr/libexec/cups/backend
Also, don't forget to change the permissions on this file--it needs root permissions (700) which can be changed with the following after moving cupd-pdf into the backend directory:
sudo chmod 700 /usr/libexec/cups/backend/cups-pdf
Edit the file contained in /cups-pdfdownloaddir/extra/cups-pdf.conf. Under the "PDF Conversion Settings" header, find a line under the GhostScript that reads #GhostScript /usr/bin/gs. I did not uncomment it in case I needed it, but simply added beneath it the line Ghostscript /usr/bin/pstopdf. (There should be no pre-cursor # for any of these modifications)
Find the line under GSCall that reads #GSCall %s -q -dCompatibilityLevel=%s -dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite -sOutputFile="%s" -dAutoRotatePage\
s=/PageByPage -dAutoFilterColorImages=false -dColorImageFilter=/FlateEncode -dPDFSETTINGS=/prepress -c .setpdfwrite \
-f %s Again without uncommenting this, under this I added the line GSCall %s %s -o %s %s
Find the line under PDFVer that reads #PDFVer 1.4 and change it to PDFVer, no spaces or following characters.
Now save and exit editing before copying this file to /etc/cups with the following command
sudo cp cups-pdfdownloaddir/extra/cups-pdf.conf /etc/cups
Be careful of editing in a text editor because newlines in UNIX and Mac environments are different and can potentially ruin scripts. You can always use a perl command to remove them, but I'm paranoid and prefer not to deal with it in the first place.
You should now be able to open a program (e.g. Word, Excel, ...) and select File >> Print and find an available printer called CUPS-PDF. Print to this printer, and you should find your pdfs in /var/spool/cups-pdf/yourusername/ by default.
*Also, I figured this might be helpful because it helped me: if something gets screwed up in following these directions and you need to start over/get rid of it, in order to remove the driver you need to (1) remove the cups-pdf backend from /usr/libexec/cups/backend (2) remove the cups-pdf.conf from /etc/cups/ (3) Go into System Preferences >> Print & Fax and delete the CUPS-PDF printer.
This is how I successfully set up a pdf backend/filter for myself, however there are more details, and other information on customization contained in the readme file. Hope this helps someone else!

Resources