Opprette Alfred Workflows i Haskell

Hva du skal skape

Funksjonell programmering er programmeringsparadigmet hvor du programmerer uten å bruke variabler. Funksjoner kaller andre funksjoner med variabel passerer mellom.

Dette paradigmet gjør det mulig for konstanter og sterk type støping. Det er også preget av lat evaluering: uttrykk evalueres ikke før et resultat er nødvendig.

Haskell er et funksjonelt programmeringsspråk som har eksistert siden 1987. Det har et stort fellesskap av programmerere bak det og er tilgjengelig på Mac, Windows og Linux-plattformene.

I denne opplæringen lager jeg en alfred bibliotek for å bidra til å lage arbeidsflyter i Haskell. Så skal jeg lage en arbeidsflyt med dette biblioteket.

I denne opplæringen antar jeg at du allerede er kjent med å skrive arbeidsflyter i Alfred. Hvis ikke, vennligst sjekk ut disse veiledningene:

  • Alfred for nybegynnere
  • Alfred for mellomprodukter
  • Alfred for Advanced
  • Alfred Debugging

Siden en komplett beskrivelse av Haskell programmering er utenfor omfanget av denne opplæringen, kan du lese En Gentile Introduksjon til Haskell: Versjon 98. Jeg personlig lærte Haskell fra den gratis boken Skriv deg selv et ord om 48 timer. Jeg liker å lære nye språk ved å skrive et program som er nyttig.

Installere Haskell

Å bruke Haskell på Mac, trenger du først XCode installert. Dette er en gratis installasjon fra Mac App Store. Når du laster ned, starter du XCode og åpne Innstillinger Panel.

I Innstillinger Panel, Klikk på steder punkt. På bunnen, sørg for at Kommandolinjeverktøy peker på din versjon av XCode. Det vil be om brukerinnlogging. Når gitt, er kommandolinjeverktøyene satt opp til bruk.

Med XCode installert og satt opp, last ned Haskell kompilator og støttefiler fra Haskell for Mac OS X.

Etter at du har pakket opp filen, flytter du ghc-7.10.1.app til applikasjonsmappen (7.10.1 var den siste versjonen som jeg skrev denne opplæringen).

Installatøren viser koden du vil legge til i ~ / Bash_profile fil og din ~ / .Zshrc fil (hvis du bruker Z-shell). Når du legger til koden i shellfilene dine, klikker du på Oppdater sjekkliste. Alle avmerkingsboksene skal være grønne. Du er nå klar til å lage Haskell programmer.

Alfred Library i Haskell

Haskell har en pakkebehandling ligner på NodeJS's NPM. Det er Cabal. Med Cabal Du kan laste ned og installere mange tredjepartsbiblioteker som andre har skrevet inn Haskel. For Alfred Haskell Library, du må installere TagSoup bibliotek. Dette hjelper å hente bundled av alfred arbeidsflyt. På kommandolinjen skriver du:

kabal installere tagsoup 

Opprett nå en ny fil som heter Alfred.hs. Alle Haskell programfiler slutter med .hs forlengelse. I denne filen begynner du å plassere denne koden:

Modul Alfred (start, slutt, addItem, addItemBasic, getAlfredDataFileContents, putAlfredDataFileContents, getAlfredCacheFileContents, putAlfredCacheFileContents) der import System.Process import System.Directory import System.Environment importere Text.HTML.TagSoup 

