Spåra projekttid med Alfred Timekeeper

Vad du ska skapa

Alfred Time Keeper

Många människor jonglera flera projekt med olika tidsplaner. Från webbapps till dedikerade program finns det redan ett antal sätt att hålla koll på tid som spenderas på ett projekt. De flesta kräver nät service och / eller ett program att hålla sig igång hela tiden. Ofta är det inte praktiskt.

Alfred Timekeeper fungerar på samma sätt som ett system för korthållning: du sparar tidstämpel när du börjar och slutar arbeta. Eftersom det bara registreras tidsstämplar är ett program eller en webbtjänst inte alltid öppen.

I denna handledning antar jag att du redan är bekant med att skriva arbetsflöden i Alfred. Om inte, kolla in dessa handledningar: Alfred for Beginners, Intermediates, Advanced Users och Alfred Debugging.

Övergripande Design

Många arbetar med olika datorer på olika platser. Det gör det svårare att hålla reda på projekt och tidshantering. Genom att använda Dropbox synkroniseras all information om projekt och tidshantering automatiskt.

Detta tillvägagångssätt kräver att all information hålls i filer och inte i datorminnet. Denna begränsning kräver användning av två datalagringsarrangemang: lokal katalog av information som endast används av det systemets program, och a synkroniserad katalog som delas med varje dator som är ansluten till den.

Den lokala lagringen innehåller hänvisningen till den synkroniserade katalogen och redigeraren för att redigera tidskrifter. Dessa filer finns i Alfreds datalägesplats.

Den synkroniserade katalogen håller alla tidtabeller, listor över projekt, senast kända tillstånd för inspelningsinformation och tidszoninformationen. Det kommer att ligga i en Dropbox-plats. Alla filsystem synkroniseringssystem kan användas, jag råkar bara ha Dropbox redan.

Skapa arbetsflödet

I Alfred skapar du ett nytt arbetsflöde som heter Alfred Timekeeper.

Skapa arbetsflödet

I det här nya arbetsflödet måste du skapa en Filfilter som bara kommer att lista kataloger.

Ställ in tidskriftsregisterkommando

Du kan ställa in Filtyper genom att dra en katalog från Upphittare till Filtyper område. Ställ in Sökomfattning till katalogen som innehåller ditt DropBox-konto.

Lägg till en Kör skript blockera efter det här blocket, avmarkera alla escape-alternativen. Till det blocket lägger du till det här skriptet:

####### Kontanter. ######## VPREFS = "$ HOME /Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data /" NVPREFS = "$ HOME / Bibliotek / Application Support / Alfred 2 / Workflow Data /" ################################################################## ############################################### # Läs bundled från arbetsflödet info.plist ###################################### ############ getBundleId () / usr / libexec / PlistBuddy -c "Skriv ut: bundled "" info.plist " ##################################################### ##################### Få arbetsflödesdata dir ######## ################################################## ####### () local BUNDLEID = $ (getBundleId) echo "$ NVPREFS $ BUNDLEID" om [! -d "$ (getDataDir)"]; då mkdir -p "$ (getDataDir)"; tryck på "$ (getDataDir) /dir.txt"; tryck på "$ (getDataDir) /editor.txt"; fi # Spara kataloginformationen. eko "query"> "$ (getDataDir) /dir.txt"; # Berätta för användaren. echo "Ange katalog till" query '. "; 

Detta skript kontrollerar att datakatalogen finns där. Om det inte finns skapas det katalogen och de filer som används för arbetsflödet. Det tar inmatningen i fråga makro och placerar det i dir.txt filen i datakatalogen. Den meddelar då användaren av åtgärden.

Anslut Kör skript blockera till ett anmälningsblock. Allt Kör skript block härifrån ska anslutas till det här anmälningsblocket. Ställ in dess utgång för att vara fråga makro och ställa in Visa bara om godkänt i argument har innehåll.

När du väl har sparat, ställa in kalkylbladet. Inne i Dropbox-katalogen, skapa en katalog för tidsblad och använd atk: setdir kommandot för att ställa in den katalogen. Du kör nu ett system för tidssystem för flera system!

