def __load_configuration(self, configuration_path): """ Load the configuration from the supplied path. If the file does not exist at this path, create it from the default config settings. """ expanded_path = path.expanduser(configuration_path) if not path.exists(path.dirname(expanded_path)): makedirs(path.dirname(expanded_path)) if not path.exists(expanded_path): self.__write_config_file(expanded_path, self.DEFAULT_CONFIG) p = Printer() p.add_header("Wilcume on Færeld") p.newline() p.add("This looks like it is your first time running Færeld.") p.newline() p.add("A config file has been created at ", Highlight(expanded_path), ".") p.newline() p.add( "This contains some default values to get you started, ", "but you should take a look to add your own areas and projects.", ) p.newline() p.add( "For more information, please see the configuration documentation ", "at https://faereld.readthedocs.io/en/latest/usage/configuration.html", ) p.newline() p.print() else: self.__load_configuration_values(expanded_path)
def input_non_project_object(self, area): use_last_objects = self.config.get_area(area).get( "use_last_objects", False) last_objects = [] if use_last_objects: last_objects = self.db.get_last_objects( area, self.config.get_num_last_objects()) last_objects_dict = { "[{0}]".format(x): k[0] for x, k in enumerate(last_objects) } # Transform last objects into [x]: object tags if len(last_objects) > 0: p = Printer() last_objects_dict = { "[{0}]".format(x): k for x, k in enumerate(last_objects) } p.add("Last {0} {1} Objects :: ".format( len(last_objects), area)) p.newline() for k, v in sorted(last_objects_dict.items()): p.add("{0} {1}".format(k, v)) p.newline() p.print() object = prompt("Object :: ", completer=WordCompleter(last_objects), vi_mode=True) if use_last_objects: if object in last_objects_dict: return last_objects_dict[object] return object
def projects_help(projects, project_description_func): p = Printer() for project in projects: p.add("[{}]".format(project)) p.add(project_description_func(project)) p.newline() return p
def print(self): self.simple_summary.print() p = Printer() p.newline() p.add_header("Total Time Logged Per Project") p.newline() graph = ( SummaryGraph(self.project_time_map) .set_max_width(utils.max_width(self.config.get_max_graph_width())) .set_key_transform_function(self.config.get_project_name) .sort_graph(reverse=True) .generate() ) for row in graph: p.add_nowrap(row) p.newline() p.add_header("Total Time Logged Per Area Per Project") p.newline() multigraph = ( SummaryMultiGraph(self.project_area_time_map, 30) .set_header_transform_function(self.config.get_project_name) .generate() ) for row in multigraph: p.add_nowrap(row) p.print()
def summary(self, target): summary = self.db.get_summary(target=target, detailed=True) if target is None: Printer().add_mode_header("Summary").print() else: if target not in self.config.get_areas(): p = Printer() p.add("ERROR: No area found for: [", Highlight(target), "]") p.newline() p.add("Valid areas are: ") for area in self.config.get_areas(): p.add(f"[{area}]") p.print() return Printer().add_mode_header(f"Summary [{target}]").print() summary.print()
def print(self): self.simple_summary.print() p = Printer() def day_num_to_string(day_num): dates = { 0: "MON", 1: "TUE", 2: "WED", 3: "THU", 4: "FRI", 5: "SAT", 6: "SUN", } return dates[day_num] def zero_pad_hour(hour): if len(str(hour)) == 1: return "0{}".format(str(hour)) return str(hour) p.newline() p.add_header("Total Time Logged Per Day") p.newline() graph = (SummaryGraph(self.day_delta_map).set_max_width( utils.max_width( self.config.max_graph_width)).set_key_transform_function( day_num_to_string).generate()) for row in graph: p.add_nowrap(row) p.newline() p.add_header("Total time logged per hour") p.newline() graph = (SummaryGraph(self.hour_delta_map).set_max_width( utils.max_width( self.config.max_graph_width)).set_key_transform_function( zero_pad_hour).generate()) for row in graph: p.add_nowrap(row) p.print()
def cli_help(): p = Printer() p.add_mode_header("Help") p.newline() p.add( "Færeld (an Old English word meaning journey or ", "progession) is a time tracking utility built for ", "optimising and visualising the time spent on ", "projects and self-improvement.", ) p.newline() p.add("faereld [-c CONFIG] MODE [TARGET]") p.newline() p.add("Færeld has 5 modes:") p.add("INSERT Insert a time tracking record into Færeld") p.add("SUMMARY Produce a summary of time spent on all areas") p.add("PROJECTS Produce a summary of time spent on project specific areas") p.add( "PRODUCTIVITY Produce a summary of productivity aggregated over ", "hours and days of the week", ) p.add("HELP Print the help") p.newline() p.add_header("Configuration") p.newline() p.add( "Færeld's configuration file is stored, by ", "default, in ~/.andgeloman/faereld/config.yml. ", "In this file you can define your own areas and ", "projects, as well as tweak some settings for ", "things like the data path. For a full ", "explanation of these settings, please consult ", "https://faereld.readthedocs.io/en/latest/usage/configuration.html.", ) p.newline() p.add("To use a different configuration file, use the -c flag ::") p.add(" faereld -c /path/to/config.yml MODE") p.newline() p.add("Source :: https://github.com/autophagy/faereld") p.add("Issue Tracker :: https://github.com/autophagy/faereld/issues") p.add("Documentation :: https://faereld.readthedocs.io/en/latest/") return p
def areas_help(areas): p = Printer() for area_code, area in areas.items(): p.add("[{0}] {1}".format(area_code, area["name"])) p.newline() return p
def print(self): self.simple_summary.print() p = Printer() p.newline() p.add_header(f"Summary For {self.area_name}") p.newline() minimum = None maximum = None average = datetime.timedelta() for entry in self.area_time_map[self.area]: if minimum is None or minimum > entry: minimum = entry if maximum is None or maximum < entry: maximum = entry average += entry average = average / len(self.area_time_map[self.area]) p.add( f"The lowest recorded entry for {self.area_name} is ", f"{utils.format_time_delta(minimum)}.", ) p.add( f"The highest recorded entry for {self.area_name} is ", f"{utils.format_time_delta(maximum)}.", ) p.add( f"The average entry for {self.area_name} is ", f"{utils.format_time_delta(average)}.", ) p.newline() p.add_header(f"Entry Time Distribution for {self.area_name}") p.newline() box = (BoxPlot(self.area_time_map).set_max_width( utils.max_width(self.config.get_max_graph_width()) ).set_exclude_list( self.config.get_exclude_from_entry_time_distribution()).generate()) for row in box: p.add_nowrap(row) p.newline() p.add_header("LAST {0} ENTRIES".format(len(self.last_entries))) p.newline() for entry in self.last_entries: if self.config.get_use_wending(): start_date = entry.start.strftime("{daeg} {month} {gere}") else: start_date = entry.start.strftime("%d %b %Y") p.add(*utils.get_rendered_string( entry.area, self.config.get_area(entry.area), start_date, self.config.get_object_name(entry.area, entry.obj), utils.time_diff(entry.start, entry.end), entry.purpose, )) p.print()
def print(self): self.simple_summary.print() p = Printer() p.newline() p.add_header("Total Time Logged Per Area") p.newline() # Sum all the timedeltas for the summary graph summary_time_map = dict( map( lambda x: (x[0], sum(x[1], datetime.timedelta())), self.area_time_map.items(), )) graph = (SummaryGraph(summary_time_map).set_max_width( utils.max_width( self.config.get_max_graph_width())).set_exclude_list( self.config.get_exclude_from_total_time()).generate()) for row in graph: p.add_nowrap(row) p.newline() p.add_header("ENTRY TIME DISTRIBUTION PER AREA") p.newline() box = (BoxPlot(self.area_time_map).set_max_width( utils.max_width(self.config.get_max_graph_width()) ).set_exclude_list( self.config.get_exclude_from_entry_time_distribution()).generate()) for row in box: p.add_nowrap(row) p.newline() p.add_header("LAST {0} ENTRIES".format(len(self.last_entries))) p.newline() for entry in self.last_entries: if self.config.get_use_wending(): start_date = entry.start.strftime("{daeg} {month} {gere}") else: start_date = entry.start.strftime("%d %b %Y") p.add(*utils.get_rendered_string( entry.area, self.config.get_area(entry.area), start_date, self.config.get_object_name(entry.area, entry.obj), utils.time_diff(entry.start, entry.end), entry.purpose, )) p.print()
def areas_help(areas): p = Printer() for area_code, area in areas.items(): p.add(f"[{area_code}] {area['name']}") p.newline() return p