De modul Alfred ( starter en modul. Alle Haskell filer er moduler. Inne i parentesen defineres funksjonene som denne modulen vil gjøre tilgjengelig. Alle Haskell Funksjonene starter med små bokstaver. Hvis modulen skal være hovedprogrammet, må den ha en hoved- funksjon. Siden dette er et bibliotek, har det bare funksjoner og konstantdeklarasjoner.

Etter å ha erklært modul og hva den eksporterer, skriver du listen over de forskjellige biblioteker som brukes. Dette biblioteket bruker tre biblioteker: System.Process, System.Directory, System.Environment, og Text.HTML.TagSoup som vi lastet ned med Cabal.

cacheDirBasic :: String cacheDirBasic = "/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data /" dataDirBasic :: String dataDirBasic = "/ Bibliotek / Application Support / Alfred 2 / Workflow Data /" start :: String start = ""End :: String End ="" 

Deretter definerer jeg tre konstanter. Den første linjen er typen erklæring med den faktiske definisjonen under den. De :: symbolet erklærer at de neste elementene er typedeklarasjoner. Her definerer vi konstanter som en string type.

addItem :: String -> String -> String -> String -> String -> String -> String -> String addItem a b c d e f g = ""++ e ++""++ f ++""++ g ++"" 

De addItem funksjonen tar syv string innganger og lager XML-elementet string som utgang. Legg merke til at typen erklæring ligner åtte string typer skilt av ->. De -> symbolet viser neste type. De første syv typene er inngangen med den siste som er returverdien. Alle funksjoner i Haskell må ha en returverdi.

addItemBasic :: String -> String -> String -> String -> String addItemBasic a b c d = addItem a b "ja" "" c d "icon.png" 

De addItemBasic bruker addItem funksjon for å lage et XML-element med tre av inngangene satt til en standardverdi.

getBundleID :: IO (String) getBundleID = gjør tagger <- fmap parseTags $ readFile "info.plist" let id = fromTagText $ dropWhile (~/= "") (partisjoner (~ =="") tagger !! 0) !! 1 retur id 

De getBundleID få IDen til Alfred Workflow-bunten fra Info.plist fil i arbeidsflytkatalogen. Denne filen er en ren tekst plist. Siden dette er en type XML eller HTML-format, TextSoup biblioteket fungerer veldig bra for å lese det og avkode det. Dette er en monad-funksjon (enkelt sett, en funksjon som samhandler med elementet utenfor programmet. For eksempel: filer, GUI, osv.) Du kan lære mer om monader i monads opplæring. Enhver funksjon med returtype av IO () er en monad for inngangs- eller utgangsfunksjoner.

Her bryter den funksjonelle programmeringsstilen ned til en liste over elementer. De gjøre søkeord sier "gjør følgende i orden".

Den første linjen etter gjøre leser i Info.plist fil og analyserte merkene ved hjelp av parseTags fra TextSoup bibliotek. Den andre linjen finner den første dict tag og slipp alt til string stikkord. Den ekstraherer deretter innholdene i koden og plasserer den i den trasistiske konstanten id. id er en konstant fordi det er verdi kan ikke forandre seg. Siden alt alfred Info.plist filer har nøyaktig samme layout, jeg trenger ikke å teste nøkkelen for å være riktig. De id verdien returneres deretter.

getAlfredDataFileContents :: String -> IO (String) getAlfredDataFileContents fileName = do h <- getHomeDirectory id <- getBundleID let fPath = h ++ dataDirBasic ++ id ++ "/" ++ fileName fExist <- doesFileExist fPath if fExist then do contents <- readFile fPath return contents else return "" 

Den neste monadfunksjonen får innholdet i en fil som er i Alfred Data Directory for arbeidsflyten og returnerer den til anropsfunksjonen. Funksjonen får først brukerens hjemmedirektorat, får bunte-ID, skaper en bane til Alfred Data Directory for arbeidsflyten, og returnerer innholdet til den filen hvis den eksisterer. Ellers returnerer funksjonen en tom streng.

putAlfredDataFileContents :: String -> String -> IO () putAlfredDataFileContents fileName dataStr = do h <- getHomeDirectory id <- getBundleID writeFile (h ++ dataDirBasic ++ id ++ "/" ++ fileName) dataStr 

Den neste monaden gjør det motsatte. Det tar et filnavn og dataene som skal lagres i den filen. Siden innholdet vil bli lagt inn i filen som heter om den eksisterer eller ikke, må eksistensen av filen ikke bestemmes.

getAlfredCacheFileContents :: String -> IO (String) getAlfredCacheFileContents fileName = do h <- getHomeDirectory id <- getBundleID let fPath = h ++ cacheDirBasic ++ id ++ "/" ++ fileName fExist <- doesFileExist fPath if fExist then do contents <- readFile fPath return contents else return "" putAlfredCacheFileContents :: String -> String -> IO () putAlfredCacheFileContents filnavn dataStr = gjør h <- getHomeDirectory id <- getBundleID writeFile (h ++ cacheDirBasic ++ id ++ "/" ++ fileName) dataStr 

De to siste monadfunksjonene i biblioteket leser og skriver filer i Alfred Cache katalog for arbeidsflyten.

Haskell Case Converter

Med biblioteket opprettet, er det å skrive en arbeidsflyt. Opprett en ny arbeidsflyt i alfred kalt Haskell Text Converter som vist:

De Skriptfilter skal se slik ut:

Nå klikker du på Åpne arbeidsflytmappe. Dette åpner mappen for arbeidsflyten i finneren. Sett en kopi av Alfred.hs i det. Lag nå filen cases.hs og plasser denne koden der:

modul Hoved hvor import System.Environment import System.Exit import Data.List importere Data.Char import kvalifisert Data.ByteString importere kvalifisert Alfred som AL - - Alle ordene som skal være store og små bokstaver. - upperWordsList = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "HTML" CSS "," AT & T "," PHP "," UI ") - - Alle ordene skal bare være små bokstaver. - lowerWordsList = ["til", "for", "om", "inn", "på", " eller "," er "," med "," en "," "," av "," vs "," vs. "," via "," via "," en "] toWordLower :: String -> String toWordLower a = map toLow a toWordUpper :: String -> String toWordUpper a = map toUpper a toFirstLetterUpper :: [Char] -> [Char] toFirstLetterUpper [] = [] toFirstLetterUpper (a: []) = toUpper a: [] toFirstLetterUpper (a: ax) = toUpper a: toWordLower øks tilFirstLetterUpperOnly :: [Char] -> [Char] toFirstLetterUpperOnly [] = [] toFirstLetterUpperOnly (a: []) = toUpper a: [] tilFirstLetterUpperOnly (a: ax) = toUpper a: akse tilFirstLetterLowerOnly :: [Char] -> [Char] toFirstLetterLowerOnly [] = [] tilFirstLetterLowerOnly (a: []) = toLower a: [] toFirstLetterLowerOnly (a: ax) = toLower a: ax toTitleCase :: [Char] -> [Char] toTleleCase [] = [] toTitleCase a | elem (toWordUpper a) upperWordsList = toWordUpper a | elem (toWordLower a) lowerWordsList = toWordLower a | ellers = toFirstLetterUpper en processLine :: String -> (String -> String) -> [String] -> String processLine "" f [a] = concatMap f $ ord en prosesslinje cf [a] = init $ concatMap ) $ map f $ ord a procLower :: [String] -> String procLower [a] = toWordLower en procUpper :: [String] -> String procUpper [a] = toWordUpper en procSentence :: [String] -> String procSentence [ a] = toFirstLetterUpper en procTitle :: [String] -> String procTitle a = toFirstLetterUpperOnly $ processLine ""TitleCase en procCamel :: [String] -> String procCamel a = toFirstLetterLowerOnly $ processLine" tilFirstLetterUpper en procSlash :: [String] - > String procSlash a = processLine "/" toWordLower a procPascal :: [String] -> String procPascal a = processLine "" tilFirstLetterUpper en procCobra :: [String] -> String procCobra a = processLine "_" tilFirstLetterUpper en procDot :: [ String] -> String procDot a = processLine "." toWordLower a procDash :: [String] -> String procDash a = processLine "-" toWordLower en addItemCase :: String -> String -> String -> String addItemCase abc = AL.addItemBasisk abbc alfredScript :: [String] -> IO ) "alfredScript [] = putStr" "alfredScript [caseStr] = gjør putStr AL.begin putStr (addItemCase" HTCTitle "(procTitle [caseStr])" Tittel Case ") putStr (addItemCase" HTCLower "(procLower [caseStr] putStr (addSteenceCase "caseUp") "Saks tilfelle") putStr (addItemCase "HTCCamel" (procCamel [caseStr]) "Camel Tilfelle ") putStr (addItemCase" HTCSlash "(procSlash [caseStr])" Slash Case ") putStr (addItemCase" HTCPascal "(procPascal [caseStr])" Pascal Case ") putStr (addItemCase" HTCCobra "(procCobra [caseStr])" Cobra Case ") putStr (addItemCase" HTCDot "(procDot [caseStr])" Dot Case ") putStr (addItemCase" HTCDash "(procDash [caseStr])" Dash Case ") putStr AL .end main = gjør args <- getArgs alfredScript args 

