Alfred Workflows in Swift

Apple heeft een nieuwe taal gemaakt om aan te vullen Doelstelling C: Snel. Snel is nog steeds in de C-taalklasse, maar heeft enkele functies van een geïnterpreteerde taal. De eenvoudigere syntaxis vergeleken met Doelstelling C maakt het leren en gebruiken veel gemakkelijker. Snel is bruikbaar als een tolk of een compiler.

Ik introduceer deze taal door te laten zien hoe je deze kunt gebruiken met Alfred Workflows en ik neem aan dat je al bekend bent met schrijfworkflows in Alfred. Zo niet, bekijk dan deze tutorials: Alfred voor beginners, Intermediates, gevorderd, en Alfred Debugging.

Deze tutorial richt zich op het gebruik Snel met Alfred en geen volledige taalreferentie. Er is een geweldige tutorial-serie over leren Snel op codetabellen+, Een inleiding tot Swift: deel 1 en Een inleiding tot Swift: deel 2. Ik ga ervan uit dat je deze artikelen al hebt gelezen.

Installatie van Xcode 6.1

Installeren Snel op een Mac moet je XCode installeren vanuit de App Store. Na de installatie moet u een terminalvenster openen en uitvoeren:

xcode-select -s / Applications/Xcode.app/ --install

Dat maakt alle XCode-tools beschikbaar voor de opdrachtregel.

Snelheid toevoegen aan de shell

Je kunt compileren en experimenteren Snel in XCode 6.1 en zijn Speelplaats. Deze tutorial richt zich op het gebruik Snel op de opdrachtregel met alleen een editor van een programmeur en de opdrachtregel.

Ervan uitgaande dat je bent geïnstalleerd XCode 6.1 naar de toepassingen map, moet u toevoegen Snel's uitvoerbare map naar het pad. Voor Bash, voeg dit toe aan jouw ~ / .Bashrc het dossier:

export PATH = "$ PATH: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin" 

Voor zsh, voeg dezelfde regel toe aan uw ~ / .Zshrc het dossier. Voor Vis shell, voeg deze regel toe:

set -xg PATH "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin" $ PATH 

Ik heb ondervonden dat het gebruik van de xcrun opdracht zonder dat de PATH-set zoals hierboven is beschreven, werkt niet altijd.

Compileren Snel bestanden op de opdrachtregel, typ je:

swiftc 

Rennen Snel in een interactieve interpreter typt u:

snel

Swift aan een editor toevoegen

Het toevoegen Snel ondersteuning voor Sublieme tekst is makkelijk. Installeer Package Manager voor Sublime Text. Zodra u Package Manager hebt, moet u het pakket installeren Snel door het gebruiken van Shift-Command-P, type pakket installeren, invoeren, en Snel. Dit zou het moeten installeren Snel pakket.

Op Emacs, de pakketbeheerder voor Emacs is de beste route, maar het is alleen in Emacs 24+. Voor Emacs 24+, je moet downloaden en installeren Aquamacs. De Emacs geïnstalleerd op een standaard Mac is versie 22. Om te installeren Aquamacs gebruik makend van HomeBrew en HomeBrew Cask, typ dit in een terminal:

brouwt vat installeer aquamacs 

Eenmaal geïnstalleerd, moet u dit toevoegen aan uw ~ / Emacs het dossier:

(vereisen 'pakket) (package-initialize) (add-to-list' package-archives '("melpa". "http://melpa.milkbox.net/packages/")) 

Rennen Aquamacs en open de Emacs Package Manager met Meta-x pakket-lijst-pakketten.

Emacs Package Manager

Zoeken swift-mode en klik erop. U moet mogelijk installeren flycheck ook.

Voor Vim, je moet installeren Swift.Vim. De gemakkelijkste manier om te installeren Swift.Vim is om te installeren maximum-awesome eerste. Installeren maximum-awesome, open een terminal in de ~ / Documents (of een andere map. Het moet een aantal zijn waar je van plan bent om te houden.). Typ het volgende:

git clone https://github.com/square/maximum-awesome.git cd maximum-awesome rake 

De installatie duurt een tijdje. Voeg daarna deze regel toe aan uw ~ / .Vimrc.bundle.local het dossier:

Plugin 'Keithbsmiley / swift.vim' 

Eenmaal opgeslagen, opnieuw uitvoeren Vim en typ

: PluginInsall

Vundle, welke maximum-awesome installeert, installeert eventuele nieuwe plug-ins.

Vundler Installatie van Swift.Vim

In dit geval, Vundler installeert de Swift.Vim inpluggen. Vim zal nu syntax highlighting voor doen Snel.

Swift geïnterpreteerd vs gecompileerd

Snel kan worden uitgevoerd als een interpreter of een compiler. Om dat te illustreren, maakt u een bestand hello.swift en voeg dit toe:

#! / usr / bin / env xcrun -sdk macosx swift println ("Hallo wereld!") 

Dit is de meest elementaire Hallo Wereld programma dat mensen gebruiken als hun eerste programma. De eerste regel vertelt de shell waarmee u dit script wilt uitvoeren xcrun met de opgegeven opdrachtregel. xcrun is een Mac OSX-programma voor het uitvoeren van XCode-hulpprogramma's vanaf de opdrachtregel.

Sla het bestand op en verander de uitvoeringsmodus met

chmod x + een hello.swift 

Voer het bestand uit met

./hello.swift 

En het zal produceren Hallo Wereld! op de terminal door het script uit te voeren Snel als een tolk. Om te compileren, typ dit op de terminal:

swiftc hello.swift 

EEN Hallo programma bestaat nu in die map. Type

./Hallo 

en je zult precies dezelfde output zien.

Hello World-programma

Beide methoden produceerden exact hetzelfde resultaat. Het enige verschil is dat voor de geïnterpreteerde aanpak, XCode 6 moet op elk systeem zijn dat het uitvoert. Als je het programma compileert, kan het op elke Mac worden uitgevoerd.

Een interessante opmerking over de geïnterpreteerde aanpak is dat het hetzelfde is als de gecompileerde aanpak voor wat er wordt uitgevoerd. In de geïnterpreteerde modus compileert het het programma in het geheugen en loopt het rechtstreeks in het geheugen. De gecompileerde aanpak compileert naar schijf en u voert het programma uit. Over het algemeen bespaart u geen tijd door Swift-code te interpreteren.

Alfred Library

Om schrijfprogramma's te maken voor gebruik in Alfred, een bibliotheek met helperfuncties kan een grote troef zijn. Maak een nieuw bestand met de naam Alfred.swift en plaats deze code in:

// // Klasse: Alfred // // Beschrijving: deze klasse als voor het helpen bij het maken van workflows voor Alfred met // Apple's Swift-taal. // // Klassenvariabelen: // // Naam Beschrijving // // cachepad naar de map die de cache voor de werkstroom bevat // gegevenspad naar de map die de gegevens voor de werkstroom bevat // bundleId De ID voor de werkstroom bundel die de workflow vertegenwoordigt // pad naar de map van de werkstroom // home pad naar de basismap van de gebruiker // resulteert in de verzamelde resultaten. Dit wordt geconverteerd naar de XML-lijst voor // feedback naar Alfred // // // Import Libraries die nodig zijn. // import Foundation // // Definieer gebruikte structuren. // struct AlfredResult var Uid: String = "" var Arg: String = "" var Titel: String = "" var Sub: String = "" var Icon: String = "" var Valid: String = "" var Auto: String = "" var Rtype: String = "" // // Klasse: Regex // // Beschrijving: dit is een helperklasse voor het schrijven van tests met reguliere expressies. Gebaseerd // op artikel: http://benscheirman.com/2014/06/regex-in-swift/ // class Regex let internalExpression: NSRegularExpression let pattern: String init (_ pattern: String) self.pattern = pattern var error: NSError? self.internalExpression = NSRegularExpression (patroon: patroon, opties: .CaseInsensitive, error: & error)!  func-test (invoer: String) -> Bool let matches = self.internalExpression.matchesInString (invoer, opties: nihil, bereik: NSMakeRange (0, count (invoer))) return matches.count> 0 // / / Klasse: Alfred // // Beschrijving: deze klasse bevat de functies die nodig zijn om werkstromen voor Alfred te schrijven. // public class Alfred var cache: String = "" var data: String = "" var bundleId: String = "" var path: String = "" var home: String = "" var fileMGR: NSFileManager = NSFileManager () var maxResults: Int = 10 var currentResult: Int = 0 var results: [AlfredResult] = [] // // Bibliotheekklasse Function: // // init Deze klassefunctie wordt aangeroepen wanneer bibliotheek // de variabelen initialiseert die voor de bibliotheek voordat iemand // een oproep kan doen naar een bibliotheekklassefunctie. // public init () // // Maak de resultaatarray. // var resfirst: AlfredResult = AlfredResult () resfirst.Title = "Geen overeenkomsten gevonden ..." resfirst.Uid = "default" resfirst.Valid = "no" resfirst.Arg = "" resfirst.Sub = "" resfirst.Icon = "" resfirst.Auto = "" resfirst.Rtype = "" results.append (resfirst) maxResults = 10 currentResult = 0 // // Stel het pad en de huisvariabelen in vanuit de omgeving. // in Objective C: NSString * path = [[[NSProcessInfo processInfo] environment] objectForKey: @ "PATH"]; // let process = NSProcessInfo.processInfo (); laat edict = NSDictionary (dictionary: process.environment) path = fileMGR.currentDirectoryPath home = edict ["HOME"] als! String // // Als het bestand info.plist bestaat, leest u het voor de bundleid en stelt u de bundleId-variabele in. // bundleId = GetBundleId () // // Maak de directorystructuur voor de cache en gegevensmappen. // cache = home + "/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data /" + bundleId; data = home + "/ Bibliotheek / Application Support / Alfred 2 / Workflow Data /" + bundleId; // // Zien of de cachemap bestaat. // if (! fileMGR.fileExistsAtPath (cache)) // // Het bestaat niet. Creëer het! // fileMGR.createDirectoryAtPath (cache, withIntermediateDirectories: true, attributes: nil, error: nil) // // Kijk of de datamap bestaat. // if (! fileMGR.fileExistsAtPath (data)) // // Het bestaat niet. Creëer het! // fileMGR.createDirectoryAtPath (data, withIntermediateDirectories: true, attributes: nil, error: nil) // // class Functie: GetBundleId // // Beschrijving: deze klassefunctie leest de workflows info.plist en geeft // terug de bundleid // public func GetBundleId () -> String // // haal de bundel-ID uit de plist als deze al niet is opgehaald. // if (bundleId == "") let path = NSBundle.mainBundle (). pathForResource ("info", ofType: "plist") laat dict = NSDictionary (contentsOfFile: path!)! bundleId = dict ["bundleid"] as! String // // Retourneer de bundel-ID. // return (bundleId) // // class Functie: Cache // // Beschrijving: deze klassefunctie retourneert de cachemap voor de werkstroom. // public func Cache () -> String return (cache) // // class Functie: Gegevens // // Beschrijving: deze klassefunctie retourneert de gegevensdirectory voor de werkstroom. // public func Data () -> String return (data) // // class Functie: Pad // // Beschrijving: deze klassefunctie retourneert het pad naar de werkstroom. // public func Path () -> String return (path) // // class Functie: Home // // Beschrijving: deze klassefunctie retourneert de basismap voor de gebruiker. // public func Startpagina () -> String return (home) // // class Functie: ToXML // // Beschrijving: deze klassefunctie neemt de resultaatarray en maakt er een // XML-reeks van om terug te geven aan Alfred. // openbare func ToXML () -> String var newxml: String = ""voor resultaat in resultaten newxml + ="\ (Result.Arg)\ (Result.Title)\ (Result.Sub)\ (Result.Icon)" // // Sluit de XML en retourneer de XML-reeks. // newxml + =""return (newxml) // // class Functie: AddResultaat // // Beschrijving: Helper class-functie die het eenvoudig maakt om waarden // in een klassefunctie door te geven // en een array-resultaat te maken dat wordt doorgegeven aan Alfred . // // Invoer: // uid de uid van het resultaat, moet uniek zijn // arg het argument dat wordt doorgegeven // titel De titel van het resultaatitem // sub De ondertitelingstekst voor het resultaatitem // icon het pictogram dat moet worden gebruikt voor het resultaatitem // geldig stelt in of het resultaatitem kan worden bewerkt // automatisch de autocomplete-waarde voor het resultaatitem // rtype Ik heb geen idee waarvoor deze wordt gebruikt. HELP! // openbare functie AddResult (uid: String, arg: String, title: String, sub: String, icon: String, valid: String, auto: String, rtype: String) // // Nieuwe array toevoegen als deze niet vol is. / / if (currentResult < maxResults)  if(currentResult != 0)  var resfirst:AlfredResult = AlfredResult() resfirst.Title = title resfirst.Uid = uid resfirst.Valid = valid resfirst.Arg = arg resfirst.Sub = sub resfirst.Icon = icon resfirst.Auto = auto resfirst.Rtype = rtype results.append(resfirst)  else  results[0].Title = title results[0].Uid = uid results[0].Valid = valid results[0].Arg = arg results[0].Sub = sub results[0].Icon = icon results[0].Auto = auto results[0].Rtype = rtype  currentResult++   // // class Function: AddResultsSimilar // // Description: This class function will only add the results that are similar to the // input given. This is used to select input selectively from what the // user types in. // // Inputs: // inString the String to test against the titles to allow that record or not // uid the uid of the result, should be unique // arg the argument that will be passed on // title The title of the result item // sub The subtitle text for the result item // icon the icon to use for the result item // valid sets whether the result item can be actioned // auto the autocomplete value for the result item // rtype I have no idea what this one is used for. HELP! // public func AddResultsSimilar(uid: String, inString: String, arg: String, title: String, sub: String, icon: String, valid: String, auto: String, rtype: String)  // // Create the test pattern. // var matchstr = inString + ".*" // // Compare the match String to the title for the Alfred output. // if(Regex(inString + ".*").test(title))  // // A match, add it to the results. // AddResult( uid, arg: arg, title: title, sub: sub, icon: icon, valid: valid, auto: auto, rtype: rtype)   // // class Function: SetDefaultString // // Description: This class function sets a different default title // // Inputs: // title the title to use // public func SetDefaultString(title: String)  if(currentResult == 0)  // // Add only if no results have been added. // results[0].Title = title    

Dit is een port van mijn Alfred Go-taalbibliotheek die ik gebruik in de tutorial Track Project Time met Alfred Timekeeper aan Snel. Ik definieer een structuur, AlfredResult, om items terug te laten keren naar a Scriptfilter in Alfred, een klasse voor het gebruik van de NSRegularExpression Doelstelling C klasse en de Alfred klas voor het afhandelen van alles wat een Alfred workflow zou nodig hebben.

Op dit punt merkte je dat ik een genoemd Doelstelling C klasse. Snel neemt de noodzaak om te gebruiken niet weg Doelstelling C bibliotheken. De Snel standaard bibliotheek heeft basistaalconstructies en routines. Niets dat specifiek voor het besturingssysteem is. Allemaal Doelstelling C bibliotheken zijn direct bruikbaar vanaf Snel. Dus gooi niet al je jouwe weg Doelstelling C referentie handleidingen. Ze zijn nog steeds nodig.

De Alfred klasse heeft een initialisatieroutine die de verschillende mappaden verkrijgt die een werkstroom zou gebruiken en de gegevens- en cachemaps maken als deze nog niet bestaan. De methodes AddResult () en AddResultsSimilar () maak de resultatenstructuur voor de XML-uitgangen aan Alfred. De AddResultsSimilar () voegt alleen het resultaat toe als het vergelijkbaar was met de titelregel. De ToXML () functie voert de XML van de resultatenmatrix uit.

De workflow

De voorbeeldworkflow zal een case-converter zijn. Ik heb het eenmaal in PHP gemaakt, maar voor veel systemen werkt het echt traag. Het zal een string op de Alfred prompt of uit de OSX-selectie met een sneltoets en geef een lijst met beschikbare conversies. Het toont de resulterende conversie terwijl u typt. De conversie die de gebruiker selecteert, is de naar het klembord en de bovenste applicatie verzonden.

Alfred Case Converter Workflow

Maak een Alfred-workflow zoals u hierboven ziet.

Scriptfilter van Workflow

Stel de ScriptFilter zoals je hierboven ziet. Selecteer de Open workflowmap in de rechter benedenhoek. EEN vinder venster opent voor de directory voor de workflow. Kopieer de Alfred bibliotheek bestand eerder gemaakt naar deze map. Maak vervolgens een nieuw bestand met de naam tcconverter.swift en voeg deze code toe aan de onderkant van het bestand:

// // Programma: Text Case Converter (tcconverter) // // Beschrijving: dit programma neemt een tekenreeks op de opdrachtregel, converteert // op verschillende manieren en maakt een XML-uitvoer voor het weergeven van // in een Alfred Script Filter. // // // Importeer bibliotheken: // import Alfred import Foundation class Converter init () // // Maak het Alfred-object. // var wf = Alfred () // // Verkrijg de opdrachtregelreeks en initialiseer de telling. // let str: String = Process.arguments [1] var count = 0 // // Naar een hoofdletterreeks. // var result = str.capitalizedString wf.AddResult ("CS \ (count)", arg: result, title: "Hoofdletter: \ (result)", sub: "Text Case Converter", pictogram: "icon.png" , geldig: "yes", auto: "", rtype: "") count ++ // // Creëer een kleine letters reeks. // result = str.lowercaseString wf.AddResult ("CS \ (count)", arg: result, title: "Kleine letters: \ (result)", sub: "Text Case Converter", pictogram: "icon.png", valid: "yes", auto: "", rtype: "") count ++ // // Maak een hoofdletters. // result = str.uppercaseString wf.AddResult ("CS \ (count)", arg: result, title: "Hoofdletters: \ (result)", sub: "Text Case Converter", pictogram: "icon.png", valid: "yes", auto: "", rtype: "") count ++ // // Maak een Titlecase-string. // result = TitleCase (str) wf.AddResult ("CS \ (count)", arg: result, title: "Titlecase: \ (result)", sub: "Text Case Converter", pictogram: "icon.png" , geldig: "yes", auto: "", rtype: "") count ++ // // Voer de XML uit. // println (wf.ToXML ()) // // Methode: TitleCase // // Beschrijving: deze methode converteert de tekenreeks die is gegeven naar Title Case. // // Input: // str De tekenreeks die moet worden geconverteerd. // func TitleCase (str: String) -> String // // Maak een reeks woorden om kleine letters te maken. // laat lager = ["naar", "een", "en", "naar", "als", "maar", "door", "voor", "als", "in", "aan", "of", "is", "met", "een", "de", "van", "vs", "versus", "via", "via", "en"] // // Creëren een reeks woorden die als hoofdletters moeten worden gebruikt. // laat upper = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "HTML", "CSS", "AT & T", "PHP"] // // Splits de tekenreeks door spaties. // var words = str.componentsSeparatedByString ("") // // initialiseer helpervariabelen. // var result = "" var first = true // // Doorloop elk woord. // for word in words // // Maak een kleine letters van het woord en het resultaatwoord als hoofdletters. // var lword = word.lowercaseString var res = word.capitalizedString // // Doorloop elk woord dat een kleine letter moet zijn. // voor low in lower if lword == low.lowercaseString // // Het moet in kleine letters zijn. Stel het resultaatwoord in en breek // uit de lus. // res = low break // // Loop door elk woord dat in hoofdletters moet zijn. // for up in upper if lword == up.lowercaseString // // Het moet hoofdletters zijn. Stel het resultaatwoord in en doorbreek. // res = opbreken // // Als dit het eerste woord is, gebruik dan altijd hoofdletters. // if first res = res.capitalizedString first = false // // Creëer de resulterende string. // result + = "\ (res)" // // Retourneer het resultaat. // return (result) let cv: Converter = Converter () 

Deze code definieert de omvormer voorwerp. Dat object maakt de verschillende versies van de tekenreeks en wijst deze toe aan de XML-resultatenlijst. Eenmaal volledig gebouwd, stuurt het de XML naar de uitvoer.

De omvormer object heeft de Hoofdzaak() methode voor het maken van een titelgevalversie van de tekenreeks. Het vergelijkt elk woord in de string met de kleine array en de array met hoofdletters. Als deze in deze wordt gevonden, wordt het woord op die waarde ingesteld. Het zorgt er altijd voor dat het eerste woord een hoofdletter is.

Het compileren van een bibliotheek met een applicatie is een beetje ingewikkeld. Voer in het programma Terminal.app of iTerm.app deze opdrachtregels uit in de map die de bronnen bevat.

  1. xcrun swiftc -emit-library -emit-object Alfred.swift -sdk $ (xcrun --show-sdk-path --sdk macosx) -module-name Alfred
  2. ar rcs libAlfred.a Alfred.o
  3. xcrun swiftc -emit-module Alfred.swift -sdk $ (xcrun --show-sdk-path --sdk macosx) -module-naam Alfred
  4. xcrun swiftc -o tcconverter -I "./" -L "./" -lAlfred -sdk $ (xcrun --show-sdk-path --sdk macosx) tcconverter.swift

Nadat alle vier de stappen zijn uitgevoerd, hebt u het tcconverter-programma in die map. Als u de tcconverter.swift-code wijzigt, hoeft u alleen de laatste opdracht opnieuw uit te voeren. Als u de Alfred.swift-code wijzigt, moet u alle vier de regels opnieuw uitvoeren.

Het programma tcconverter zou nu in de workflow-map moeten staan. Je kunt het testen in de Alfred prompt:

De code testen

Het downloadbestand bevat al deze bestanden en de werkstroom die u kunt bekijken.

Conclusie

In deze tutorial heb ik je laten zien hoe je moet installeren Snel op de Mac, configureer drie verschillende programma-editors en shells, voer uit Snel programma's in een terminal en gebruik Snel bouwen Alfred-workflows

Dat is veel kennis die je moet oefenen om te onthouden. Ga het daarom geweldig maken Alfred-workflows in Snel en deel ze met iedereen!