Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 22488c380a5dbea72812aa66cdfec673efaaf4e3 @AliSoftware committed Aug 27, 2012
Showing with 572 additions and 0 deletions.
  1. +15 −0 .gitignore
  2. +29 −0 LICENCE
  3. +48 −0 Plugins/Demo.xcpp
  4. +105 −0 Plugins/TemplateInfoStructDef.xcpp
  5. +92 −0 README.md
  6. +25 −0 Test Files/DemoTest.plist
  7. +38 −0 xcpc/xcpc
  8. +74 −0 xcpc/xcpcompiler.xslt
  9. +146 −0 xcpc/xcppreprocessor.xslt
@@ -0,0 +1,15 @@
+# Xcode
+build/*
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+*.xcworkspace
+!default.xcworkspace
+xcuserdata
+profile
+*.moved-aside
29 LICENCE
@@ -0,0 +1,29 @@
+/***********************************************************************************
+ *
+ * Copyright (c) 2012 Olivier Halligon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ ***********************************************************************************
+ *
+ * Any comment or suggestion welcome. Referencing this project in your AboutBox is appreciated.
+ * Please tell me if you use this class so we can cross-reference our projects.
+ *
+ ***********************************************************************************/
+
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin id="com.niji.dsquare.plist-plugin.demo"
+ name="Demo plist Structure Definition"
+ xmlns:xcpp="urn:X-AliSoftware:xcodeplugin:preprocessor">
+
+ <extension id="com.niji.dsquare.plist.structure-definition.demo"
+ name="Demo plist">
+
+ <filename pattern="Demo*.plist" />
+
+ <!-- "_root_" is the magic name of the top-level property list element -->
+ <definition name="_root_" localizedString="Demo Schema" class="Dictionary">
+ <dictionaryKeys>
+ <key name="Name" localizedString="Inventory Name" class="String" use="required"/>
+ <key name="Items" localizedString="Inventory Items" class="Inventory" use="required"/>
+ </dictionaryKeys>
+ </definition>
+
+ <definition name="Inventory" class="Array" arrayElementClass="InventoryItem">
+ <arrayEntries>
+ <entry class="BookTypeElement"/>
+ <entry class="MovieTypeElement"/>
+ </arrayEntries>
+ </definition>
+
+ <definition name="InventoryItem" class="VariantDictionary" default="BookTypeElement">
+ <xcpp:variants variantKey="Kind" localizedString="Inventory Item Kind">
+ <xcpp:variant variantValue="BookType" localizedString="Book" identifyingKey="Title">
+ <key name="Title" localizedString="Book Title" class="String" use="required"/>
+ <key name="Author" localizedString="Book Author" class="String" use="optional"/>
+ <key name="ReleaseDate" localizedString="First Release Date" class="Date" use="optional"/>
+ </xcpp:variant>
+ <xcpp:variant variantValue="MovieType" localizedString="Movie" identifyingKey="Title">
+ <key name="Title" localizedString="Movie Title" class="String" use="required"/>
+ <key name="Director" localizedString="Director" class="String" use="optional"/>
+ <key name="ReleaseDate" localizedString="Air Date" class="Date" use="optional"/>
+ </xcpp:variant>
+ <xcpp:variant variantValue="CarType" localizedString="Car" identifyingKey="License">
+ <key name="License" localizedString="License Plate" class="String" use="required"/>
+ <key name="Brand" localizedString="Car Brand" class="String" use="optional"/>
+ </xcpp:variant>
+ </xcpp:variants>
+ </definition>
+
+ </extension>
+</plugin>
+
@@ -0,0 +1,105 @@
+<plugin name="File Template Plist Structure Definition"
+ id="com.apple.xcode.plist-plugin.filetemplate"
+ version="1.0"
+ xmlns:xc="urn:X-AliSoftware:xcodeplugin:preprocessor">
+
+ <extension point="com.apple.xcode.plist.structure-definition"
+ id="com.niji.dsquare.plist.structure-definition.filetemplate" version="1.0"
+ name="File Template plist">
+
+ <filename pattern="TemplateInfo.plist" />
+
+ <!-- "_root_" is the magic name of the top-level property list element -->
+ <definition name="_root_" localizedString="Template Description" class="Dictionary">
+ <dictionaryKeys>
+ <key name="Kind" localizedString="Template Type" class="TemplateKind" use="required"/>
+ <key name="AllowedTypes" localizedString="Allowed UTI file types" class="AllowedUTITypesList" use="required"/>
+ <key name="DefaultCompletionName" localizedString="Default completion name" class="String" use="required"/>
+ <key name="Description" localizedString="Template Description" class="String" use="optional"/>
+ <key name="MainTemplateFile" localizedString="Main template file" class="String" default="__FILEBASENAME__.m" use="required" />
+ <key name="Options" localizedString="Options" class="OptionsList" use="optional" />
+ <key name="Platforms" localizedString="Supported platforms" class="PlatformsList" use="required" />
+ <key name="SortOrder" localizedString="Sort order" class="String" />
+ <key name="Summary" localizedString="Template Summary" class="String" use="optional" />
+ </dictionaryKeys>
+ </definition>
+
+ <!-- Template Kind -->
+ <definition name="TemplateKind" class="String">
+ <allowableValues>
+ <value name="Xcode.IDEKit.TextSubstitutionFileTemplateKind"
+ localizedString="File Template with Text Substitution" />
+ </allowableValues>
+ </definition>
+
+ <!-- Allowed Types -->
+ <definition name="AllowedUTITypesList" class="Array" arrayElementClass="AllowedUTITypesEntry">
+ <arrayEntries>
+ <entry class="AllowedUTITypesEntry" localizedString="Objective-C Source" />
+ </arrayEntries>
+ </definition>
+ <definition name="AllowedUTITypesEntry" class="String">
+ <allowableValues>
+ <value name="public.objective-c-source" localizedString="Objective-C Source" />
+ <value name="public.objective-c-plus-plus-source" localizedString="Objective-C++ Source" />
+ </allowableValues>
+ </definition>
+
+ <!-- Platform -->
+ <definition name="PlatformsList" class="Array" arrayElementClass="PlatformsEntry">
+ <arrayEntries>
+ <entry class="PlatformsEntry" localizedString="iPhone OS" />
+ </arrayEntries>
+ </definition>
+ <definition name="PlatformsEntry" class="String">
+ <allowableValues>
+ <value name="com.apple.platform.iphoneos" localizedString="iPhone OS" />
+ <value name="com.apple.platform.macosx" localizedString="Mac OS" />
+ </allowableValues>
+ </definition>
+
+
+
+
+ <!-- Options -->
+ <definition name="OptionsList" class="Array" arrayElementClass="OptionsEntry" />
+
+ <xc:define id="CommonOptionProperties">
+ <key name="Identifier" localizedString="Identifier" class="String" use="required"/>
+ <key name="Description" localizedString="Description" class="String" use="required"/>
+ <key name="Name" localizedString="Option Name / Label" class="String" use="required"/>
+ <key name="Default" localizedString="Default value" class="String" use="required"/>
+ <key name="RequiredOptions" localizedString="Required Options to enabled this option" class="RequiredOptionsType"/>
+ </xc:define>
+
+ <definition name="OptionsEntry" class="VariantDictionary" default="OptionsEntry_Text">
+ <xc:variants variantKey="Type" localizedString="Type">
+ <xc:variant variantValue="text" localizedString="Text Field" identifyingKey="Identifier">
+ <xc:paste idref="CommonOptionProperties" />
+ <key name="Required" localizedString="Is required" class="Boolean" use="optional"/>
+ <key name="NotPersisted" localizedString="Does not persist for next templates" class="Boolean" use="optional"/>
+ </xc:variant>
+ <xc:variant variantValue="class" localizedString="Class Popup" identifyingKey="Identifier">
+ <xc:paste idref="CommonOptionProperties" />
+ <key name="Required" localizedString="Is required" class="Boolean" use="required"/>
+ <key name="FallbackHeader" localizedString="Fallback Header to import" class="String" use="required"/>
+ <key name="Suffixes" localizedString="File name suffixes for known classes" class="DictionaryOfStrings" use="required"/>
+ <key name="Values" localizedString="Known classes with custom Template variants" class="ArrayOfStrings" use="required"/>
+ </xc:variant>
+ <xc:variant variantValue="checkbox" localizedString="Boolean Option" identifyingKey="Identifier">
+ <xc:paste idref="CommonOptionProperties" />
+ </xc:variant>
+ </xc:variants>
+ </definition>
+
+
+ <!-- Other Global Definitions -->
+ <definition name="RequiredOptionsType" localizedString="Required Options to enable this option" class="Dictionary">
+ <!-- For each option identifier required, associate an NSArray of values that will enable this option -->
+ </definition>
+ <definition name="DictionaryOfStrings" class="Dictionary"/>
+ <definition name="ArrayOfStrings" class="NSArray" arrayElementClass="String"/>
+
+ </extension>
+
+</plugin>
@@ -0,0 +1,92 @@
+XCPC : Xcode Plugin Compiler
+============================
+
+This tool is intended to generate Xcode 4.x plugins, in dvtplugin file format, especially
+to generate PLIST-file structure definitions.
+
+These PLIST-file structure definitions define some well-known PLIST files (like Info.plist or Settings.bundle/Root.plist)
+to make Xcode help you fill and edit these files, like:
+* associating Human-Readable names for dictionary keys (that's how Xcode display human-readable keys for your Info.plist files)
+* propose preformatted dictionary entries (that's how Xcode propose pre-formatted dicts in Settings.bundle/Root.plist files for the various kind of preferences entries (Text Field, ToggleSwitch...))
+* Validate your PLIST conformity with the expected structure
+
+
+## Generating your own PLIST structure definition files
+
+To generate your own PLIST structure definition files, you have to:
+* Prepare a XML file describing your PLIST expected structure. See [below](#xml-file-format).
+* Preprocess and compile this XML file to generate a dvtplugin file. Use the xcpc shell script for that,
+which will apply some XSLT stylesheet magic to the input XML file.
+
+The xcpc shell script command line usage is as follow:
+* Invoke `xcpc -xcodeplugin <inputFile>` to generate the output of the preprocessor to stdout. This will print the
+XML corresponding to the old ".xcodeplugin" file format for Xcode plugins (Xcode3 file format)
+* Invoke `xcpc -install <inputFile>` to generate the final ".dvtplugin" file (new Xcode4 file format) and make the script
+install it directly into "~/Library/Developer/Xcode/Plug-Ins" so that is will be available the next time you restart Xcode.
+
+## XML file format
+
+The XML file format expected by xcpc is basically the xcodeplugin file format used in Xcode3.
+xcpc will simply add:
+
+* Support for useful tags to simplify the input format, especially for VariantDictionary used to propose pre-filled
+dictionaries to your PLIST entries (like what is already done with the Settings.bundle/Info.plist files in Xcode to add
+PreferenceSpecifier entries for either Text Fields, Toggle Switches, Titles, Sliders, ...) without have to define a lot of
+repeatiting XML fragments; use `<xc:variant>` and `<xc:variant>` tags in your `<definition class="VariantDictionary">` nodes for that.
+* Support for "copy/pasting" XML fragments (like #define macros in C). The principle is to associate an id to some XML fragment
+so that you can "paste" it anywhere else in your XML without making a lot of copy/pasting. This is especially useful if you have
+a lot of common dictionary keys in your PLIST structure and don't want to repeat these key definitions everywhere.
+Use `<xc:define id="...">` and `<xc:paste idref="..." />` for that.
+
+The XML xcodeplugin file format is actually not documented by Apple so this is mainly guessing and introspection.
+The easiest way to discovery the syntax is to go and find inspiration in the existing xcodeplugin files
+present in "Xcode.app/Contents/PlugIns" and in the examples provided with this project (see "Plugins" directory).
+
+----
+
+Here is the generic structure anyway:
+
+ <plugin name="Your Plist Structure Definition"
+ id="com.yourcompany.plist-plugin.yourformat"
+ version="1.0"
+ xmlns:xc="urn:X-AliSoftware:xcodeplugin:preprocessor">
+
+ <extension point="com.apple.xcode.plist.structure-definition"
+ id="com.yourcompany.plist.structure-definition.yourformat" version="1.0"
+ name="Your plist">
+
+ <definition ...>
+ <definition ...>
+ ...
+
+ </extension>
+ </plugin>
+
+Each `<definition>` tag define a type with its name, and a "class" which can be a standard class like "String", "Boolean",
+"Dictionary", "Array" or "VariantDictionary", or any custom class whose definition is provided in another
+`<definition name="...">` tag in the same XML.
+
+Definitions of class "Array" can have an attribute "arrayElementClass" to define the class of the items in the array.
+They can also have a subnode `<arrayEntries>` that contains some default entries listed using `<entry>` tags.
+
+Definitions of class "String" can have a subnode `<allowableValues>` that contains a list of allowable values using `<value>` tags.
+
+Definitions of class "Dictionary" should have a subnode `<dictionaryKeys>` that list the allows keys in this dictionary.
+Each key is defined using a `<key name="..." localizedString="..." class="..." use="[optional|required]">` node.
+Class can be "*" to allow the user to select any class instead of forcing a strict type for the key.
+
+As VariantDictionary are quite more complex to define, the tags `<xc:variants>` and `<xc:variant>` can be
+used. They will be and preprocessed by the xcppreprocessor.xslt stylesheet to generate the appropriate
+`<variants>` and `<variant>` tags, but also all associated definitions, and all allowableValues for the
+variantKey in each case automatically. See examples for inspiration.
+
+
+## Usage in Xcode
+
+Once you have compiled your own dvtplugin to describe your custom PLIST structure and it has been installed into
+"~/Library/Developer/Xcode/Plug-Ins", simply open any PLIST file in Xcode.
+
+Then if your plist is not recognized automatically to be of the expected structure
+(which could be done by filename matching using the <filename pattern="..." /> tags in your source XML),
+simply right-click anywhere of your PLIST and select the appropriate entry in the "Property List Type"
+submenu _(You should find your custom type here)_.
@@ -0,0 +1,25 @@
+<?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>Name</key>
+ <string>Some test</string>
+ <key>Items</key>
+ <array>
+ <dict>
+ <key>Kind</key>
+ <string>BookType</string>
+ <key>Title</key>
+ <string>Peter Pan</string>
+ <key>Author</key>
+ <string>Riesling</string>
+ </dict>
+ <dict>
+ <key>Kind</key>
+ <string>CarType</string>
+ <key>License</key>
+ <string>1234 ABC 35</string>
+ </dict>
+ </array>
+</dict>
+</plist>
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+if [ "$1" = "-install" ]; then
+ doInstall=1
+ mkdir -p "${outputDir}"
+ shift
+elif [ "$1" = "-xcodeplugin" ]; then
+ onlyPreprocess=1
+ shift
+fi
+if [ "${1:0:1}" = "-" -o ! -n "$1" ]; then
+ # Remaining argument starts with "-" or is empty
+ echo "Usage: xcpc [-install|-xcodeplugin] inputFile"
+ exit 1
+fi
+
+inputFile=$1
+if [ $doInstall ]; then
+ outputFile=~/Library/Developer/Xcode/Plug-Ins/$(basename $inputFile .xcpp).dvtplugin
+else
+ outputFile=/dev/stdout
+fi
+xsltDir=$(dirname $0)
+
+if [ $onlyPreprocess ]; then
+ /usr/bin/xsltproc "${xsltDir}/xcppreprocessor.xslt" "${inputFile}"
+ if [ $? -ne 0 ]; then
+ echo "Failed to preprocess plugin source."
+ fi
+else
+ cat "${inputFile}" | /usr/bin/xsltproc "${xsltDir}/xcppreprocessor.xslt" - | /usr/bin/xsltproc "${xsltDir}/xcpcompiler.xslt" - >"${outputFile}"
+ if [ $? -eq 0 ]; then
+ echo "Plugin generated to: ${outputFile}. Please restart Xcode."
+ else
+ echo "Failed to generate plugin."
+ fi
+fi
+
Oops, something went wrong.

0 comments on commit 22488c3

Please sign in to comment.