Denne koden tar inn en streng fra kommandolinjen og genererer Alfred Script Filter xml format med ni forskjellige saktyper.

De tittel tilfelle format bruker to lister med ord for å gjøre hele store eller små bokstaver. Den faktiske funksjonen toTitleCase bruker kondisjonstegn for å se om ordet er i hovedliste eller i små bokstaver. Hvis det er, gjør det på den måten. Ellers bare gjør det første bokstaveret store bokstaver.

Hjelperfunksjonen processLine tar en streng og en funksjon, bruker funksjonen til alle oppføringer i en liste med strenger, legger strengen til hver oppføring, og sammenkobler de resulterende strengene sammen. Denne funksjonen behandler mange av saken konverteringer på en full streng.

Jeg opprettet en hjelperfunksjon addItemCase som dupliserer arg verdi til tittel verdi i addItemBasic fungere i alfred bibliotek. Funksjonell programmering handler om å skape funksjon av funksjoner som får jobben gjort uten varialbles!

De fleste av de andre funksjonene er ganske enkle å finne ut. Jeg gir deg oppdraget å studere dette slik at du kan lage din egen Haskell arbeidsflyt.

For å kompilere programmet, skriv dette på kommandolinjen i katalogen i arbeidsflyten:

ghc cases.hs 

Med programmet kompilert og arbeidsflyten opprettet, kan du nå bruke den til å konvertere strenger. I Alfred Prompt, type ht: conv dette er en test .

Ovenstående bilde viser resultatet. Velg den du vil ha, og den er plassert i utklippstavlen. Nedlastingsfilen inneholder en kopi av denne arbeidsflyten. Jeg har også en utvidet versjon tilgjengelig på Haskell Text Converter på Packal.org.

Også, jeg forbedrer stadig og legger til Alfred Library i Haskell. Du kan alltid få den nyeste versjonen på Alfred Library i Haskell GitHub Repository.

Konklusjon

I denne veiledningen har jeg vist deg hvordan du installerer Haskell Opprett en Mac på Mac alfred bibliotek for å hjelpe til med å skape nye arbeidsflyter, og laget en prøve-arbeidsflyt med biblioteket. Nå er det din tur å gjøre noe bra Alfred Workflows. Vennligst del dem i kommentarene nedenfor.