Det är den grundläggande installationsrutinen för arbetsflödet. Innan du tar itu med huvudprogrammet måste du ställa in arbetsmiljön.

Ställa in Go-miljön

Det enklaste sättet att installera go programmeringsspråket är by homebrew. Om du inte har installerat homebrew men handledningen Homebrew Demystified: OS X: s Ultimate Package Manager kommer att visa dig hur.

I en terminal skriver du:

brygga installationen gå 

Skapa katalogen i hemkatalogen . Go-språket lagrar alla nedladdade bibliotek där. Lägg till i .bashrc fil och / eller .zshrc fil den här raden:

exportera GOPATH = "/ Användare //gå" 

Om du använder fisk, lägg till det här till config.fish fil:

set -xg GOPATH "/ Användare //gå" 

Efter omladdning av skalet kan du installera goAlfred-biblioteket genom att skriva:

gå och få github.com/raguay/goAlfred 

Detta bibliotek gör det lättare att använda språket med Alfred. Det kommer att skapa kataloger till datalagringsområdet för Alfreds arbetsflöden och göra XML-noteringen nödvändig Script Filters.

Timekeeper.go

För att skapa huvudprogramfilen måste du gå till katalogen för arbetsflödet. Öppna Kör skript blockera.

Öppnar Workflow Directory

Klicka på Öppna arbetsflödesmapp knappen längst ner på Manus: område. Detta öppnar arbetsflödeskatalogen i Upphittare (eller Stigfinnare om du har det). För att öppna katalogen i ett terminalskal kan du använda Alfred Workflow TerminalFinder för att öppna en Finder- eller Path Finder-katalog i en terminalsession (eller iTerm).

Skapa programfilen i terminalen

En gång i terminalprogrammet skriver du:

tryck på Timekeeper.go 

Öppna den filen i valfri redigerare. Öppna den här koden när den är öppen:

paketets huvud // // Program: TimeKeeper.go // // Beskrivning: Detta program kör återkopplingslogiken för att välja på / av-tillståndet för // det aktuellt tidsbestämda projektet. // // // Importera de bibliotek vi använder för det här programmet. // // ("fmt" "github.com/raguay/goAlfred" "io" "io / ioutil" "os" "regexp" "strconv" "strängar" "tid") // // Uppställning och konstanter som används . // // MAXPROJECTS Detta är det maximala antalet tillåtna projekt. // TSDir Detta håller katalognamnet för tidskrifterna. Det är en komplett väg. // const (MAXPROJECTS int = 20) var TSDir = "" // // Funktion: huvud // // Beskrivning: Detta är huvudfunktionen för TimeKeeper-programmet. Det tar kommandoraden // och analyserar den för rätt funktionalitet. // func main () om len (os.Args)> 1 switch os.Args [1] [0] case 'm': // // atk: month // SystemViewMonth () case 'w': // // atk: vecka // SystemViewWeek () fallet 't': // // atk: current // SystemViewDate () fallet 'r': // // atk: remove // ​​RemoveProject () fallet 'c' : // // atk: project // ChangeProject () fallet 'b': // // atk: current // SystemViewDay () fallet 'a': // // atk: addproject // AddProject () fallet ' ': // // atk: state // StopStart () fallet' p ': // // Används för atk: projekt script fileter // projekt () fallet' T ': // // atk: time // SystemAllProjects () fall: s: fallgrops default: // // Används för skriptfiltret på atk: state // state () // // Funktion: getTimeSheetDir // // Beskrivning: Den här funktionen används för att cacha en kopia av tid // arkarkatalogen och ge den i retur. // func getTimeSheetDir () sträng if strings.Contains ("", TSDir) Filnamn: = goAlfred.Data () + "/dir.txt" buf, err: = ioutil.ReadFile (Filnamn) om err == nil // // Konvertera katalogvägen till en sträng och trimma den. // TSDir = strings.TrimSpace (sträng (buf)) // // Återgå katalogen till tidskrifterna. // return (TSDir) // // Funktion: SystemAllProjects // // Beskrivning: Denna funktion kommer att visa till terminalen tiden för alla projekt på // dagen som anges på kommandoraden nästa. // func SystemAllProjects () // // Hämta det aktuella datumet om det inte finns någon på kommandoraden. // tm: = time.Now () om len (os.Args)> 2 om strings.Contains ("today", os.Args [2]) // // Dagens datum. // tm = time.Now () annars om strings.Contains ("igår", os.Args [2]) // // Igår är idag minus en dag. // tm = time.Now () tm = tm.AddDate (0, 0, -1) else // // Parsa den angivna datumsträngen. // tm, _ = time.Parse ("2006-Jan-02", os.Args [2]) // // Hämta listan över projektnamn. // proj: = GetListOfProjects () // // För varje projekt, ta tid på den för den angivna dagen. // numproj: = len (proj) - 1 för i: = 0; jag < numproj; i++  fmt.Printf("%s: %s\n", proj[i], formatTimeString(GetTimeAtDate(proj[i], tm)))   // // Function: SystemViewMonth // // Description: This function will calculate the time the current month for all the projects. // func SystemViewMonth()  // // Get the current project. // currentProject := GetCurrentProject() // // Get the time on that project for this month. The current time gives the current month. // tm := GetTimeAtMonth(currentProject, time.Now()) // // format the time string and print it out. // fmt.Print(formatTimeString(tm))  // // Function: GetTimeAtDate // // Description: This function will take a project and calculate the time spent // on that project for a particular date. // func GetTimeAtMonth(project string, date time.Time) int64  tm := int64(0) dateStart := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.UTC) // // Get the time added up for the whole week. // for i := 0; i <= date.Day(); i++  tm += GetTimeAtDate(project, dateStart.AddDate(0, 0, i))  // // Return the amount of time calculated. // return (tm)  // // Function: SystemViewWeek // // Description: This function will calculate the time the current week for all the projects. // // Inputs: // variable description // func SystemViewWeek()  currentProject := GetCurrentProject() tm := GetTimeAtWeek(currentProject, time.Now()) fmt.Print(formatTimeString(tm))  // // Function: GetTimeAtDate // // Description: This function will take a project and calculate the time spent // on that project for a particular date. // func GetTimeAtWeek(project string, date time.Time) int64  tm := int64(0) dateStart := date dateEnd := date switch date.Weekday()  case 0:  dateEnd = dateEnd.AddDate(0, 0, 6)  case 1:  dateStart = dateStart.AddDate(0, 0, -1) dateEnd = dateEnd.AddDate(0, 0, 5)  case 2:  dateStart = dateStart.AddDate(0, 0, -2) dateEnd = dateEnd.AddDate(0, 0, 4)  case 3:  dateStart = dateStart.AddDate(0, 0, -3) dateEnd = dateEnd.AddDate(0, 0, 3)  case 4:  dateStart = dateStart.AddDate(0, 0, -4) dateEnd = dateEnd.AddDate(0, 0, 2)  case 5:  dateStart = dateStart.AddDate(0, 0, -5) dateEnd = dateEnd.AddDate(0, 0, 1)  case 6:  dateStart = dateStart.AddDate(0, 0, -6)   // // Get the time added up for th whole week. // for i := 0; i < 7; i++  tm += GetTimeAtDate(project, dateStart.AddDate(0, 0, i))  return (tm)  // // Function: SystemViewDate // // Description: This function will calculate the time for projects at a certain date. // func SystemViewDate()  currentProject := GetCurrentProject() tm := GetTimeAtDate(currentProject, time.Now()) fmt.Print(formatTimeString(tm))  // // function: SystemViewDay // // Description: This function is for displaying a nice time for the current project. // func SystemViewDay()  currentProject := GetCurrentProject() tm := GetTimeAtDate(currentProject, time.Now()) ctime := formatTimeString(tm) state := GetCurrentState() fmt.Printf("The current time on %s is %s. Current state is %s.", currentProject, ctime, state)  // // Function: GetTimeAtDate // // Description: This function will take a project and calculate the time spent // on that project for a particular date. // func GetTimeAtDate(project string, date time.Time) int64  // // Get the current project. // filename := generateTimeLogFileName(project, date) tm := readDayTime(filename) return tm  // // Function: formatTimeString // // Description: This function takes the number of seconds and returns a string // in hour:minute:seconds format with zero padding. // // Input: // tm time in seconds (an int64) // func formatTimeString(tm int64) string  min := int(tm / 60) sec := tm - int64(min*60) hr := min / 60 min = min - (hr * 60) return fmt.Sprintf("%02d:%02d:%02d", hr, min, sec)  // // Function: readDayTime // // Description: This function reads a time sheet file and calculates the time // represented in that file. func readDayTime(filename string) int64  buf, _ := ioutil.ReadFile(filename) times := regexp.MustCompile("\n|\r").Split(string(buf), -1) // // Loop through all the time lines. // tmwork := int64(0) firsttime := int64(0) first := false for i := 0; i < len(times); i++  if !strings.Contains("", times[i])  // // Split by colon to time and action. // parts := strings.Split(times[i], ":") if strings.Contains("start", parts[1])  firsttime, _ = strconv.ParseInt(parts[0], 10, 64) first = true  else  tm, _ := strconv.ParseInt(parts[0], 10, 64) tmwork += tm - firsttime first = false    // // If a start was the last thing processed, that means it is still being timed. Get the // current time to see the overall time. firsttime is the time stamp when the start // was given. // if first  currentTime := time.Now() ctime := currentTime.Unix() tmwork += ctime - firsttime  // // Return the final Time. // return tmwork  // // Function: RemoveProject // // Description: This function will remove a project from the list a valid projects. // func RemoveProject()  // // Get the project name from the command line. // proj := GetCommandLineString() // // Get the list of project names. // projects := GetListOfProjects() // // Open the projects file in truncation mode to remove all the old stuff. // Filename := getTimeSheetDir() + "/projects.txt" Fh, err := os.OpenFile(Filename, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0666) if err != nil  // // The file would not open. Error out. // fmt.Print("Could not open the projects file: ", Filename, "\n") os.Exit(1)  // // Loop through all the projects. // for i := 0; i < len(projects); i++  if !strings.Contains(proj, projects[i])  // // It is not the project to be removed. Put it into the file. // Fh.WriteString(projects[i] + "\n")   // // Close the file. // Fh.Close() // // Tell the user that the project has been removed. // fmt.Print(proj + " has been removed!")  // // Function: ChangeProject // // Description: This function will change the currently active project. If the old // project was started, it will stop it first, then set the new project // and start it. // func ChangeProject()  // // Get the project name from the command line. // proj := GetCommandLineString() // // Get the current project. // currentProject := GetCurrentProject() // // Stop the current project. // StopStartProject(currentProject, "stop") // // Save the new project to the data file. // SaveProject(proj) // // Start the new project. // StopStartProject(proj, "start") // // Tell the user it is started. // fmt.Print("The current project is now " + proj + " and is started.")  // // Function: GetCommandLineString // // Description: This function is used to get the after the function if there is one. // If not, then just return nothing. // func GetCommandLineString() string  // // See if we have any input other then the command. // clstring := "" if len(os.Args) > 2 clstring = strings.TrimSpace (os.Args [2]) // // Återgå strängen. // return (clstring) // // Funktion: AddProject // // Beskrivning: Den här funktionen lägger till ett nytt projekt i listan över aktuella projekt. // func AddProject () // // Hämta projektnamnet från kommandoraden. // proj: = GetCommandLineString () // // Skapa filnamnet som innehåller alla projekt. // projectFile: = getTimeSheetDir () + "/projects.txt" Fh, err: = os.OpenFile (projectFile, os.O_APPEND | os.O_WRONLY | os.O_CREATE, 0666) om err! = nil Fh, err = os.Create (projectFile) om err! = nil // // Filen skulle inte öppnas. Fel ut. // fmt.Print ("Kunde inte öppna projektfilen:", projectFile, "\ n") os.Exit (1) // // Skriv det nya kommandot med tidsstämpeln till bufferten. // _, err = io.WriteString (Fh, proj + "\ n") // // Förlora filen. // Fh.Close () // // Berätta för användaren att projektet har lagts till. // fmt.Print ("Added project" + proj + "till listan.") // // Funktion: state // // Beskrivning: Den här funktionen ger rätt utgång för att ändra tillståndet. Staten // först är det motsatta från det nuvarande tillståndet. // func state () // // Hämta sista status för det aktuella projektet. // stateFile: = getTimeSheetDir () + "/laststate.txt" buf, _: = ioutil.ReadFile (stateFile) curState: = sträng (buf) // // Ställ in det första kommandot motsatsen till det aktuella läget. På så sätt // användaren trycker helt enkelt tillbaka till växelstat. // if strings.Contains (curState, "start") goAlfred.AddResult ("stop", "stop", "stop", "", "icon.png", "yes", "", "" goAlfred .AddResult ("start", "start", "start", "", "icon.png", "yes", "", "") annars goAlfred.AddResult ("start", "start" starta "," "," icon.png "," ja "," "," ") goAlfred.AddResult (" stop "," stop "," stop "," "," icon.png " , "", "") // // Skriv ut xml-strängen. // fmt.Print (goAlfred.ToXML ()) // // Funktion: projekt // // Beskrivning: Den här funktionen skapar en lista över projekten och visar de // som liknar inmatningen. // func-projekt () // // Hämta projektnamnet från kommandoraden. // proj: = GetCommandLineString () // // Ange vår standardsträng. // goAlfred.SetDefaultString ("Alfred Time Keeper: Sorry, no match ...") // // Få det senaste projektet. // senaste projekt: = GetCurrentProject () // // Hämta listan över projekt. // projects: = make ([] sträng, MAXPROJECTS) projects = GetListOfProjects () // // Regexp split statement ger en sträng mer än delades ut. Den sista // strängen är en catchall. Det behöver inte ingå. // numproj: = len (projekt) - 1 // // Skapa ett resultatlista för varje projekt. Visa alla sätta det aktuella projektet. // för i: = 0; jag < numproj; i++  if !strings.Contains(projects[i], latestproject)  goAlfred.AddResultsSimilar(proj, projects[i], projects[i], projects[i], "", "icon.png", "yes", "", "")   // // Print out the xml string. // fmt.Print(goAlfred.ToXML())  // // Function: GetListOfProjects // // Description: This function will return an array of string with the names of the project. // func GetListOfProjects() []string  // // Create the projects array and populate it. // projectFile := getTimeSheetDir() + "/projects.txt" buf, _ := ioutil.ReadFile(projectFile) // // Split out the different project names into separate strings. // return (regexp.MustCompile("\n|\r").Split(string(buf), -1))  // // Function: StopStart // // Description: This will place a start or stop time stamp for the current project and // current date. // func StopStart()  // // See if we have any input other then the command. If not, assume a stop command. // cmd := "stop" if len(os.Args) > 2 cmd = strings.ToLower (os.Args [2]) // // Hämta det aktuella projektet. // currentProject: = GetCurrentProject () // // Kör lämplig funktion och skriv ut resultaten. // fmt.Print (StopStartProject (currentProject, cmd)) // // Funktion: GetCurrentProject // // Beskrivning: Den här funktionen hämtar det aktuella projektet från // state-filen. // func GetCurrentProject () sträng // // Hämta det aktuella projektet. // Filnamn: = getTimeSheetDir () + "/project.txt" buf, _: = ioutil.ReadFile (Filnamn) // // Konvertera det aktuella projektet till en sträng, trimma det och returnera det. // return (strings.TrimSpace (string (buf))) // // Funktion: SaveProject // // Beskrivning: Den här funktionen sparar det angivna projektnamnet till // aktuell projektfil. // // Inputs: // proj Namnet på det nya projektet // func SaveProject (proj string) // // Skriv det nya projektet. // Filnamn: = getTimeSheetDir () + "/project.txt" err: = ioutil.WriteFile (Filnamn, [] byte (proj), 0666) om err! = Nil fmt.Print ("Kan inte skriva projektfilen : "+ Filnamn) os.Exit (1) // // Funktion: StopStartProject // // Beskrivning: Den här funktionen används för att ställa in tillståndet för det angivna projektet. // // Inputs: // currentProject Projektet för att åstadkomma tillståndet för. // cmd Start- eller stoppkommandot. // func StopStartProject (currentProject string, cmd string) string // // Ställ in resultatsträngen. // resultStr: = "" currentState: = GetCurrentState () // // Är det aktuella läget detsamma som det nya läget? // om strings.Contains (cmd, currentState) // // Det är redan i det läget. Gör ingenting, men ge ett meddelande. // resultStr = "Already" + cmd + "\ n" else // // Okej, vi kan fortsätta skriva den nya staten i // daterad projektfil. Öppna filen för att skriva. // currentTime: = time.Now () Filnamn: = generateTimeLogFileName (currentProject, currentTime) Fh, err: = os.OpenFile (Filnamn, os.O_APPEND | os.O_WRONLY | os.O_CREATE, 0666) om err! = nil  // // Filen skulle inte öppnas. Fel ut. // fmt.Print ("Kunde inte öppna den daterade projektfilen:", Filnamn, "\ n") os.Exit (1) // // Skriv det nya kommandot med tidsstämpeln till bufferten. // str: = fmt.Sprintf ("% d:% s \ n", currentTime.Unix (), cmd) _, err = io.WriteString (Fh, str) // // Förlora filen. // Fh.Close () // // Skriv filen laststate med den nya staten. // ioutil.WriteFile (getTimeSheetDir () + "/ laststate.txt", [] byte (cmd), 0666) // // Berätta användaren är den inställd. // resultStr = currentProject + "är nu" + cmd // // Återgå den resulterande strängen. // return (resultStr) // // function: GetCurrentState // // Beskrivning: Den här funktionen får projektets aktuella status. // func GetCurrentState () sträng // // Hämta nuvarande tillstånd. // Filnamn: = getTimeSheetDir () + "/laststate.txt" buf, err: = ioutil.ReadFile (Filnamn) currentState: = "stop" om err == nil // // Konvertera det aktuella projektet till en sträng och trimma det. // currentState = strings.TrimSpace (sträng (buf)) return currentState // // Funktion: generateTimeLogFileName // // Beskrivning: Dessa funktioner skapar loggfilen baserat på projektnamnet och // datumet. // // Inputs: // proj Namn på projektet // dt Datum ifråga // func generateTimeLogFileName (projsträng, dt time.Time) string // // Skapa det riktiga filnamnet baserat på projektnamn och datum . // filnamn: = getTimeSheetDir () + "/" + proj + "_" + dt.Format ("2006-01-02") + ".txt" returnera (filnamn) 

