package main import ( //"os" "fmt" "strconv" "strings" "time" "github.com/abiosoft/ishell" //"github.com/EPRparadox82/ishell" "github.com/fatih/color" ) //var mastercol *color.Color func interact(fulldb bool) { //stdOut() shell := ishell.New() shell.SetMultiChoicePrompt(" ->", " - ") shell.SetChecklistOptions("[ ] ", "[X] ") //fmt.Println(os.Args) //cyan := color.New(color.FgCyan).SprintFunc() //yellow := color.New(color.FgYellow).SprintFunc() //green := color.New(color.FgGreen).SprintFunc() boldBlue := color.New(color.FgBlue, color.Bold).SprintFunc() boldRed := color.New(color.FgRed, color.Bold).SprintFunc() boldMag := color.New(color.FgMagenta, color.Bold).SprintFunc() boldCyan := color.New(color.FgCyan, color.Bold).SprintFunc() boldGreen := color.New(color.FgGreen, color.Bold).SprintFunc() boldYell := color.New(color.FgYellow, color.Bold).SprintFunc() promptcol := boldBlue //PromptColor(GetColor()) if fulldb { promptcol = PromptColor(GetColor()).SprintFunc() } // display info. //shell.Println("Starting interactive Shell") shell.SetPrompt(promptcol(">>>")) // New Customer / New Project { newcmd := &ishell.Cmd{ Name: "new", Help: "project / customer", LongHelp: ` Usage: new `, } newcmd.AddCmd(&ishell.Cmd{ Name: "project", Help: "Start new Project", LongHelp: ` Usage: new project If no Task is currently running a new project will be added to database and opened. When there is an open Task the user will be notified to stop it before adding a new Project`, Func: func(c *ishell.Context) { //c.Print("\033[H\033[2J") //c.Println(boldGreen("Start New Project")) newProject() //showLastProject() stdOut() c.Println(promptcol("______________________")) }, }) newcmd.AddCmd(&ishell.Cmd{ Name: "customer", Help: "Add new Customer", LongHelp: ` Usage: new customer Add a new Customer to Database`, Func: func(c *ishell.Context) { addCustomer() c.Println(promptcol("______________________")) }, }) paycmd := &ishell.Cmd{ Name: "payment", Help: "/now - Enter a Payment",// at a specific Time 'YYYY-MM-DD' Or 'now'", LongHelp: ` Usage: new payment /now Enter a new Payment at . Use Format "YYYY-MM-DD" for date. 'now' will start the Task at current local date.`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") if isDate(arg){ AddPayment(arg) }else{ c.Println(boldRed("new payment - Please enter a valid Date of Format 'YYYY-MM-DD'")) } } else { c.Println(boldRed("new payment - Please enter a Date")) } stdOut() c.Println(promptcol("______________________")) }, } paycmd.AddCmd(&ishell.Cmd{ Name: "now", Help: "Enter a new Payment dated today", LongHelp: ` Usage: new payment now Enter a new Payment with current local date`, Func: func(c *ishell.Context) { AddPayment("jetzt") stdOut() c.Println(promptcol("______________________")) }, }) newcmd.AddCmd(paycmd) shell.AddCmd(newcmd) } shell.AddCmd(&ishell.Cmd{ Name: "resume", Help: "Resume the Paused Task", LongHelp: ` Usage: resume Resume the Task that was paused 'now'.`, Func: func(c *ishell.Context) { newTask(true) stdOut() setPauseTask(0) c.Println(promptcol("______________________")) }, }) shell.AddCmd(&ishell.Cmd{ Name: "pause", Help: "Close the Current Task and remember it", LongHelp: ` Usage: pause Closes the current task 'now' and remember it to continue later. The User is not asked to enter a comment.`, Func: func(c *ishell.Context) { if opentask.Id > 0 { setPauseTask(opentask.Id) c.Println("Pausing Task", pausetask) } closeTask(false) stdOut() c.Println(promptcol("______________________")) }, }) shell.AddCmd(&ishell.Cmd{ Name: "status", Help: "Show Current Project and Tasks", LongHelp: ` Usage: status Shows the current Project, its last Tasks and if there is a open Task.`, Func: func(c *ishell.Context) { //stdOut() showStatus(true) c.Println(promptcol("______________________")) }, }) /* OLD CHECKBILL shell.AddCmd(&ishell.Cmd{ Name: "checkbill", Help: " check a Bill with the following id as paid", LongHelp: ` Usage: checkbill Check the bill of the set as paid on the current date`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { checkBill(argi) //stdOut() } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { c.Println(boldRed("checkbill - Please enter an id")) showLastBills(0) } c.Println(promptcol("______________________")) }, }) */ // Delete Commands: Bill / Task / Payment { delcmd := &ishell.Cmd{ Name: "delete", Help: "task / bill", LongHelp: ` Usage: delete `, } delcmd.AddCmd(&ishell.Cmd{ Name: "bill", Help: " Delete a Bill with the following id", LongHelp: ` Usage: delete bill Delete the bill of the set and set its Task back to unbilled`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { deleteBill(argi) stdOut() } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { c.Println(boldRed("deletebill - Please enter an id")) showLastBills(0) } c.Println(promptcol("______________________")) }, }) delcmd.AddCmd(&ishell.Cmd{ Name: "payment", Help: " Delete the Payment with the following id", LongHelp: ` Usage: delete payment Delete the payment of the set `, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { DeletePayment(argi) stdOut() } else { c.Println(boldRed(arg, " is not a valid id!")) } } else { selids, lids := GetPaymentList() choice := c.MultiChoice(lids, "Select a Payment to Edit") if choice > -1 { DeletePayment(selids[choice]) } } c.Println(promptcol("______________________")) }, }) delcmd.AddCmd(&ishell.Cmd{ Name: "task", Help: " Delete a Task with the following id", LongHelp: ` Usage: delete task Delete the Task of the set `, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { deleteTask(argi) stdOut() } else { c.Println(boldRed(arg, " is not a valid id!")) } } else { tids := GetTaskIds() selids, lids := GetTaskList(tids, false,false) choice := c.MultiChoice(lids, "Select a Task to Delete") if choice > -1 { deleteTask(selids[choice]) } //c.Println(boldRed("deletetask - Please enter an id")) //allProjects() } c.Println(promptcol("______________________")) }, }) shell.AddCmd(delcmd) } // OPEN PROJECT COMMAND shell.AddCmd(&ishell.Cmd{ Name: "project", Help: " Open a Project of the following id", LongHelp: ` Usage: project Open the Project with the set If there is an open Task the user will be notified to close it first.`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { setProject(argi) stdOut() } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { pids := GetProjectIds() selids, lids := getProjectList(pids) choice := c.MultiChoice(lids, "Select a Project to Edit") if choice > -1 { setProject(selids[choice]) } //c.Println(boldRed("editproject - Please enter an id")) //c.Println(boldRed("project - Please enter an id")) //allProjects() } c.Println(promptcol("______________________")) }, }) // EDIT COMMAND { editcmd := &ishell.Cmd{ Name: "edit", Help: " customer / payment / project / task", LongHelp: ` Usage: edit `, /* customer - Edit Customer of given id. project - Edit Project of given id. task - Edit Task of given id.`, */ } editcmd.AddCmd(&ishell.Cmd{ Name: "task", Help: " Edit a Task of the following id", LongHelp: ` Usage: edit task Edit Task of the set . Press on empty line to keep the old entry`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { editTask(argi) } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { tids := GetTaskIds() selids, lids := GetTaskList(tids, false,false) choice := c.MultiChoice(lids, "Select a Task to Edit") //c.Println(tids) //c.Println(selids) if choice > -1 { editTask(selids[choice]) //c.Println(choice,selids[choice]) } //c.Println(boldRed("edittask - Please enter an id")) } c.Println(promptcol("______________________")) }, }) editcmd.AddCmd(&ishell.Cmd{ Name: "project", Help: " Edit the Project of the following id", LongHelp: ` Usage: edit project Edit Project of the set . Press on empty line to keep the old entry`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { editProject(argi) //allProjects() //stdOut() } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { pids := GetProjectIds() selids, lids := getProjectList(pids) choice := c.MultiChoice(lids, "Select a Project to Edit") //c.Println(pids) //c.Println(selids) if choice > -1 { editProject(selids[choice]) //c.Println(choice,selids[choice]) } //c.Println(boldRed("editproject - Please enter an id")) //allProjects() } c.Println(promptcol("______________________")) }, }) editcmd.AddCmd(&ishell.Cmd{ Name: "payment", Help: " Edit the Payment of the following id", LongHelp: ` Usage: edit payment Edit Payment of the set . Press on empty line to keep the old entry`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { EditPayment(argi) } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { selids, lids := GetPaymentList() choice := c.MultiChoice(lids, "Select a Payment to Edit") if choice > -1 { EditPayment(selids[choice]) } } c.Println(promptcol("______________________")) }, }) editcmd.AddCmd(&ishell.Cmd{ Name: "customer", Help: " Edit the Customer of the following id", LongHelp: ` Usage: edit customer Edit Customer of the set . Press on empty line to keep the old entry`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { editCustomer(argi) allCustomers(false) //stdOut() } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { selids, lids := getCustomerList() choice := c.MultiChoice(lids, "Select a Customer to Edit") if choice > -1 { editCustomer(selids[choice]) } //c.Println(boldRed("editcustomer - Please enter an id")) //allCustomers() } c.Println(promptcol("______________________")) }, }) editcmd.AddCmd(&ishell.Cmd{ Name: "bill", Help: " Edit a Bill of the following id", LongHelp: ` Usage: edit bill Edit Bill of the set . Press on empty line to keep the old entry`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { editBill(argi) } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { tids := GetBillIds(false) selids, lids := GetBillList(tids) choice := c.MultiChoice(lids, "Select a Bill to Edit") //c.Println(tids) //c.Println(selids) if choice > -1 { editBill(selids[choice]) //c.Println(choice,selids[choice]) } //c.Println(boldRed("edittask - Please enter an id")) } c.Println(promptcol("______________________")) }, }) shell.AddCmd(editcmd) } { startcmd := &ishell.Cmd{ Name: "start", Help: "/now - Start a Task",// at a specific Time 'YYYY-MM-DD HH:MM' Or 'HH:MM' Or 'now'", LongHelp: ` Usage: start /now Start a new Task in the currently open Project at . Use Format "YYYY-MM-DD HH:MM" or "HH:MM" for datetime. If the latter is used the current local Date will be set. 'now' will start the Task at current local time.`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") newTaskTime(arg) stdOut() } else { c.Println(boldRed("start - Please enter a Datetime")) } c.Println(promptcol("______________________")) }, } startcmd.AddCmd(&ishell.Cmd{ Name: "now", Help: "Start a new Task immediately", LongHelp: ` Usage: start now Start a new Task in the currently open Project with current local time`, Func: func(c *ishell.Context) { newTask(false) stdOut() c.Println(promptcol("______________________")) }, }) shell.AddCmd(startcmd) } // STOP Command group { stopcmd := &ishell.Cmd{ Name: "stop", Help: "/now - Stop Open Task",// at a specific Time 'YYYY-MM-DD HH:MM' Or 'HH:MM'", LongHelp: ` Usage: stop /now Stop the active Task at . Use Format "YYYY-MM-DD HH:MM" or "HH:MM" for datetime. If the latter is used the current local Date will be set. 'now' will stop the Task at current local time. In case of a Stop-time before Task start user will be notified.`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") closeTaskTime(arg) stdOut() } else { c.Println(boldRed("stop - Please enter a Datetime")) } c.Println(promptcol("______________________")) }, } stopcmd.AddCmd(&ishell.Cmd{ Name: "now", Help: "Stop the currently Open Task immediately", LongHelp: ` Usage: stop now Stop the open Task at the current local time. If no task is open the user will be notified.`, Func: func(c *ishell.Context) { closeTask(true) stdOut() c.Println(promptcol("______________________")) }, }) shell.AddCmd(stopcmd) } // PRINT commans { printcmd := &ishell.Cmd{ Name: "print", Help: "yyy / xxx / bills", LongHelp: ` Usage: print Print Bills and Reports.`, } printcmd.AddCmd(&ishell.Cmd{ Name: "bills", Help: "Print selected Bills again to pdf", LongHelp: ` Usage: print bills Show all Projects with a small summary, sorted by Customer.`, Func: func(c *ishell.Context) { tids := GetBillIds(false) ids, str := GetBillList(tids) choices := c.Checklist(str, "Which Bills should be Printed again ?", nil) out := func() (c []int) { for _, v := range choices { if v > -1 { c = append(c, ids[v]) } } return } prbills := loadBills(out()) if isInterSure(fmt.Sprintf("Print %v Bills?",len(prbills))) { c.ProgressBar().Indeterminate(true) c.ProgressBar().Start() for i,_ := range prbills { _, cust := GetProject(prbills[i].project) files := billTemplate(prbills[i], cust) err = runLatex(files.Main, prbills[i].identity) } c.ProgressBar().Stop() if err == nil { c.Println("Finished without Errors") } else { c.Println("Finished with error:", err) } c.Print("<>") c.ReadLine() }else{ c.Println(boldRed("Charging Aborted")) } c.Println(promptcol("______________________")) }, }) shell.AddCmd(printcmd) } // SHOW commands { showcmd := &ishell.Cmd{ Name: "show", Help: "all / customers / bills / invoice / project", LongHelp: ` Usage: show `, // Show all Projects with a small summary sorted by Customer.`, } showcmd.AddCmd(&ishell.Cmd{ Name: "all", Help: "Show all Projects sorted by customers", LongHelp: ` Usage: show all Show all Projects with a small summary, sorted by Customer.`, Func: func(c *ishell.Context) { allProjects() stdOut() c.Println(promptcol("______________________")) }, }) /* showcmd.AddCmd(&ishell.Cmd{ Name: "bills", Help: "Show all Bills", LongHelp: ` Usage: all bills Show all previous Bills with small summary.`, Func: func(c *ishell.Context) { showLastBills(0) c.Println(promptcol("______________________")) }, }) */ showcmd.AddCmd(&ishell.Cmd{ Name: "customers", Help: "Show all Customers", LongHelp: ` Usage: all customers Show all Customers.`, Func: func(c *ishell.Context) { allCustomers(false) c.Println(promptcol("______________________")) }, }) showcmd.AddCmd(&ishell.Cmd{ Name: "bills", Help: " - Show the last n bills. If no n specified all Bills are shown ", LongHelp: ` Usage: show bills Show the last n Bills with a small summary. If no is specified all bills are shown.`, Func: func(c *ishell.Context) { //c.ClearScreen() arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { showLastBills(argi) } else { c.Println(boldRed(arg, "is not a valid integer!")) } } else { showLastBills(0) //c.Println(boldRed("showbills - Please enter an integer")) } //stdOut() c.Println(promptcol("______________________")) }, }) showcmd.AddCmd(&ishell.Cmd{ Name: "invoice", Help: " - Show details of the invoice with given id.", LongHelp: ` Usage: show invoice Show detailed information of Invoice with given id. If no is specified a selection screen is shown.`, Func: func(c *ishell.Context) { //c.ClearScreen() arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { if isBill(argi){ mid := []int{argi} thebill := loadBills(mid) ShowBill(thebill[0], true) }else{ c.Println(boldRed(arg, "is not a valid id!")) } } else { c.Println(boldRed(arg, "is not a valid integer!")) } } else { tids := GetBillIds(false) selids, lids := GetBillList(tids) choice := c.MultiChoice(lids, "Select a Bill to Edit") //c.Println(tids) //c.Println(selids) if choice > -1 { mid := []int{selids[choice]} thebill := loadBills(mid) ShowBill(thebill[0], true) } } //stdOut() c.Println(promptcol("______________________")) }, }) showcmd.AddCmd(&ishell.Cmd{ Name: "project", Help: " - Show details of the project with given id.", LongHelp: ` Usage: show invoice Show detailed information of Project with given id. If no is specified a selection screen is shown.`, Func: func(c *ishell.Context) { arg := "none" if len(c.Args) > 0 { arg = strings.Join(c.Args, " ") argi, err := strconv.Atoi(arg) if err == nil { ShowProjectStatus(argi) //allProjects() //stdOut() } else { c.Println(boldRed(arg, "is not a valid id!")) } } else { pids := GetProjectIds() selids, lids := getProjectList(pids) choice := c.MultiChoice(lids, "Select a Project to Show") if choice > -1 { ShowProjectStatus(selids[choice]) } } c.Println(promptcol("______________________")) }, }) shell.AddCmd(showcmd) } /* // multiple choice shell.AddCmd(&ishell.Cmd{ Name: "choice", Help: "multiple choice prompt", Func: func(c *ishell.Context) { choice := c.MultiChoice([]string{ "Golangers", "Go programmers", "Gophers", "Goers", }, "What are Go programmers called ?") if choice == 2 { c.Println("You got it!") } else { c.Println("Sorry, you're wrong.") } }, }) // multiple choice shell.AddCmd(&ishell.Cmd{ Name: "checklist", Help: "checklist prompt", Func: func(c *ishell.Context) { languages := []string{"Python", "Go", "Haskell", "Rust"} choices := c.Checklist(languages, "What are your favourite programming languages ?", nil) out := func() (c []string) { for _, v := range choices { c = append(c, languages[v]) } return } c.Println("Your choices are", strings.Join(out(), ", ")) }, }) */ //Test stuff in shell { //var autostuff = []string{"fuck This is Awsome","this cannot be real","shit my pants"} testcmd := &ishell.Cmd{ Name: "test", Help: "Test some functions in interactive mode", LongHelp: ` Usage: test Test functions in interactive mode`, Func: func(c *ishell.Context) { if len(c.Args) > 0 { c.Println("SomeArgs",c.Args) }else{ c.Println("No Args") } }, } testcmd.AddCmd(&ishell.Cmd{ Name: "new", Help: "Test export", LongHelp: ` Usage: export Test Export`, Func: func(c *ishell.Context) { c.Println("Said new!!!") MakeAnalysis() //getInterAutoInput("Really?",autostuff) }, }) shell.AddCmd(testcmd) } // DATA commands { datacmd := &ishell.Cmd{ Name: "data", Help: "import/export", LongHelp: ` Usage: data `, } datacmd.AddCmd(&ishell.Cmd{ Name: "export", Help: "export data from db", LongHelp: ` Usage: data export Export data from customers, projects and all closed tasks as csv files and tar them together`, Func: func(c *ishell.Context) { prid := GetProjectIds() cuid := GetCustomerIds() taid := GetTaskIds() //biid := GetBillIds() prs := GetSelectedProjects(prid) cus := GetSelectedCustomers(cuid) tas := GetSelectedTasks(taid) bls := GetAllBills() c.Println(frame(boldGreen("Export DB Data"),true)) c.Println(nli+"Customers:",len(cus)) c.Println(nli+" Projects:",len(prs)) c.Println(nli+" Tasks:",len(tas)) c.Println(nli+" Bills:",len(bls)) //c.Println("Customers:",cus) if isInterSure(sli+"Export this data?"){ filen := getNewInterInput("Filename: ","export.tar",nli) ExportCustomers(cus) ExportProjects(prs) ExportTasks(tas) ExportBills(bls) TarExports(filen) PurgeTemps() c.Println(nli+"Data exported to",filen) c.Println(frame(posR(),false)) }else{ c.Println(frame(negR(),false)) } }, }) datacmd.AddCmd(&ishell.Cmd{ Name: "import", Help: "import data into db", LongHelp: ` Usage: data import takes a tarball of csv data and imports it into the DB`, Func: func(c *ishell.Context) { //autostuff = append(autostuff,"scheissdreck") c.Println(frame(boldGreen("Import Data into DB"),true)) filen := getNewInterInput("Filename: ","export.tar",nli) err := UnTarExports(filen) if err != nil { c.Println(boldRed(err)) c.Println(frame(negR(),false)) return }else{ c.Println(nli,boldGreen("File Loaded")) c.Println(frame(posR(),false)) } icus := ImportCustomers() itas := ImportTasks() iprs := ImportProjects() ibls := ImportBills() PurgeTemps() //c.Println(sli,"Loaded Data") //c.Println(nli,"Customers:",len(icus)) //c.Println(nli," Projects:",len(iprs)) //c.Println(nli," Tasks:",len(itas)) //if isInterSure(sli+"Import this into DB?"){ SaveImportsToDB(icus,iprs,itas,ibls) //c.Println(boldGreen("Import Successful")) //c.Println(frame(posR(),false)) //}else{ // c.Println(boldRed("Nothing Imported")) // c.Println(frame(negR(),false)) //} }, //c.Println("Projects:",iprs) }) shell.AddCmd(datacmd) } // Config Commands { confcmd := &ishell.Cmd{ Name: "config", Help: "View and Edit Configuration", LongHelp: ` Usage: config [] Show the current configuration and ask if it should be edited. Configurations contains the location of the database file and the Personal Data needed for charging. If config is edited press on empty line to keep the old entry`, Func: func(c *ishell.Context) { editConf() c.Println(promptcol("______________________")) }, } // Prompt Color confcmd.AddCmd(&ishell.Cmd{ Name: "color", Help: "Select the Color of the prompt", LongHelp: ` Usage: config color Select the color of the prompt`, Func: func(c *ishell.Context) { choice := c.MultiChoice([]string{ boldMag("Magenta"), boldBlue("Blue"), boldCyan("Cyan"), boldGreen("Green"), boldYell("Yellow"), boldRed("Red"), }, "What Color should the Prompt be?") promptcol = PromptColor(choice).SprintFunc() //promptcol = mastercol.SprintFunc() c.SetPrompt(promptcol(">>>")) c.Println(promptcol("As You Wish!")) c.Println(promptcol("______________________")) }, }) shell.AddCmd(confcmd) } // Gather Tasks For Bills shell.AddCmd(&ishell.Cmd{ Name: "charge", Help: "Select Tasks to be charged", LongHelp: ` Usage: charge Select the tasks that should be merged into a Bill. The Task selection cannot be changed afterward. The bill can be deleted and a new selection made.`, Func: func(c *ishell.Context) { nix := []int{0} ids, str := GetTaskList(nix, true,true) choices := c.Checklist(str, "Which Tasks should be charged in the new bill ?", nil) out := func() (c []int) { for _, v := range choices { if v > -1 { c = append(c, ids[v]) } } return } //All selected ids selids := out() //bids,str2 := getTaskList(selids,false) //c.Println(bids,str2) c.Println(len(selids), "Tasks Selected") //If None Selected end if len(selids) == 0 { return } //get if selected tasks have multicustomers, are from multipe projects, and get the ids of the projects multicust, multiproj, projids := checkCustomerProjects(selids) billprojid := 0 // CHECK IF ONLY ONE CUSTOMER if multicust { c.Println(boldRed("Cannot Write One Bill to multiple Customers! Please Select different Tasks")) } else { // CHECK IF ONLY ONE PROJECT ELSE CHOOSE ONE if multiproj { prid, prstr := getProjectList(projids) sel := c.MultiChoice(prstr, "What Project Should be Billed ?") if sel > -1 { billprojid = prid[sel] } } else { billprojid = projids[0] } seltasks := GetSelectedTasks(selids) count, hours, dur := AnalyzeTasks(seltasks) //c.Printf("%v Tasks Selected. Totaling %.2f (h) - Dates: %s\n",count,hours,dur) proj, cust := GetProject(billprojid) // IF CUSTOMER 0 NO BILL CAN BE CREATED if cust.Id == 0 { c.Println(boldRed("Customer ", cust.Company, " with id ", cust.Id, " Cannot be billed. Please move ", proj.Name, " to a valid Customer")) return } //billid,billident := newBill(billprojid) //prs,cus := getProjectName(billprojid) //c.Println("For",cust.company,"-",cust.name) //c.Println("Project:",proj.name,"- ID:",proj.id) //c.Println("Projected Income:",hours*cust.satz,"€") //c.Println("Create New Bill:",billid) //c.ReadLine() //Make NEW BILL WITH ID and INV No c.ShowPrompt(false) //fullbillinfo := fmt.Sprintf("For: %s - %s - %.2f(€/h) - Invoice: %s Id:%v\nProject: %s - Id:%v\n%v Tasks Selected. Totaling %.2f (h) - Dates: %s\nProjected Income: %.2f(€)\n",cust.company,cust.name,cust.satz,billident,billid,proj.name,proj.id,count,hours,dur,hours*cust.satz) fullbillinfo := fmt.Sprintf("For: %s - %s - %.2f(€/h) \nProject: %s - Id:%v\n%v Tasks Selected. Totaling %.2f (h) - Dates: %s\nProjected Income: %.2f(€)\n", cust.Company, cust.Name, cust.Satz, proj.Name, proj.Id, count, hours, dur, hours*cust.Satz) sep := "-------------------------\n" restinfo := "Here some Info about the rest" restids := selids var allitems []billitem //allaccounted := false //resttasks := seltasks //SELECT SUBSET AND NAME BILLITEM //c.clear()//Println(some,"Str2:",str2) for { doneinfo2 := "" sumh := 0.0 if len(restids) == 0 { break } for _,itm := range allitems { doneinfo2 = fmt.Sprintf("%s %s - %v(h)\n",doneinfo2,itm.Task,itm.Hours) sumh += itm.Hours } doneinfo1 := fmt.Sprintf("Already Billed: %v(h)\n",sumh) doneinfo := fmt.Sprintf("%s%s",doneinfo1,doneinfo2) resttasks := GetSelectedTasks(restids) rcount, rhours, _ := AnalyzeTasks(resttasks) rids, rstr := GetTaskList(restids, false,false) qu := "Select Tasks to Group as Billitem" restinfo = fmt.Sprintf("%v Tasks Left, Total %.2f(h)\n%s", rcount, rhours, qu) pre := "" if len(allitems) > 0{ pre = fmt.Sprintf("%s%s%s%s%s", fullbillinfo, sep,doneinfo,sep, restinfo) }else{ pre = fmt.Sprintf("%s%s%s", fullbillinfo, sep, restinfo) } choices2 := c.Checklist(rstr, pre, nil) out = func() (c []int) { for _, v := range choices2 { if v > -1 { c = append(c, rids[v]) } } return } taskids := out() restids = removeItems(restids, taskids) if len(taskids) > 0 { ittasks := GetSelectedTasks(taskids) comm := GetSelectedComments(ittasks) itcount, ithours, itdur := AnalyzeTasks(ittasks) c.Printf("\n%v Tasks Selected, Total %.2f(h), Date: %s\n", itcount, ithours, itdur) if len(comm) >0 { c.Printf(" Comments on selected Tasks:\n%s\n",StrLines(comm," ")) } c.ShowPrompt(false) c.Print("Name your Item for the Bill: ") tsk := c.ReadLine() var hrf float64 for { c.Print("How Many Hours: ") hr := c.ReadLine() hrf, err = strconv.ParseFloat(hr, 64) if err != nil { c.Println(hr, boldRed("can not be Parsed as a Float."), "Try a shape of X.X") } else { break } } //c.Printf("%T %v - %T %v\n", tsk, tsk, hrf, hrf) allitems = append(allitems, billitem{tsk, itdur, hrf, Round(hrf*cust.Satz, 1)}) c.Print("<>") c.ReadLine() //c.ShowPrompt(true) } } halfbill := bill{0, "None", dur, proj.Id, proj.Name, time.Time{}, time.Time{}, allitems, 0} ShowBill(halfbill,false) if isInterSure("Is this bill Correct?") { billid, billident := newBill(billprojid) //c.Println(green("Bill Completed")) fullbill := bill{billid, billident, dur, proj.Id, proj.Name, time.Time{}, time.Time{}, allitems, 0} saveBill(fullbill) checkTasks(selids, billid) c.ProgressBar().Indeterminate(true) c.ProgressBar().Start() testid := []int{billid} testbill := loadBills(testid) //c.Println(testbill[0].projectname,testbill[0].items) files := billTemplate(testbill[0], cust) c.Println(files) err = runLatex(files.Main, testbill[0].identity) c.ProgressBar().Stop() if err == nil { c.Println("Finished without Errors") } else { c.Println("Finished with error:", err) } c.Print("<>") c.ReadLine() }else{ c.Println(boldRed("Charging Aborted")) } stdOut() } c.Println(promptcol("______________________")) c.ShowPrompt(true) }, }) // Decide if interactive mode should be started //args := removeStringFromArray(os.Args[1:],"-file",1) if len(interArgs) > 0 { //args := removeStringFromArray(os.Args[1:],"-file",1) //fmt.Println(args) shell.Process(interArgs...) } else { //shell.Println("Starting interactive Shell") stdOut() //start shell shell.Run() // teardown shell.Close() } //fmt.Println("Laboravi emeritus...") } func isInterSure(question string) bool { shell := ishell.New() shell.ShowPrompt(false) defer shell.ShowPrompt(true) shell.Printf("%s ('y/Y/yes' Default: n) : ", question) line := shell.ReadLine() if line == "yes" || line == "y" || line == "Y" { return true } else { return false } } /* func getInterAutoInput(question string,autocom []string) (out string) { shell := ishell.New() shell.ShowPrompt(false) defer shell.ShowPrompt(true) shell.AddCmd(&ishell.Cmd{ Name: "", Help: "never to be seen", Completer: func([]string) []string { return autocom}, Func: func(c *ishell.Context) { c.Print(question) //out = shell.ReadLine() out = fmt.Sprint(c.Args) }, }) //shell.SetRootCmd("fun") shell.Run() return } */ func getInterInput(question string) (out string) { shell := ishell.New() shell.ShowPrompt(false) defer shell.ShowPrompt(true) shell.Print(question) out = shell.ReadLine() return } func getNewInterInput(question, old, border string) string { shell := ishell.New() shell.ShowPrompt(false) defer shell.ShowPrompt(true) if old != "" { shell.Println(border+"Current:", old) } shell.Print(border+question) line := shell.ReadLine() if line == "" { return old } else { return line } } func getInterMultiInput(question string) (out string) { shell := ishell.New() //shell.ShowPrompt(false) //defer shell.ShowPrompt(true) shell.SetPrompt(nli+">>>") shell.SetMultiPrompt(nli+"...") shell.Println(question, "(Multiline input, end with ';')") out = shell.ReadMultiLines(";") shell.Println(sli+" -Done-") return } func getNewInterMultiInput(question, old, border string) (out string) { shell := ishell.New() //shell.ShowPrompt(false) //defer shell.ShowPrompt(true) shell.SetPrompt(border+">>>") shell.SetMultiPrompt(border+"...") if old != "" { shell.Println(border,"Current:\n", old) shell.Println(border,"Should current entry be replaced? A Newline will be added otherwise") } if isInterSure(border+" ") { shell.Println(border, question, "(Multiline input, end with ';')") out = shell.ReadMultiLines(";") shell.Println(border," -Done-") } else { shell.Print(nli+question) txt := shell.ReadLine() if txt == "" { out = old } else { out = old + "\n" + txt } } return /*if line == "" { return old }else{ return line }*/ } // Invoke an Multiplechoice Question with a question and // the list of options and return the selected list id func Multichoice(question string,list []string) (int) { shell := ishell.New() marker := li+li+">" shell.SetMultiChoicePrompt(marker,nli) shell.SetChecklistOptions("[ ] ", "[X] ") qu1 := line(marker,false) qu2 := frame(question,true) quest := qu1 + strings.TrimLeft(qu2,"\n") choice := -1 choice = shell.MultiChoice(list,quest) return choice /*shell.AddCmd(&ishell.Cmd{ Name: "choice", Help: "multiple choice prompt", Func: func(c *ishell.Context) { choice := c.MultiChoice([]string{ "Golangers", "Go programmers", "Gophers", "Goers", }, "What are Go programmers called ?") if choice == 2 { c.Println("You got it!") } else { c.Println("Sorry, you're wrong.") } }, }) str := "choice" shell.Process(str) shell.Println(about)*/ } // Invoke a Checklist Question with a leading Question // line and return an int slice of the selected rows of the list func Checklist(question string, list []string) ([]int) { shell := ishell.New() marker := li+li+">" shell.SetMultiChoicePrompt(marker,nli) shell.SetChecklistOptions("[ ] ", "[X] ") qu1 := line(marker,false) qu2 := frame(question,true) quest := qu1 + strings.TrimLeft(qu2,"\n") choices := shell.Checklist(list,quest,nil) return choices }