2009-06-23 23 views

Trả lời

4

Tôi đã tạo ba cho số JSON.Framework for Cocoa and the iPhone. Những chăm sóc những điều sau đây:.

  • Tạo một hình ảnh phát hành đĩa với khung nhúng năng động, tùy chỉnh iPhone SDK, tài liệu API và một số file tài liệu trong
  • Run Doxygen qua nguồn để tạo ra một tài liệu Xcode tương thích thiết lập và cài đặt nó. Điều này có nghĩa là khi bạn tìm kiếm những thứ trong tài liệu của Xcode, bạn cũng có thể tìm thấy tài liệu của mình.
  • Chạy Doxygen trên nguồn để cập nhật phiên bản đã đăng ký của tài liệu API trong chính cây nguồn. Điều này là khá gọn gàng nếu bạn sử dụng Subversion (mà nó giả định) vì tài liệu luôn được cập nhật cho chi nhánh bạn đang ở. Tuyệt vời nếu bạn đang lưu trữ trên Google Code chẳng hạn.

Hãy coi chừng một số giá trị theo dự án được mã hóa cứng ở bên dưới. Tôi không muốn có khả năng phá vỡ các kịch bản bằng cách chỉnh sửa chúng. Chúng được khởi chạy từ Giai đoạn tập lệnh tùy chỉnh trong Xcode. Bạn có thể xem cách chúng được tích hợp trong dự án Xcode cho dự án được liên kết ở trên.

CreateDiskImage.sh:

#!/bin/sh 

set -x 

# Determine the project name and version 
VERS=$(agvtool mvers -terse1) 

# Derived names 
VOLNAME=${PROJECT}_${VERS} 
DISK_IMAGE=$BUILD_DIR/$VOLNAME 
DISK_IMAGE_FILE=$INSTALL_DIR/$VOLNAME.dmg 

# Remove old targets 
rm -f $DISK_IMAGE_FILE 
test -d $DISK_IMAGE && chmod -R +w $DISK_IMAGE && rm -rf $DISK_IMAGE 
mkdir -p $DISK_IMAGE 

# Create the Embedded framework and copy it to the disk image. 
xcodebuild -target JSON -configuration Release install || exit 1 
cp -p -R $INSTALL_DIR/../Frameworks/$PROJECT.framework $DISK_IMAGE 

IPHONE_SDK=2.2.1 

# Create the iPhone SDK directly in the disk image folder. 
xcodebuild -target libjson -configuration Release -sdk iphoneos$IPHONE_SDK install \ 
    ARCHS=armv6 \ 
    DSTROOT=$DISK_IMAGE/SDKs/JSON/iphoneos.sdk || exit 1 
sed -e "s/%PROJECT%/$PROJECT/g" \ 
    -e "s/%VERS%/$VERS/g" \ 
    -e "s/%IPHONE_SDK%/$IPHONE_SDK/g" \ 
    $SOURCE_ROOT/Resources/iphoneos.sdk/SDKSettings.plist > $DISK_IMAGE/SDKs/JSON/iphoneos.sdk/SDKSettings.plist || exit 1 

xcodebuild -target libjson -configuration Release -sdk iphonesimulator$IPHONE_SDK install \ 
    ARCHS=i386 \ 
    DSTROOT=$DISK_IMAGE/SDKs/JSON/iphonesimulator.sdk || exit 1 
sed -e "s/%PROJECT%/$PROJECT/g" \ 
    -e "s/%VERS%/$VERS/g" \ 
    -e "s/%IPHONE_SDK%/$IPHONE_SDK/g" \ 
    $SOURCE_ROOT/Resources/iphonesimulator.sdk/SDKSettings.plist > $DISK_IMAGE/SDKs/JSON/iphonesimulator.sdk/SDKSettings.plist || exit 1  

# Allow linking statically into normal OS X apps 
xcodebuild -target libjson -configuration Release -sdk macosx10.5 install \ 
    DSTROOT=$DISK_IMAGE/SDKs/JSON/macosx.sdk || exit 1 

