¿Alguien tiene un script Xcode para generar directivas @property y @synthsize para variables de instancia en una clase?Script Xcode para generar/sintetizar propiedades
Respuesta
Uso el accesorio que hace esto y mucho más.
http://www.kevincallahan.org/software/accessorizer.html
muy barato y de gran alcance.
Este es el que se me ocurrió basado en uno que encontré hace mucho tiempo, reescrito en Python y con las mejoras que puede generar múltiples propiedades a la vez, entre otras cosas.
Generará propiedades para todas las variables de instancia seleccionadas usando (copia) como atributo.
Todavía hay algunos casos de borde con múltiples @interfaces o @implementaciones en un archivo, así como algunos con identificadores inusuales o colocación de asterisco (como en * const), pero debería cubrir la mayoría de los estilos de codificación típicos. Siéntase libre de editar/publicar modificaciones si soluciona alguno de estos casos.
#!/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()
Uh, no lo es "sintetizar", con dos e's? Supongo que este script no puede funcionar correctamente con el deletreado "synthsize". – n8gray
Sí, gracias por señalar eso. –
Aquí hay uno que escribí ayer para hacer las directivas @property antes de encontrarme con esta pregunta unas horas más tarde. Es un filtro de texto simple y sería trivial extenderlo a las directivas @synthesize (agregue una cláusula when
adecuada a la declaración case
y realice las adiciones apropiadas a la condición when block_end
), y no hay mucho más trabajo para extenderla para manejar varias ocurrencias de @ interfaz/@ aplicación en un archivo (mediante el seguimiento de sus nombres --- se puede hacer a través de capturas de expresiones regulares, como todo lo demás está en el guión):
#! /usr/bin/ruby
# -------------- Basic Definitions -----------------------------
doc = "%%%{PBXFilePath}%%%"
# regular expressions
search_exp = /[[:space:]]*([[a-zA-Z0-9]]*)[[:space:]]\*([a-zA-Z0-9]*)/
interface_start = /@interface/
block_end = /^\}/
#initializing variables
properties_list = []
properties_string = ""
reading_interface = 0
#---------------- Start Processing -----------------------------
file = File.open(doc, "r").readlines
file.each do |line|
# capture the regular expression matches only in the
# interface declaration and print out the matching
# property declarations
case line
# start capturing
when interface_start
reading_interface = 1
puts line
# capture and keep in properties_list
when search_exp
if (reading_interface == 1) then
data = Regexp.last_match
properties_list << data
end
puts line
# unpack properties_list and print out the property
# declarations
when block_end
if (reading_interface == 1) then
reading_interface = 0
properties_list.each do |pair|
properties_string << "@property (readwrite, copy) #{pair[0].lstrip};\n"
end
puts line
puts "\n" + properties_string
end
else puts line
end
end
corro esto utilizando "sin entrada" y "reemplazar contenidos del documento "como las opciones de E/S en el editor de scripts de usuario.
Aquí está el userscript que uso actualmente - funciona en una variable de instancia a la vez. Intenta usar el mecanismo de retención correcto (los tipos simples no se conservan) y también crea la instrucción @synthesize en el archivo de implementación; actualmente, aún no crea declaraciones dealloc para usted.
#! /usr/bin/perl -w
#Input: Selection
#Directory: Selection
#Output: Display in Alert
#Errors: 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);
#my $otherText = substr $headerFileContents, $selectionStartIndex;
#my $pulledText = "";
#if (length($otherText) && $otherText =~ /.*$(^.*;).*/)
#{
# $pulledText = $1;
#}
#
#
#print $pulledText;
$selectedText = trim $selectedText;
my $type = "";
my $asterisk = "";
my $name = "";
my $behavior = "";
my $iboutlet = "";
# 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 = "(nonatomic, retain) ";
}
else
{
$behavior = "(nonatomic) ";
$asterisk = "";
}
}
else
{
print "Bailing, error in Regex";
exit 1;
}
# special case, see if we need to keep around an IBOUTLET declaration.
if (length($selectedText) && ($selectedText =~ /IBOutlet/))
{
$iboutlet = "IBOutlet ";
}
# 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 proper declaration
my $propertyDeclaration = $leadingNewline . "\@property " . $behavior . $iboutlet . $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;
Accessorizer http://www.kevincallahan.org/software/accessorizer.html hace estas cosas y mucho más. También maneja prefijos y postfixes personalizados (sufijos). Si quieres el guión bajo de Google, lo tienes. Si desea cambiarlo, cámbielo sobre la marcha, sin necesidad de editar scripts. Además, hay una tabla de valores predeterminados en la que puede definir especificadores de propiedades predeterminados según el tipo de ivar pasado (copiar, retener, solo leer, asignar, etc.). Detecta IBOutlet e inserta automáticamente la palabra clave IBOutlet, elimina sus vistas para -viewDidUnload, hace varios estilos de dealloc. También escribe todos los accesorios peludos para colecciones (NSMutableArray y NSSet). Hace key-archiving, varios enfoques de bloqueo, puede ordenar su propiedad y sintetizar bloques, escribir código KVO, código Singleton, convertir a selector, generar etiquetas HeaderDoc, NSLog() y más ... También tiene una pestaña de estilos flexibles para poner llaves en línea nueva o no, para espaciar, para nombres de argumentos personalizados, etc. La mayoría de las cosas se manejan a través de Servicios, por lo que simplemente selecciona tu bloque de ivar, presiona una o dos teclas y listo. Si minimiza el Accesorio a la base, su interfaz no pasa al frente, lo que le permite mantenerse enfocado en Xcode o cualquier otro editor que admita Servicios. Por supuesto, Accessorizer también escribe accesos explícitos (como en Objective-C 1.0) y le permite anular las propiedades, todo con un simple cambio de un interruptor. Incluso puede personalizar la anulación basada en el tipo pasado. Mire los videos para verlos en acción.
Este es un script en Python para Xcode 3.2.4 que genera; propiedades de interfaz, sintetizar la implementación y dealloc. Para instalar, copie este script, vaya al menú de scripts de Xcode (penúltimo) "Editar scripts de usuario ..." Agréguelo en Código, cree un nuevo nombre de script y pegue el script de python a continuación.
Para usar simplemente seleccione las variables debajo de la interfaz @, luego llame a este script. A continuación, agregará todas las @ propiedades, en la implementación y todas las @synthesize y dealloc. No agregará IBOutlet a ninguna de sus etiquetas o botones, ya que no lo sabe, pero este es fácil de agregar manualmente.
La sangría del siguiente script es crítica, así que no la cambie.
#!/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.
# Xcode script options should be as follows:
# 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*((?:(?:\\b\w+\\b)\s+)*(?:(?:\\b\\w+\\b)))\\s*""" + # Identifier(s)
"""([*]?)\\s*""" + # An optional asterisk
"""(\\b\\w+?)(_?\\b);""", # The variable name
re.M)
# Now for each instance variable in the selected section
properties = ""
synthesizes = ""
deallocs = ""
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 = "(nonatomic, retain) " # Attributes if variable is pointer
if not asterisk:
pointerPropertyAttributes = "(nonatomic, assign) "
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)
# only do the objects
if asterisk:
newDealloc = " [%s%s release];\n" % (variableName,
trailingUnderscore and
" = %s_" % variableName)
properties += newProperty
synthesizes += newSynthesize
# only add if it's an object
if asterisk:
deallocs += newDealloc
# 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 synthsize 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])
implementationFileText = subprocess.Popen(
["osascript",
"-e",
getFileContentsScript,
implementationFilePath],
stdout=subprocess.PIPE).communicate()[0]
# We want to insert the deallocs either immediately after the last existing
# [* release] or after the [super dealloc]
lastDeallocRegex = re.compile("^\\s+\[super dealloc\];?\\n" +
"(?:.*^\\s+\[\w release\];?\\n)?", re.M | re.S)
deallocInsertIndex = \
lastDeallocRegex.search(implementationFileText).end()
addedNewDeallocLine = "\n"
if re.search("^\s*\[\w release\];?", implementationFileText, re.M):
# Not the only dealloc, don't add
addedNewDeallocLine = ""
newImplementationFileText = "%s%s%s%s" % \
(implementationFileText[:deallocInsertIndex],
addedNewDeallocLine,
deallocs,
implementationFileText[deallocInsertIndex:])
subprocess.call(["osascript",
"-e",
setFileContentsScript,
implementationFilePath,
newImplementationFileText])
# Switch Xcode back to header file
subprocess.Popen(["osascript",
"-e",
getFileContentsScript,
headerFilePath],
stdout=subprocess.PIPE).communicate()
Whoa, hay un montón de scripts locas pasando aquí.
A partir de Xcode 4.4 (tal vez antes) ... Sus IVAR
s auto-será sintetizado .. Por ejemplo ..
@property (assign) BOOL automatically;
@property (strong) NSArray *believeDat;
puede "accessored" a través de
self.automatically = YES;
y edite la variable de instancia directamente a través de auto-generated-with-leading-underscore como ...
_believeDat = @["thank you, jesus", @"mary poopins"];
no @synthesize
necesario.
En cuanto a la entrada rápida y sencilla de tal @property
... arrastre lo siguiente, uno a la vez, en la biblioteca "Fragmento de código" ... y puede asignar atajos de teclado para insertar estos puntos de inicio para ingresar propiedades más rápido. Yo uso rrr para objetos y aaa de primitivas .. pero este soy yo ..
@property (nonatomic, assign) <#type#> <#name#>;
@property (nonatomic, retain) <#type#> *<#name#>;
por último pero no menos importante, y algunos me permite llamarlo loco .. pero arrojo las siguientes macros en mi .pch
para agilizar aún más, aclarar y dar la bienvenida brevedad al proceso ... todas las exenciones de responsabilidad macro comunes se aplican ...
#define RONLY readonly
#define RDWRT readwrite
#define NATOM nonatomic
#define STRNG strong
#define ASS assign
#define CP copy
#define SET setter
#define GET getter
junto con estructura similar #define
s para las clases de manzana (#define NSA NSArray \ #define NSS NSString
), esto hace las cosas más fáciles de leer, y más rápido para entrar (para mí), que parece ...
@property (NATOM, STRNG) NSA* fonts;
@property (NATOM, STRNG) NSS* cachedPath;
¿Quiere decir que todos @property se han sintetizado automáticamente? No es necesario definir sintetizar? – Dejell
- 1. propiedades @synthesized automáticamente en Xcode 4.4
- 2. Editor de lista de propiedades después de instalar Xcode 4
- 3. Ejecutar script durante Limpiar/Limpiar todo en Xcode
- 4. Volcar todas las propiedades definidas en el script Ant
- 5. XCode Sintaxis para colorear Roto
- 6. Script de Xcode Ejecución Fase de compilación "Ejecutar script solo al instalar" Opción
- 7. Xcode autoCompletion
- 8. Script Bash para ejecutar el script php
- 9. Xcode Consejos para usuarios de Eclipse?
- 10. Importación automática para Xcode
- 11. mejores prácticas para administrar y cargar propiedades
- 12. Xcode variables
- 13. Esquema para admitir propiedades dinámicas
- 14. Propiedades de estilo para TDateTimePicker
- 15. IDC no XCode para Cocoa?
- 16. Xcode 4.3 para Snow Leopard
- 17. ¿Qué sistema SCM para Xcode?
- 18. XCode Test Automation para iPhone
- 19. Integración continua para proyectos Xcode?
- 20. ¿Necesito palabras clave ARC para propiedades que no sintetizo?
- 21. Script BASH para pasar variables sin sustitución al nuevo script
- 22. Script Scala para copiar archivos
- 23. Bash script ¿Qué es: = para?
- 24. ¿Script simple para contar NLOC?
- 25. ¿Instalar script para OmniBrowser para Pharo 1.3?
- 26. Acceso a las variables especificadas para Jenkins Groovy Plugin Script
- 27. Script Bash: uso del comando "script" de un script bash para iniciar sesión
- 28. Definición de #defines por Xcode al compilar para el iPhone
- 29. XCode 4.3 - Desinstalar XCode 4.2
- 30. Python: propiedades idiomáticas para datos estructurados?
Gracias por la sugerencia - Voy a echar un vistazo. –