Alfred Workflow in Swift

Apple ha creato una nuova lingua da integrare Objective-C: veloce. veloce è ancora nella classe di linguaggio C, ma ha alcune caratteristiche di un linguaggio interpretato. La sintassi più semplice rispetto a Objective-C renderà l'apprendimento e l'utilizzo molto più facile. veloce è utilizzabile come interprete o compilatore.

Sto introducendo questo linguaggio mostrando come usarlo con Alfred Workflow e presumo che tu abbia già familiarità con la scrittura di flussi di lavoro in Alfred. In caso contrario, consulta questi tutorial: Alfred per principianti, intermedi, Avanzate, e Alfred Debugging.

Questo tutorial si concentra sull'uso veloce con Alfred e non un riferimento completo alla lingua. C'è una grande serie di tutorial sull'apprendimento veloce su Code Tuts+, Introduzione a Swift: Parte 1 e Introduzione a Swift: parte 2. Supporrò che tu abbia già letto questi articoli.

Installare Xcode 6.1

Installare veloce su un Mac, devi installare XCode dall'App Store. Una volta installato, è necessario aprire una finestra di terminale ed eseguire:

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

Ciò renderà tutti gli strumenti XCode disponibili per la riga di comando.

Aggiunta di Swift alla shell

Puoi compilare e sperimentare veloce nel XCode 6.1 e la sua Terreno di gioco. Questo tutorial si concentra sull'uso veloce sulla riga di comando utilizzando solo l'editor di un programmatore e la riga di comando.

Supponendo che tu abbia installato XCode 6.1 al applicazioni cartella, sarà necessario aggiungere velocela directory degli eseguibili nel percorso. Per bash, aggiungi questo al tuo ~ / .Bashrc file:

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

Per zsh, aggiungi la stessa linea al tuo ~ / .Zshrc file. Per Pesce shell, aggiungi questa riga:

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

Ho trovato che usando il xcrun comando senza avere il PATH impostato come sopra non funziona sempre.

Compilare veloce file sulla riga di comando, si digita:

swiftc 

Correre veloce in un interprete interattivo, digiti:

veloce

Aggiunta di Swift a un editor

Aggiunta veloce supporto per Testo sublime è facile. Installa Gestione pacchetti per il testo sublime. Una volta che hai Package Manager, devi installare il pacchetto veloce usando Maiuscole-Comando-P, genere installazione del pacchetto, accedere, e veloce. Questo dovrebbe installare il veloce pacchetto.

Sopra Emacs, il gestore di pacchetti per Emacs è il percorso migliore, ma è solo dentro Emacs 24+. Per Emacs 24+, devi scaricare e installare Aquamacs. Il Emacs installato su un Mac standard è la versione 22. Per installare Aquamacs utilizzando HomeBrew e Casetta HomeBrew, digita questo in un terminale:

brew cask installa aquamacs 

Una volta installato, devi aggiungerlo al tuo ~ / .Emacs file:

(richiede 'pacchetto') (pacchetto-initialize) (lista-pacchetto '-archivio' ("melpa". "http://melpa.milkbox.net/packages/")) 

Correre Aquamacs e apri il Emacs Package Manager con Meta-x pacchetti-lista-pacchetti.

Emacs Package Manager

Cercare swift-mode e fare clic su di esso. Potrebbe essere necessario installare flycheck anche.