# Copy the source verbatim into the disk image. 
cp -p -R $SOURCE_ROOT/Source $DISK_IMAGE/$PROJECT 
rm -rf $DISK_IMAGE/$PROJECT/.svn 

# Create the documentation 
xcodebuild -target Documentation -configuration Release install || exit 1 
cp -p -R $INSTALL_DIR/Documentation/html $DISK_IMAGE/Documentation 
rm -rf $DISK_IMAGE/Documentation/.svn 

cat <<HTML > $DISK_IMAGE/Documentation.html 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> 
<script type="text/javascript"> 
<!-- 
window.location = "Documentation/index.html" 
//--> 
</script> 
</head> 
<body> 
<p>Aw, shucks! I tried to redirect you to the <a href="Documentaton/index.html">api documentation</a> but obviously failed. Please find it yourself. </p> 
</body> 
</html> 
HTML 

cp -p $SOURCE_ROOT/README $DISK_IMAGE 
cp -p $SOURCE_ROOT/Credits.rtf $DISK_IMAGE 
cp -p $SOURCE_ROOT/Install.rtf $DISK_IMAGE 
cp -p $SOURCE_ROOT/Changes.rtf $DISK_IMAGE 

hdiutil create -fs HFS+ -volname $VOLNAME -srcfolder $DISK_IMAGE $DISK_IMAGE_FILE 

InstallDocumentation.sh:

#!/bin/sh 
# See also http://developer.apple.com/tools/creatingdocsetswithdoxygen.html 

set -x 

VERSION=$(agvtool mvers -terse1) 

DOXYFILE=$DERIVED_FILES_DIR/doxygen.config 
DOXYGEN=/Applications/Doxygen.app/Contents/Resources/doxygen 
DOCSET=$INSTALL_DIR/Docset 

rm -rf $DOCSET 
mkdir -p $DOCSET || exit 1 
mkdir -p $DERIVED_FILES_DIR || exit 1 

if ! test -x $DOXYGEN ; then 
    echo "*** Install Doxygen to get documentation generated for you automatically ***" 
    exit 1 
fi 

# Create a doxygen configuration file with only the settings we care about 
$DOXYGEN -g - > $DOXYFILE 

cat <<EOF >> $DOXYFILE 

PROJECT_NAME   = $FULL_PRODUCT_NAME 
PROJECT_NUMBER   = $VERSION 
OUTPUT_DIRECTORY  = $DOCSET 
INPUT     = $SOURCE_ROOT/Source 
FILE_PATTERNS   = *.h *.m 

HIDE_UNDOC_MEMBERS  = YES 
HIDE_UNDOC_CLASSES  = YES 
HIDE_UNDOC_RELATIONS = YES 
REPEAT_BRIEF   = NO 
CASE_SENSE_NAMES  = YES 
INLINE_INHERITED_MEMB = YES 
SHOW_FILES    = NO 
SHOW_INCLUDE_FILES  = NO 
GENERATE_LATEX   = NO 
GENERATE_HTML   = YES 
GENERATE_DOCSET  = YES 
DOCSET_FEEDNAME  = "$PROJECT.framework API Documentation" 
DOCSET_BUNDLE_ID  = org.brautaset.$PROJECT 

EOF 

# Run doxygen on the updated config file. 
# doxygen creates a Makefile that does most of the heavy lifting. 
$DOXYGEN $DOXYFILE 

# make will invoke docsetutil. Take a look at the Makefile to see how this is done. 
make -C $DOCSET/html install 

# Construct a temporary applescript file to tell Xcode to load a docset. 
rm -f $TEMP_DIR/loadDocSet.scpt 

cat <<EOF > $TEMP_DIR/loadDocSet.scpt 
tell application "Xcode" 
    load documentation set with path "/Users/$USER/Library/Developer/Shared/Documentation/DocSets/org.brautaset.${PROJECT}.docset/" 
end tell 
EOF 