Den koden definierar alla funktioner i Alfred Timekeeper. Programmets utformning är att göra olika funktioner baserade på ett kommandobrev och alternativparametrar efter det. Det kommer att hämta kalkylbladet från Alfred och skapa projektfiler och tidskrifter efter behov.

sammanställa

Du måste sammanställa programmet innan du kan använda det. Go-språket är inte ett tolkat språk, men ett sammanställt språk. Detta gör det möjligt för programmet att springa mycket snabbare.

I terminalprogrammet skriver du:

gå bygg Timekeeper.go 
Sammanställning Timekeeper.go

Om allt är på plats ordentligt, borde du nu ha Tidmätare program i den katalogen. Det är i rött ovanför. Om något inte kopierades rätt och kompileringen misslyckas, leta upp linjenummeret och jämför det med ovanstående. Eller skaffa en ny kopia från nedladdningen som ges med denna handledning.

Lägga till Alfred-funktioner

När programmet är klart måste du ringa det från Alfred. Skapa en Nyckelord blockera med sökordet satt till atk: addproject. Anslut den till en Kör skript blockera och sätt den här koden:

./ TimeKeeper en "query" 

Allt Kör skript block här ute bör vara inställd att springa våldsamt slag skript och ingen av de inställda escape-alternativen. Ovanstående skript låter skapa nya projekt. Använd detta för att skapa dina olika projekt. Jag har projekten: Envato, CustomCT, och uppdrag skapad för det arbete jag gör.

Nu när du har projekt måste du nu ställa in ett som det aktuella projektet. Skapa en Skriptfilter som nedan:

Skriptfilter för att välja ett projekt

Lägg till en Kör skript blockera efter det med följande skript:

./ Timekeeper c "query" 
Ställa in projektet

Nu kan du ställa in det projekt du vill arbeta med. I Alfred Prompt, skriv ATK: projekt och en lista över de skapade projekten ska visas. Välj det projekt du vill ha och det startar automatiskt timing för dig.

Därför, om du valde Handledningar projekt, det finns en fil som heter Tutorials_2014-05-05.txt (det vill säga så länge du skapade den den 5 maj 2014). Inuti den filen är en tidsstämpel, en kolon och a Start påstående. Du kommer också att ha project.txt fil med det aktuella valda projektet, laststate.txt fil med sista tillståndet (dvs: Start eller sluta), och den projects.txt fil med en lista över skapade projekt.

Tidpunkten har börjat, men nu måste du stoppa det. Skapa en ny Skriptfilter blockera med sökordet satt till atk: tillstånd och manuset satt till:

./ TimeKeeper s "query" 

Det borde ansluta till en Kör skript blockera med manuset satt till:

./ TimeKeeper o "query" 

De s kommando berättar Timekeeper-programmet för att generera en XML-utgång för nästa tillstånd. Det kommer automatiskt att ha det första alternativet i XML att vara motsatsen till det aktuella tillståndet.

Ändra timing-stater

Du kan nu byta status för ett projekt med atk: tillstånd. Du kan också skapa snabbtangenter för att starta och stoppa timingen. Försök att göra det själv på egen hand. Du lär dig aldrig tills du försöker!

Lägga till en extern utlösare

Du kanske vill att ett externt program ska ställa in tiden för inspelning av tid. Skapa därför en Extern utlösare blockera som visas. Anslut det här blocket till föregående Kör skript blockera.

Lägga till en extern utlösare - Konfiguration

De Provkod längst ner kan spåras av vilket AppleScript-medveten program som ska utlösa start / stopp åtgärder på det aktuella projektet. Om du ersätter texten testa med sluta, det kommer att sluta timing. Om du ersätter texten testa med Start, det kommer att börja timing. Används med ControlPlane, Du kan skapa en regel för att stänga av timing när datorn sover och fortsätter timing när datorn vaknar.

Nu när du börjar och stoppar tiden måste du se tiden. Skapa en Nyckelord blockera med atk: ström. Anslut den till en Kör skript blockera med det här skriptet:

eko "./Timekeeper b '; 

Anslut den till Underrättelse blockera.

Nuvarande tidskommando

När du kör atk: ström i Alfred prompt får du den aktuella tiden på projektet och nuvarande tillstånd.

Andra datorn

Om du har en annan dator, ställ in Alfred för att dela över Dropbox. När du har konfigurerat uppdateras alla dina arbetsflöden automatiskt från en dator till en annan.

Konfigurera Alfred Syncing

Välj Ange synkroniseringsmapp att konfigurera synkronisering via Dropbox och följ anvisningarna. Använd kommandot på den andra datorn atk: setdir för att ställa in kalkylbladskatalogen du skapade i Dropbox. De två systemen kan nu starta och stoppa projektets timing. Se till att Dropbox är helt synkroniserad mellan tillståndsändringar.

Slutsats

Det är grunden för Alfred Timekeeper. Arbetsflödet som är förpackat med hämtningen är den fullständiga versionen med andra funktioner. Du förstår nu hur du skapar ditt eget tidhanteringssystem som är skalbart att använda på flera datorer med Dropbox och tar inte upp datorns resurser. 

Eftersom jag använder det här varje dag kommer jag att lägga till fler funktioner som ett webgränssnitt för att se tidskrifterna grafiskt. Om du kan komma med andra funktioner, försök att lägga till dem själv! Det är roligt att arbeta med Alfreds arbetsflöden.