Per Vim, è necessario installare Swift.Vim. Il modo più semplice per installare Swift.Vim è da installare massimo-awesome primo. Installare massimo-awesome, aprire un terminale in ~ / Documenti (o qualsiasi altra directory. Deve essere un po 'dove si intende mantenere). Digitare quanto segue:

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

L'installazione richiederà un po 'di tempo. Successivamente, aggiungi questa linea al tuo ~ / .Vimrc.bundle.local file:

Plugin 'Keithbsmiley / swift.vim' 

Una volta salvato, riesegui Vim e scrivi

: PluginInsall

Vundle, quale massimo-awesome installa, installa qualsiasi nuovo plugin.

Vundler Installazione di Swift.Vim

In questo caso, Vundler installa il Swift.Vim collegare. Vim ora eseguirà l'evidenziazione della sintassi per veloce.

Swift Interpreted vs Compiled

veloce può funzionare come un interprete o un compilatore. Per illustrare ciò, crea un file hello.swift e aggiungilo a questo:

#! / usr / bin / env xcrun -sdk macosx swift println ("Hello World!") 

Questo è il più basilare Ciao mondo programma che le persone usano come primo programma. La prima riga indica la shell con cui si desidera eseguire questo script xcrun con la riga di comando specificata. xcrun è un programma Mac OSX per l'esecuzione di utilità XCode dalla riga di comando.

Salva il file e modifica la sua modalità di esecuzione con

chmod x + a hello.swift 

Esegui il file con

./hello.swift 

E produrrà Ciao mondo! sul terminale eseguendo lo script con veloce come interprete. Per compilare, digita questo sul terminale:

swiftc ciao.swift 

UN Ciao il programma ora esiste in quella directory. genere

./Ciao 

e vedrai esattamente lo stesso risultato.

Ciao programma mondiale

Entrambi i metodi hanno prodotto lo stesso identico risultato. L'unica cosa diversa è quella per l'approccio interpretato, XCode 6 deve essere su ogni sistema che lo esegue. Se si compila il programma, può essere eseguito su qualsiasi Mac.

Una nota interessante sull'approccio interpretato è che è lo stesso dell'approccio compilato per ciò che viene pubblicato. In modalità interpretata, compila il programma in memoria e viene eseguito direttamente nella memoria. L'approccio compilato viene compilato su disco e si esegue il programma. Nel complesso, non si risparmia in alcun momento interpretando il codice Swift.

Biblioteca Alfred

Per fare programmi di scrittura per l'uso in Alfred, una libreria di funzioni di supporto può essere una grande risorsa. Crea un nuovo file chiamato Alfred.swift e inserisci questo codice all'interno:

// // Classe: Alfred // // Descrizione: Questa classe serve come aiuto nella creazione di flussi di lavoro per Alfred utilizzando // linguaggio Swift di Apple. // // Variabili di classe: // // Nome Descrizione // // percorso di cache alla directory che contiene la cache per il flusso di lavoro // percorso dati alla directory che contiene i dati per il flusso di lavoro // bundleId L'ID per il bundle che rappresenta il flusso di lavoro // percorso alla directory del flusso di lavoro // percorso home alla directory home dell'utente // restituisce i risultati accumulati. Questo verrà convertito nell'elenco XML per // feedback in Alfred // // // Importa librerie necessarie. // import Foundation // // Definire le strutture utilizzate. // struct AlfredResult var Uid: String = "" var Arg: String = "" var Titolo: String = "" var Sub: String = "" var Icona: String = "" var Valid: String = "" var Auto: String = "" var Rtype: String = "" // // Classe: Regex // // Descrizione: Questa è una classe helper per scrivere test usando le espressioni regolari. Basato // sull'articolo: 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 (pattern: pattern, options: .CaseInsensitive, error: & error)!  func test (input: String) -> Bool let matches = self.internalExpression.matchesInString (input, opzioni: nil, intervallo: NSMakeRange (0, count (input))) return matches.count> 0 // / / Classe: Alfred // // Descrizione: questa classe include le funzioni necessarie per scrivere i flussi di lavoro per Alfred. // public class Alfred var cache: String = "" var data: String = "" var bundleId: String = "" var percorso: String = "" var home: String = "" var fileMGR: NSFileManager = NSFileManager () var maxResults: Int = 10 var currentResult: Int = 0 var risultati: [AlfredResult] = [] // // Classe di libreria Funzione: // // init Questa funzione di classe viene chiamata all'utilizzo della libreria per inizializzare // qualsiasi variabile utilizzata per il libreria prima che chiunque // possa effettuare una chiamata a una funzione di classe della libreria. // public init () // // Crea la matrice dei risultati. // var resfirst: AlfredResult = AlfredResult () resfirst.Title = "Nessuna corrispondenza trovata ..." resfirst.Uid = "default" resfirst.Valid = "no" resfirst.Arg = "" resfirst.Sub = "" resfirst.Icon = "" resfirst.Auto = "" resfirst.Rtype = "" results.append (resfirst) maxResults = 10 currentResult = 0 // // Imposta il percorso e le variabili iniziali dall'ambiente. // in Objective C: NSString * path = [[[NSProcessInfo processInfo] environment] objectForKey: @ "PATH"]; // let process = NSProcessInfo.processInfo (); let edict = NSDictionary (dizionario: process.environment) percorso = fileMGR.currentDirectoryPath home = edict ["HOME"] as! Stringa // // Se il file info.plist esiste, leggerlo per il bundleid e impostare la variabile bundleId. // bundleId = GetBundleId () // // Crea la struttura di directory per la cache e le directory di dati. // cache = home + "/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data /" + bundleId; data = home + "/ Library / Application Support / Alfred 2 / Workflow Data /" + bundleId; // // Controlla se la directory della cache esiste. // if (! fileMGR.fileExistsAtPath (cache)) // // Non esiste. Crealo! // fileMGR.createDirectoryAtPath (cache, withIntermediateDirectories: true, attributes: nil, error: nil) // // Controlla se la directory dei dati esiste. // if (! fileMGR.fileExistsAtPath (data)) // // Non esiste. Crealo! // fileMGR.createDirectoryAtPath (data, withIntermediateDirectories: true, attributes: nil, error: nil) // // class Funzione: GetBundleId // // Descrizione: Questa funzione di classe leggerà i flussi di lavoro info.plist e restituirà // il bundleid // public func GetBundleId () -> String // // richiama l'ID bundle dal plist se non è stato ancora recuperato. // if (bundleId == "") let path = NSBundle.mainBundle (). pathForResource ("info", ofType: "plist") lascia dict = NSDictionary (contentsOfFile: path!)! bundleId = dict ["bundleid"] come! String // // Restituisce l'ID bundle. // return (bundleId) // // class Funzione: Cache // // Descrizione: Questa funzione di classe restituisce la directory della cache per il flusso di lavoro. // public func Cache () -> String return (cache) // // class Funzione: Data // // Descrizione: Questa funzione di classe restituisce la directory dei dati per il flusso di lavoro. // public func Data () -> String return (data) // // class Funzione: Path // // Descrizione: Questa funzione di classe restituisce il percorso del flusso di lavoro. // public func Path () -> String return (path) // // class Funzione: Home // // Descrizione: Questa funzione di classe restituisce la directory Home dell'utente. // public func Home () -> String return (home) // // class Funzione: ToXML // // Descrizione: questa funzione di classe prende la matrice dei risultati e la rende in una // stringa XML per il passaggio a Alfred. // public func ToXML () -> String var newxml: String = ""per risultato in risultati newxml + ="\ (Result.Arg)\ (Result.Title)\ (Result.Sub)\ (Result.Icon)" // // Chiudi il xml e restituisci la stringa XML. // newxml + =""return (newxml) // // class Funzione: AddResult // // Descrizione: Funzione classe helper che semplifica il passaggio dei valori // in una funzione classe // e crea un risultato array da restituire ad Alfred // // Input: // uid l'uid del risultato, dovrebbe essere univoco // arg l'argomento che verrà passato // // Il titolo della voce risultato // sub Il testo dei sottotitoli per l'elemento risultato // icona l'icona da utilizzare per la voce risultato // valido imposta se l'elemento risultato può essere attivato // auto il valore di autocompletamento per la voce risultato // rtype Non ho idea di cosa sia usato per questo. HELP! // public func AddResult (uid: String, arg: String, title: String, sub: String, icona: String, valido: String, auto: String, rtype: String) // // Aggiungi nel nuovo array di risultati se non pieno. / / 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    

Questa è una porta della mia libreria di Alfred go che uso nel tutorial Traccia il tempo del progetto con Alfred Timekeeper veloce. Definisco una struttura, AlfredResult, per mantenere gli oggetti da restituire a Script Filter nel Alfred, una classe per usare il NSRegularExpression Objective-C classe, e il Alfred classe per la gestione di tutto ciò che un Alfred il flusso di lavoro avrebbe bisogno.

A questo punto, hai notato che ho menzionato un Objective-C classe. veloce non rimuove la necessità di usare Objective-C librerie. Il veloce la libreria standard ha costrutti e routine di linguaggio di base. Niente che sia specifico del sistema operativo. Tutti Objective-C le biblioteche sono utilizzabili direttamente da veloce. Quindi, non buttare via tutto il tuo Objective-C manuali di riferimento. Sono ancora necessari.

Il Alfred la classe ha una routine di inizializzazione che ottiene i diversi percorsi di directory che un flusso di lavoro utilizza e crea le directory di dati e cache se non esistono già. I metodi AddResult () e AddResultsSimilar () creare la struttura dei risultati per gli output XML su Alfred. Il AddResultsSimilar () aggiunge solo il risultato se era simile alla riga del titolo. Il Toxml () la funzione emette il codice XML dell'array dei risultati.

Il flusso di lavoro

Il flusso di lavoro di esempio sarà un convertitore di casi. L'ho creato una volta in PHP, ma per molti sistemi funziona molto lentamente. Ci vorrà una stringa sul Alfred prompt, o dalla selezione OSX utilizzando un tasto di scelta rapida, e dare un elenco di conversioni disponibili. Mostra la conversione risultante durante la digitazione. La conversione selezionata dall'utente è quella inviata negli Appunti e l'applicazione principale.

Alfred Case Converter Workflow

Crea un flusso di lavoro Alfred come vedi sopra.

Filtro script del flusso di lavoro

Impostare il ScriptFilter come vedi sopra. Seleziona il Aprire la cartella del flusso di lavoro nell'angolo in basso a destra. UN mirino la finestra si aprirà nella directory per il flusso di lavoro. Copia il Biblioteca Alfred file creato in precedenza in questa directory. Quindi creare un nuovo file chiamato tcconverter.swift e aggiungi questo codice alla fine del file:

// // Program: Text Case Converter (tcconverter) // // Descrizione: Questo programma prenderà una stringa sulla riga di comando, convertirà // in vari modi e creerà un output xml per mostrare // in uno script Alfred Filtro. // // // Importa librerie: // import Alfred import Foundation class Convertitore init () // // Crea l'oggetto Alfred. // var wf = Alfred () // // Ottieni la stringa della riga di comando e inizializza il conteggio. // let str: String = Process.arguments [1] var count = 0 // // A una stringa in maiuscolo. // var result = str.capitalizedString wf.AddResult ("CS \ (count)", arg: result, titolo: "Capitalized: \ (result)", sub: "Convertitore del caso di testo", icona: "icon.png" , valido: "si", auto: "", rtype: "") count ++ // // Crea una stringa minuscola. // result = str.lowercaseString wf.AddResult ("CS \ (count)", arg: result, title: "Minuscolo: \ (risultato)", sub: "Convertitore del caso di testo", icona: "icon.png", valid: "yes", auto: "", rtype: "") count ++ // // Crea una stringa maiuscola. // result = str.uppercaseString wf.AddResult ("CS \ (count)", arg: result, title: "Maiuscolo: \ (risultato)", sub: "Convertitore di casi di testo", icona: "icon.png", valido: "si", auto: "", rtype: "") count ++ // // Crea una stringa Titlecase. // result = TitleCase (str) wf.AddResult ("CS \ (count)", arg: result, title: "Titlecase: \ (result)", sub: "Convertitore del caso di testo", icona: "icon.png" , valido: "si", auto: "", rtype: "") count ++ // // Emette l'XML. // println (wf.ToXML ()) // // Metodo: TitleCase // // Descrizione: Questo metodo converte la stringa data in Title Case. // // Input: // str La stringa da convertire. // func TitleCase (str: String) -> String // // Crea un array di parole per rendere minuscole. // let lower = ["to", "an", "and", "at", "as", "but", "per", "per", "if", "in", "on", "or", "is", "with", "a", "the", "of", "vs", "vs.", "via", "via", "en"] // // Crea una serie di parole che devono essere classificate in alto. // let upper = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "HTML", "CSS", "AT & T", "PHP"] // // Dividi la stringa per spazi. // var words = str.componentsSeparatedByString ("") // // inizializza le variabili helper. // var result = "" var first = true // // Passa in rassegna ogni parola. // per parola in parole // // Crea una minuscola della parola e la parola risultante come maiuscola. // var lword = word.lowercaseString var res = word.capitalizedString // // Passa in rassegna ogni parola che dovrebbe essere in minuscolo. // per low in lower if lword == low.lowercaseString // // Dovrebbe essere in minuscolo. Imposta la parola risultato e rompi // fuori dal ciclo. // res = low break // // Passa in rassegna ogni parola che dovrebbe essere in maiuscolo. // per up in upper if lword == up.lowercaseString // // Dovrebbe essere in maiuscolo. Imposta la parola risultante e scoppia. // res = up break // // Se è la prima parola, quindi usa maiuscola. // if first res = res.capitalizedString first = false // // Crea la stringa risultante. // result + = "\ (res)" // // Restituisce il risultato. // return (result) let cv: Converter = Converter () 

Questo codice definisce il Converter oggetto. Quell'oggetto crea le diverse versioni della stringa e le assegna all'elenco dei risultati XML. Una volta completato, invia l'XML all'output.

Il Converter l'oggetto ha il Titlecase () metodo per creare una versione di titolo della stringa. Confronta ogni parola nella stringa con la matrice minuscola e la matrice maiuscola. Se trovato in questi, imposta la parola su quel valore. Si assicura sempre che la prima parola sia maiuscola.

Compilare una libreria per un'applicazione è un po 'complesso. Nel programma Terminal.app o iTerm.app, esegui queste righe di comando nella directory che contiene i sorgenti.

  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-name Alfred
  4. xcrun swiftc -o tcconverter -I "./" -L "./" -lAlfred -sdk $ (xcrun --show-sdk-path --sdk macosx) tcconverter.swift

Una volta che tutti e quattro i passaggi sono stati eseguiti, si avrà il programma tcconverter in quella directory. Se cambi il codice tcconverter.swift, devi solo eseguire nuovamente l'ultimo comando. Se si modifica il codice Alfred.swift, sarà necessario rieseguire tutte e quattro le righe.

Il programma tcconverter dovrebbe ora essere nella directory del flusso di lavoro. Puoi testarlo nel Alfred richiesta:

Test del codice

Il file di download contiene tutti questi file e il flusso di lavoro da esaminare.

Conclusione

In questo tutorial ti ho mostrato come installare veloce su Mac, configura tre diversi editor di programmi e shell, esegui veloce programmi in un terminale e utilizzare veloce costruire Flussi di lavoro Alfred

Questa è una quantità di conoscenza che devi praticare per ricordare. Pertanto, vai a fare qualcosa di grande Flussi di lavoro Alfred nel veloce e condividili con tutti!