# Run the load-docset applescript command. 
osascript $TEMP_DIR/loadDocSet.scpt 

RegenerateDocumentation.sh:

#!/bin/sh 
# See also http://developer.apple.com/tools/creatingdocsetswithdoxygen.html 

set -x 

VERSION=$(agvtool mvers -terse1) 

DOXYFILE=$DERIVED_FILES_DIR/doxygen.config 
DOXYGEN=/Applications/Doxygen.app/Contents/Resources/doxygen 
DOCSET=$INSTALL_DIR/Documentation 
APIDOCDIR=$SOURCE_ROOT/documentation 

rm -rf $DOCSET 
mkdir -p $DOCSET || exit 1 
mkdir -p $DERIVED_FILES_DIR || exit 1 

if ! test -x $DOXYGEN ; then 
    echo "*** Install Doxygen to get documentation generated for you automatically ***" 
    exit 1 
fi 

# Create a doxygen configuration file with only the settings we care about 
$DOXYGEN -g - > $DOXYFILE 

cat <<EOF >> $DOXYFILE 

PROJECT_NAME   = $FULL_PRODUCT_NAME 
PROJECT_NUMBER   = $VERSION 
OUTPUT_DIRECTORY  = $DOCSET 
INPUT     = $SOURCE_ROOT/Source 
FILE_PATTERNS   = *.h *.m 

HIDE_UNDOC_MEMBERS  = YES 
HIDE_UNDOC_CLASSES  = YES 
HIDE_UNDOC_RELATIONS = YES 
REPEAT_BRIEF   = NO 
CASE_SENSE_NAMES  = YES 
INLINE_INHERITED_MEMB = YES 
SHOW_FILES    = NO 
SHOW_INCLUDE_FILES  = NO 
GENERATE_LATEX   = NO 
GENERATE_HTML   = YES 
GENERATE_DOCSET  = NO 

EOF 

# Run doxygen on the updated config file. 
$DOXYGEN $DOXYFILE 

# Replace the old dir with the newly generated one. 
rm -f $APIDOCDIR/* 
cp -p $DOCSET/html/* $APIDOCDIR 
cd $APIDOCDIR 

# Revert files that differ only in the timestamp. 
svn diff *.html | diffstat | awk '$3 == 2 { print $1 }' | xargs svn revert 

# Add/remove files from subversion. 
svn st | awk ' 
    $1 == "?" { print "svn add", $2 } 
    $1 == "!" { print "svn delete", $2 } 
' | sh - 

svn propset svn:mime-type text/html *.html 
svn propset svn:mime-type text/css *.css 
svn propset svn:mime-type image/png *.png 
svn propset svn:mime-type image/gif *.gif 
2

Dưới đây là một phương thức để ghi lại một phương thức và các đối số của nó bất cứ khi nào nó được thực hiện (Chọn định nghĩa phương thức qua lời nói dối với dấu ngoặc mở và thực thi tập lệnh). Nếu FIXME xuất hiện ở đầu ra, nó có nghĩa là một loại không được công nhận. Bạn có thể thêm nó vào kịch bản hoặc chọn trình định dạng định dạng thích hợp theo cách thủ công.

#!/usr/bin/python 

# LogMethod 
# Selection 
# Selection 
# Insert after Selection 
# Display in Alert 

import sys 
import re 

input = sys.stdin.read() 

methodPieces = re.findall("""(\w*:)""", input) 
vars = re.findall(""":\(([^)]*)\)[ ]?(\w*)""", input) 

outputStrings = ["\n NSLog(@\""] 

# Method taking no parameters 
if not methodPieces: 
    outputStrings.append(re.findall("""(\w*)[ ]?{""", input)[0]) 

for (methodPiece, var) in zip(methodPieces, vars): 
    type = var[0] 
    outputStrings.append(methodPiece) 
    if "**" in type: 
     outputStrings.append("%p") 
    elif "*" in type: 
     if "char" in type: 
      outputStrings.append("%c") 
     else: 
      outputStrings.append("%@") 
    else: 
     if "int" in type or "NSInteger" in type or "BOOL" in type: 
      outputStrings.append("%i") 
     elif "NSUInteger" in type: 
      outputStrings.append("%u") 
     elif "id" in type: 
      outputStrings.append("%@") 
     elif "NSTimeInterval" in type: 
      outputStrings.append("%f") 
     elif "SEL" in type: 
      outputString.append("%s") 
     else: 
      outputStrings.append('"FIXME"') 
    if not methodPiece == methodPieces[-1]: 
     outputStrings.append('\\n"\n   @"') 

outputStrings.append("\"") 

for var in vars: 
    name = var[1] 
    outputStrings.append(",\n   ") 
    outputStrings.append(name) 

outputStrings.append(");") 

print "".join(outputStrings), 
2

Đây là một phương pháp để tạo một phương thức cho một lớp học. Đánh dấu phần khai báo biến cá thể (@interface ... {...}) và thực thi kịch bản lệnh. Sau đó dán kết quả vào quá trình triển khai của bạn. Tôi sử dụng cái này cùng với po objectName trong GDB. Nếu FIXME xuất hiện ở đầu ra, nó có nghĩa là một loại không được công nhận. Bạn có thể thêm nó vào kịch bản hoặc chọn trình định dạng định dạng thích hợp theo cách thủ công.

#!/usr/bin/python 

# Create description method for class 
# Selection 
# Selection 
# Insert after Selection 
# Display in Alert 

import sys 
import re 

input = sys.stdin.read() 

className = re.findall("""(?:@interface)(\w*)""", input)[0] 
vars = re.findall("""(\w*[ ][*]?)(\w*?)_?;""", input) 

outputStrings = ["- (NSString *)description {\n"] 
outputStrings.append("""return [NSString stringWithFormat:@"%s :\\n"\[email protected]" -""" % className) 

for type, var in vars: 
    outputStrings.append("%s:" % var) 
    if "**" in type: 
     outputStrings.append("%p") 
    elif "*" in type: 
     if "char" in type: 
      outputStrings.append("%c") 
     else: 
      outputStrings.append("%@") 
    else: 
     if "int" in type or "NSInteger" in type or "BOOL" in type: 
      outputStrings.append("%i") 
     elif "NSUInteger" in type: 
      outputStrings.append("%u") 
     elif "id" in type: 
      outputStrings.append("%@") 
     elif "NSTimeInterval" in type: 
      outputStrings.append("%f") 
     elif "SEL" in type: 
      outputString.append("%s") 
     else: 
      outputStrings.append('"FIXME"') 

    if not var == vars[-1][1]: 
     outputStrings.append(',\\n"\[email protected]" -') 

outputStrings.append("\"") 

for type, var in vars: 
    outputStrings.append(",\n") 
    outputStrings.append("[self %s]" % var) 

outputStrings.append("];\n}") 

print "".join(outputStrings), 
1

Đây là nơi tôi tìm thấy ở nơi khác tạo @property (sao chép) và @synthesize chỉ thị thuộc tính cho một biến mẫu. Nó có thể sử dụng một chút cải tiến (nói, để cho phép bạn tổng hợp nhiều biến cùng một lúc), nhưng tốt hơn là tạo chúng bằng tay.

Chọn biến mẫu mà bạn muốn tạo thuộc tính và kích hoạt tập lệnh.

Nếu tôi muốn (giữ lại) thay vì (sao chép), tôi chỉ kích hoạt tập lệnh và thay đổi nó để giữ nguyên thủ công (đủ thông minh để không bao gồm (bản sao) trên các kiểu nguyên thủy như int để bắt đầu).

#! /usr/bin/perl -w 

#Create property from instance variable 

#Entire Document 
#Home Directory 
#Discard Output 
#Display in Alert 

use strict; 

# Get the header file contents from Xcode user scripts 
my $headerFileContents = <<'HEADERFILECONTENTS'; 
%%%{PBXAllText}%%% 
HEADERFILECONTENTS 

# Get the indices of the selection from Xcode user scripts 
my $selectionStartIndex = %%%{PBXSelectionStart}%%%; 
my $selectionEndIndex = %%%{PBXSelectionEnd}%%%; 

# Get path of the header file 
my $implementationFilePath = "%%%{PBXFilePath}%%%"; 
my $headerFilePath = $implementationFilePath; 

# Look for an implemenation file with a ".m" or ".mm" extension 
$implementationFilePath =~ s/\.[hm]*$/.m/; 
if (!(-e $implementationFilePath)) 
{ 
    $implementationFilePath =~ s/.m$/.mm/; 
} 

# Handle subroutine to trime whitespace off both ends of a string 
sub trim 
{ 
    my $string = shift; 
    $string =~ s/^\s*(.*?)\s*$/$1/; 
    return $string; 
} 

# Get the selection out of the header file 
my $selectedText = substr $headerFileContents, $selectionStartIndex, ($selectionEndIndex - $selectionStartIndex); 
$selectedText = trim $selectedText; 

my $type = ""; 
my $asterisk = ""; 
my $name = ""; 
my $behavior = ""; 

# Test that the selection is: 
# At series of identifiers (the type name and access specifiers) 
# Possibly an asterisk 
# Another identifier (the variable name) 
# A semi-colon 
if (length($selectedText) && ($selectedText =~ /([_A-Za-z][_A-Za-z0-9]*\s*)+([\s\*]+)([_A-Za-z][_A-Za-z0-9]*);/)) 
{ 
    $type = $1; 
    $type = trim $type; 
    $asterisk = $2; 
    $asterisk = trim $asterisk; 
    $name = $3; 
    $behavior = ""; 
    if (defined($asterisk) && length($asterisk) == 1) 
    { 
     $behavior = "(copy) "; #"(nonatomic, retain) "; 
    } 
    else 
    { 
     $asterisk = ""; 
    } 
} 
else 
{ 
    exit 1; 
} 

# Find the closing brace (end of the class variables section) 
my $remainderOfHeader = substr $headerFileContents, $selectionEndIndex; 
my $indexAfterClosingBrace = $selectionEndIndex + index($remainderOfHeader, "\n}\n") + 3; 
if ($indexAfterClosingBrace == -1) 
{ 
    exit 1; 
} 

# Determine if we need to add a newline in front of the property declaration 
my $leadingNewline = "\n"; 
if (substr($headerFileContents, $indexAfterClosingBrace, 1) eq "\n") 
{ 
    $indexAfterClosingBrace += 1; 
    $leadingNewline = ""; 
} 

# Determine if we need to add a newline after the property declaration 
my $trailingNewline = "\n"; 
if (substr($headerFileContents, $indexAfterClosingBrace, 9) eq "\@property") 
{ 
    $trailingNewline = ""; 
} 

# Create and insert the propert declaration 
my $propertyDeclaration = $leadingNewline . "\@property " . $behavior . $type . " " . $asterisk . $name . ";\n" . $trailingNewline; 
substr($headerFileContents, $indexAfterClosingBrace, 0) = $propertyDeclaration; 

my $replaceFileContentsScript = <<'REPLACEFILESCRIPT'; 
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 
REPLACEFILESCRIPT 

# Use Applescript to replace the contents of the header file 
# (I could have used the "Output" of the Xcode user script instead) 
system 'osascript', '-e', $replaceFileContentsScript, $headerFilePath, $headerFileContents; 

# Stop now if the implementation file can't be found 
if (!(-e $implementationFilePath)) 
{ 
    exit 1; 
} 

my $getFileContentsScript = <<'GETFILESCRIPT'; 
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 
GETFILESCRIPT 

# Get the contents of the implmentation file 
open(SCRIPTFILE, '-|') || exec 'osascript', '-e', $getFileContentsScript, $implementationFilePath; 
my $implementationFileContents = do {local $/; <SCRIPTFILE>}; 
close(SCRIPTFILE); 

# Look for the class implementation statement 
if (length($implementationFileContents) && ($implementationFileContents =~ /(\@implementation [_A-Za-z][_A-Za-z0-9]*\n)/)) 
{ 
    my $matchString = $1; 
    my $indexAfterMatch = index($implementationFileContents, $matchString) + length($matchString); 

    # Determine if we want a newline before the synthesize statement 
    $leadingNewline = "\n"; 
    if (substr($implementationFileContents, $indexAfterMatch, 1) eq "\n") 
    { 
     $indexAfterMatch += 1; 
     $leadingNewline = ""; 
    } 

    # Determine if we want a newline after the synthesize statement 
    $trailingNewline = "\n"; 
    if (substr($implementationFileContents, $indexAfterMatch, 11) eq "\@synthesize") 
    { 
     $trailingNewline = ""; 
    } 

    # Create and insert the synthesize statement 
    my $synthesizeStatement = $leadingNewline . "\@synthesize " . $name . ";\n" . $trailingNewline; 
    substr($implementationFileContents, $indexAfterMatch, 0) = $synthesizeStatement; 

    # Use Applescript to replace the contents of the implementation file in Xcode 
    system 'osascript', '-e', $replaceFileContentsScript, $implementationFilePath, $implementationFileContents; 
} 

exit 0; 
+0

Trong XCode 3.2.2 kịch bản này cho phép ngoại lệ XCode khác nhau và làm cho XCode tất cả crashy. Không chắc chắn làm thế nào một kịch bản có thể làm điều đó để XCode, vì vậy tôi tưởng tượng nó là một điều XCode. –

+0

Lưu ý: Crasiness chỉ đúng nếu bạn không có cài đặt của bạn đúng trên kịch bản. –

4

Đây là sự cải tiến của tập lệnh "Tạo thuộc tính và Synth cho biến mẫu" mà Lawrence Johnston đã đăng ở trên.

Cài đặt:

Input: Toàn bộ tài liệu Thư mục: Home Directory Output: Bỏ Output Lỗi: Bỏ qua lỗi (hoặc Alert nếu bạn muốn xem chúng)

Chọn bất kỳ số lượng các biến và nó sẽ tạo thuộc tính và đồng bộ cho tất cả chúng. Nó thậm chí sẽ tạo/chỉnh sửa phương pháp dalloc của bạn khi cần thiết.

Sửa lên kết quả nếu họ không hoàn toàn đúng (copy vs giữ lại, vv)

Xử lý nhiều thứ như tên lưu trữ thanh dưới, hành vi, dealloc, ...

Liên kết tới nơi này xuất phát từ và thảo luận: http://cocoawithlove.com/2008/12/instance-variable-to-synthesized.html

#! /usr/bin/perl -w 

# Created by Matt Gallagher on 20/10/08. 
# Copyright 2008 Matt Gallagher. All rights reserved. 
# 
# Enhancements by Yung-Luen Lan and Mike Schrag on 12/08/09. 
# (mainly: multiple lines) 
# Copyright 2009 Yung-Luen Lan and Mike Schrag. All rights reserved. 
# 
# Enhancements by Pierre Bernard on 20/09/09. 
# (mainly: underbar storage name, behavior, dealloc,…) 
# Copyright 2009 Pierre Bernard. All rights reserved. 
# 
# Permission is given to use this source code file without charge in any 
# project, commercial or otherwise, entirely at your risk, with the condition 
# that any redistribution (in part or whole) of source code must retain 
# this copyright and permission notice. Attribution in compiled projects is 
# appreciated but not required. 

use strict; 

# Get the header file contents from Xcode user scripts 
my $headerFileContents = <<'HEADERFILECONTENTS'; 
%%%{PBXAllText}%%% 
HEADERFILECONTENTS 

# Get the indices of the selection from Xcode user scripts 
my $selectionStartIndex = %%%{PBXSelectionStart}%%%; 
my $selectionEndIndex = %%%{PBXSelectionEnd}%%%; 



# Find the closing brace (end of the class variables section) 
my $remainderOfHeader = substr $headerFileContents, $selectionEndIndex; 
my $indexAfterClosingBrace = $selectionEndIndex + index($remainderOfHeader, "\n}\n") + 3; 
if ($indexAfterClosingBrace == -1) 
{ 
exit 1; 
} 


# Get path of the header file 
my $implementationFilePath = "%%%{PBXFilePath}%%%"; 
my $headerFilePath = $implementationFilePath; 

# Look for an implemenation file with a ".m" or ".mm" extension 
$implementationFilePath =~ s/\.[hm]*$/.m/; 
if (!(-e $implementationFilePath)) 
{ 
$implementationFilePath =~ s/.m$/.mm/; 
} 

# Stop now if the implementation file can't be found 
if (!(-e $implementationFilePath)) 
{ 
exit 1; 
} 


my $propertyDeclarations = ''; 
my $synthesizeStatements = ''; 
my $releaseStatements = ''; 



# Handle subroutine to trim whitespace off both ends of a string 
sub trim 
{ 
my $string = shift; 
$string =~ s/^\s*(.*?)\s*$/$1/; 
return $string; 
} 

# Get the selection out of the header file 
my $selectedText = substr $headerFileContents, $selectionStartIndex, ($selectionEndIndex - $selectionStartIndex); 
$selectedText = trim $selectedText; 

my $selectedLine; 

foreach $selectedLine (split(/\n+/, $selectedText)) { 
my $type = ''; 
my $asterisk = ''; 
my $name = ''; 
my $behavior = ''; 

# Test that the selection is: 
# At series of identifiers (the type name and access specifiers) 
# Possibly an asterisk 
# Another identifier (the variable name) 
# A semi-colon 
if (length($selectedLine) && ($selectedLine =~ /([_A-Za-z][_A-Za-z0-9]*\s*)+([\s\*]+)([_A-Za-z][_A-Za-z0-9]*);/)) 
{ 
    $type = $1; 
    $type = trim $type; 
    $asterisk = $2; 
    $asterisk = trim $asterisk; 
    $name = $3; 
    $behavior = 'assign'; 

    if (defined($asterisk) && length($asterisk) == 1) 
    { 
    if (($type eq 'NSString') || ($type eq 'NSArray') || ($type eq 'NSDictionary') || ($type eq 'NSSet')) 
    { 
    $behavior = 'copy'; 
    } 
    else 
    { 
    if (($name =~ /Delegate/) || ($name =~ /delegate/) || ($type =~ /Delegate/) || ($type =~ /delegate/)) 
    { 
    $behavior = 'assign'; 
    } 
    else 
    { 
    $behavior = 'retain'; 
    } 
    } 
    } 
    else 
    { 
    if ($type eq 'id') 
    { 
    $behavior = 'copy'; 
    } 

    $asterisk = ''; 
    } 
} 
else 
{ 
    next; 
} 

my $storageName = ''; 

if ($name =~ /_([_A-Za-z][_A-Za-z0-9]*)/) { 
    $storageName = $name; 
    $name = $1; 
} 


# Create and insert the propert declaration 
my $propertyDeclaration = "\@property (nonatomic, $behavior) $type " . $asterisk . $name . ";\n"; 

$propertyDeclarations = $propertyDeclarations . $propertyDeclaration; 



# Create and insert the synthesize statement 
my $synthesizeStatement = ''; 

if (length($storageName)) 
{ 
    $synthesizeStatement = "\@synthesize $name = $storageName;\n"; 
} 
else 
{ 
    $synthesizeStatement = "\@synthesize $name;\n"; 
} 

$synthesizeStatements = $synthesizeStatements . $synthesizeStatement; 



# Create and insert release statement 
my $releaseName = $name; 
my $releaseStatement = ''; 

if (length($storageName)) 
{ 
    $releaseName = $storageName; 
} 

if ($behavior eq 'assign') 
{ 
    if ($type eq 'SEL') 
    { 
    $releaseStatement = "\t$releaseName = NULL;\n"; 
    } 
} 
else 
{ 
    $releaseStatement = "\t[$releaseName release];\n\t$releaseName = nil;\n"; 
} 

$releaseStatements = $releaseStatements . $releaseStatement; 
} 

my $leadingNewline = ''; 
my $trailingNewline = ''; 

# Determine if we need to add a newline in front of the property declarations 
if (substr($headerFileContents, $indexAfterClosingBrace, 1) eq "\n") 
{ 
$indexAfterClosingBrace += 1; 
$leadingNewline = ''; 
} 
else 
{ 
$leadingNewline = "\n"; 
} 

# Determine if we need to add a newline after the property declarations 
if (substr($headerFileContents, $indexAfterClosingBrace, 9) eq '@property') 
{ 
$trailingNewline = ''; 
} 
else 
{ 
$trailingNewline = "\n"; 
} 

substr($headerFileContents, $indexAfterClosingBrace, 0) = $leadingNewline . $propertyDeclarations . $trailingNewline; 

my $replaceFileContentsScript = <<'REPLACEFILESCRIPT'; 
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 (text 1 thru -2 of newDocText) 
end tell 
end run 
REPLACEFILESCRIPT 

# Use Applescript to replace the contents of the header file 
# (I could have used the "Output" of the Xcode user script instead) 
system 'osascript', '-e', $replaceFileContentsScript, $headerFilePath, $headerFileContents; 



my $getFileContentsScript = <<'GETFILESCRIPT'; 
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 
GETFILESCRIPT 

# Get the contents of the implmentation file 
open(SCRIPTFILE, '-|') || exec 'osascript', '-e', $getFileContentsScript, $implementationFilePath; 
my $implementationFileContents = do {local $/; <SCRIPTFILE>}; 
close(SCRIPTFILE); 

# Look for the class implementation statement 
if (length($implementationFileContents) && ($implementationFileContents =~ /(\@implementation [_A-Za-z][_A-Za-z0-9]*\n)/)) 
{ 
my $matchString = $1; 
my $indexAfterMatch = index($implementationFileContents, $matchString) + length($matchString); 

# Determine if we want a newline before the synthesize statement 
if (substr($implementationFileContents, $indexAfterMatch, 1) eq "\n") 
{ 
    $indexAfterMatch += 1; 
    $leadingNewline = ''; 
} 
else 
{ 
    $leadingNewline = "\n"; 
} 

# Determine if we want a newline after the synthesize statement 
if (substr($implementationFileContents, $indexAfterMatch, 11) eq '@synthesize') 
{ 
    $trailingNewline = ''; 
} 
else 
{ 
    $trailingNewline = "\n"; 
} 

substr($implementationFileContents, $indexAfterMatch, 0) = $leadingNewline. $synthesizeStatements . $trailingNewline; 

if ($implementationFileContents =~ /([ \t]*\[.*super.*dealloc.*\].*;.*\n)/) 
{ 
    my $deallocMatch = $1; 
    my $indexAfterDeallocMatch = index($implementationFileContents, $deallocMatch); 

    substr($implementationFileContents, $indexAfterDeallocMatch, 0) = "$releaseStatements\n"; 

} 
elsif ($implementationFileContents =~ /(\@synthesize .*\n)*(\@synthesize [^\n]*\n)/s) { 
    my $synthesizeMatch = $2; 
    my $indexAfterSynthesizeMatch = index($implementationFileContents, $synthesizeMatch) + length($synthesizeMatch); 
    my $deallocMethod = "\n- (void)dealloc\n{\n$releaseStatements\n\t[super dealloc];\n}\n"; 

    substr($implementationFileContents, $indexAfterSynthesizeMatch, 0) = $deallocMethod; 
} 

# Use Applescript to replace the contents of the implementation file in Xcode 
system 'osascript', '-e', $replaceFileContentsScript, $implementationFilePath, $implementationFileContents; 
} 

exit 0; 
Các vấn đề liên quan