Autocreate Swift init method in Xcode

After declaring a class or struct in Swift it’s pretty annoying to write an initializer for all properties.

This script creates the code for you.

For example you just wrote the struct

[format]struct Person {
let name : String
let age : Int
}
[/format]

Select the entire struct and run the script. It creates the following init method and puts it onto the clipboard. Just paste it in your Xcode document.

[format]init(name : String, age : Int) {
self.name = name
self.age = age
}
[/format]

It works also with multiple property names in one line like

[format]let firstName, lastName : String[/format]


The script was tested with Xcode 10 and High Sierra

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property indent : space & space & space & space -- default 4 spaces

tell application "Xcode"
	set allDocuments to documents whose selected character range is not {}
	if allDocuments is {} then return
	set activeDocument to item 1 of allDocuments
	set theText to text of activeDocument
	set {startIndex, endIndex} to selected paragraph range of activeDocument
	if startIndex = endIndex then return
end tell

set propertyData to {}
repeat with i from startIndex to endIndex
	set theLine to paragraph i of theText
	set nsLine to (current application's NSString's stringWithString:theLine)
	set theRange to (nsLine's rangeOfString:"(let|var)\\s" options:(current application's NSRegularExpressionSearch))
	set rangeLength to theRange's |length|() as integer
	if rangeLength > 0 then
		set rangeLocation to theRange's location() as integer
		if theLine contains "," then
			set colonOffset to offset of ":" in theLine
			set theType to text colonOffset thru -1 of theLine
			set nameText to text (rangeLocation + rangeLength + 1) thru (colonOffset - 1) of theLine
			set {TID, text item delimiters} to {text item delimiters, ","}
			set nameComponents to text items of nameText
			set text item delimiters to TID
			set whiteSpaceSet to current application's NSCharacterSet's whitespaceCharacterSet
			repeat with aName in nameComponents
				set trimmedName to trimText(aName, whiteSpaceSet)
				set end of propertyData to trimmedName & theType
			end repeat
		else
			set end of propertyData to text (rangeLocation + rangeLength + 1) thru -1 of theLine
		end if
	end if
end repeat
if propertyData = {} then return

set {TID, text item delimiters} to {text item delimiters, ", "}
set initParameters to propertyData as text
set text item delimiters to TID

set initData to {}
set initLine to indent & "init("

set end of initData to linefeed & indent & "init(" & initParameters & ") {"
repeat with aProperty in propertyData
	set propertyName to word 1 of aProperty
	set end of initData to indent & indent & "self." & propertyName & " = " & propertyName
end repeat
set end of initData to indent & "}"
set {TID, text item delimiters} to {text item delimiters, linefeed}
set initText to initData as text
set text item delimiters to TID
set the clipboard to initText

on trimText(theText, theCharacterSet)
	set nsText to (current application's NSString's stringWithString:theText)
	return (nsText's stringByTrimmingCharactersInSet:theCharacterSet) as text
end trimText