Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is the one I came up with based on one I found a long time ago, rewritten in Python and with the improvements that it can generate multiple properties at once, among other things.</p> <p>It will generate properties for all selected instance variable using (copy) as the attribute. </p> <p>There are still some edge cases with multiple @interfaces or @implementations in a file, as well as some with unusual identifiers or asterisk placement (as in *const), but it should cover most typical coding styles. Feel free to edit/post modifications if you fix any of these cases.</p> <pre><code>#!/usr/bin/python # Takes a header file with one or more instance variables selected # and creates properties and synthesize directives for the selected properties. # Accepts google-style instance variables with a tailing underscore and # creates an appropriately named property without underscore. # Entire Document # Home Directory # Discard Output # Display in Alert import os import re import subprocess # AppleScripts for altering contents of files via Xcode setFileContentsScript = """\ on run argv set fileAlias to POSIX file (item 1 of argv) set newDocText to (item 2 of argv) tell application "Xcode" set doc to open fileAlias set text of doc to newDocText end tell end run \ """ getFileContentsScript = """\ on run argv set fileAlias to POSIX file (item 1 of argv) tell application "Xcode" set doc to open fileAlias set docText to text of doc end tell return docText end run \ """ # Get variables from Xcode headerFileText = """%%%{PBXAllText}%%%""" selectionStartIndex = %%%{PBXSelectionStart}%%% selectionEndIndex = %%%{PBXSelectionEnd}%%% selectedText = headerFileText[selectionStartIndex:selectionEndIndex] headerFilePath = """%%%{PBXFilePath}%%%""" # Look for an implementation file with .m or .mm extension implementationFilePath = headerFilePath[:-1] + "m" if not os.path.exists(implementationFilePath): implementationFilePath += "m" instanceVariablesRegex = re.compile( """^\s*((?:(?:\w+)\s+)*(?:(?:\w+)))""" + # Identifier(s) """([*]?)\\s*""" + # An optional asterisk """(\\w+?)(_?);""", # The variable name re.M) # Now for each instance variable in the selected section properties = "" synthesizes = "" for lineMatch in instanceVariablesRegex.findall(selectedText): types = " ".join(lineMatch[0].split()) # Clean up consequtive whitespace asterisk = lineMatch[1] variableName = lineMatch[2] trailingUnderscore = lineMatch[3] pointerPropertyAttributes = "(copy) " # Attributes if variable is pointer if not asterisk: pointerPropertyAttributes = "" newProperty = "@property %s%s %s%s;\n" % (pointerPropertyAttributes, types, asterisk, variableName) # If there's a trailing underscore, we need to let the synthesize # know which backing variable it's using newSynthesize = "@synthesize %s%s;\n" % (variableName, trailingUnderscore and " = %s_" % variableName) properties += newProperty synthesizes += newSynthesize # Check to make sure at least 1 properties was found to generate if not properties: os.sys.stderr.writelines("No properties found to generate") exit(-1) # We want to insert the new properties either immediately after the last # existing property or at the end of the instance variable section findLastPropertyRegex = re.compile("^@interface.*?{.*?}.*?\\n" + "(?:.*^\\s*@property.*?\\n)?", re.M | re.S) headerInsertIndex = findLastPropertyRegex.search(headerFileText).end() # Add new lines on either side if this is the only property in the file addedNewLine = "\n" if re.search("^\s*@property", headerFileText, re.M): # Not the only property, don't add addedNewLine = "" newHeaderFileText = "%s%s%s%s" % (headerFileText[:headerInsertIndex], addedNewLine, properties, headerFileText[headerInsertIndex:]) subprocess.call(["osascript", "-e", setFileContentsScript, headerFilePath, newHeaderFileText]) if not os.path.exists(implementationFilePath): os.sys.stdout.writelines("No implementation file found") exit(0) implementationFileText = subprocess.Popen( ["osascript", "-e", getFileContentsScript, implementationFilePath], stdout=subprocess.PIPE).communicate()[0] # We want to insert the synthesizes either immediately after the last existing # @synthesize or after the @implementation directive lastSynthesizeRegex = re.compile("^\\s*@implementation.*?\\n" + "(?:.*^\\s*@synthesize.*?\\n)?", re.M | re.S) implementationInsertIndex = \ lastSynthesizeRegex.search(implementationFileText).end() # Add new lines on either side if this is the only synthesize in the file addedNewLine = "\n" if re.search("^\s*@synthesize", implementationFileText, re.M): # Not the only synthesize, don't add addedNewLine = "" newImplementationFileText = "%s%s%s%s" % \ (implementationFileText[:implementationInsertIndex], addedNewLine, synthesizes, implementationFileText[implementationInsertIndex:]) subprocess.call(["osascript", "-e", setFileContentsScript, implementationFilePath, newImplementationFileText]) # Switch Xcode back to header file subprocess.Popen(["osascript", "-e", getFileContentsScript, headerFilePath], stdout=subprocess.PIPE).communicate() </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload