<commit_before>""" Module "Menu" : Menu classes

    All classes required to implement menus including task menus, chat menus
    etc.
"""
# Standard Library Imports
import textwrap
import curses
import time

# Custom Module Imports

import config as C
from screen import Screen
import global_objects as G
import helper as H
import debug as DEBUG
import task as T

def truncate(string, size):
    return (string[:size-3]+"...") if len(string)>size else string

class MenuItem(object):
    """ A class for storing a single menu item. It will contain the task object
    as well as the status object. It is general enough to be used as a
    checklist item, and an actual task item"""

    def __init__(self, task, task_type, taskname,
                 width = -1, front = True):
        self.task = task
        self.task_type = task_type

        self.taskname = taskname

        if self.task_type == "habit":
            if self.task.up and self.task.down:
                self.status = H.Status("habit")
            elif self.task.up:
                self.status = H.Status("habitpos")
            elif self.task.down:
                self.status = H.Status("habitneg")
            else:
                self.status = H.Status("unscoredhabit")

            # Set Coordinates for a task
            self.task.SetXY(C.SCR_MAX_MENU_ROWS+7, 5)

            if self.task.isChallenge:
                self.status.isChallenge = True

        elif self.task_type == "todo" or self.task_type == "daily":
            checklist_tuple = self.task.ChecklistTuple()
            dueDate = getattr(self.task, "dueDate", "")
            self.status = H.Status(self.task_type, checklist_tuple, dueDate)

            # Set Coordinates for a task
            self.task.SetXY(C.SCR_MAX_MENU_ROWS+7, 5)

            if self.task.isChallenge:
                self.status.isChallenge = True

        else: # task_type = 'checklist'
            self.status = H.Status(self.task_type)


        self.x = 0
        self.y = 0

        # Width specification
        if width == -1:
            self.width = C.SCR_MENU_ITEM_WIDTH
        else:
            self.width = width

        # Should the status be at the front or the back (True/False
        # respectively)
        self.front = front


    def SetXY(self, x=0, y=0):
        self.x = x
        self.y = y
        self.SetStatusXY()

    def SetStatusXY(self):
        if self.front:
            self.status.SetXY(self.x, self.y + self.status.ReturnLenString() - 2)
        else:
            self.status.SetXY(self.x, self.y + self.width - 1)


    def DisplayName(self, color=0,highlight=False):
        if hasattr(self.task, "color"):
            color = self.task.color

        #Current task is higlighted, display the details
        if(highlight):
            self.task.Display()

        status_length = self.status.ReturnLenString()
        first_row_size = self.width - status_length - 1

        # Display Task Name
        G.screen.Display(" "*self.width,  self.x,self.y,
                         color=C.SCR_COLOR_NEUTRAL,bold=True)
        G.screen.Display(" "*(first_row_size+1), self.x,
                           self.y+status_length,highlight=highlight)
        G.screen.Display(" "*self.width,self.x+1,self.y,
                color=color,highlight=highlight)


        # Show the attributes that can be set (mark,delete, up,down,etc)
        self.status.Display()

        #Add a gray tick if it's completed
        if hasattr(self.task, 'completed') and self.task.completed:
            G.screen.Display(C.SYMBOL_TICK, self.x,self.y + status_length,
                    color=C.SCR_COLOR_NEUTRAL, bold=True,highlight=highlight)

        #If we are set to delete, strikethrough the task name
        strike=self.status.attributes.get(C.SYMBOL_DELETE, False)

        #Print the task name
        if len(self.taskname) < first_row_size: # No need to truncate
            if self.front:
                G.screen.Display(self.taskname, self.x, self.y + status_length + 1,
                        color=color, bold=True,strike=strike,highlight=highlight)

            else:
                G.screen.Display(self.taskname, self.x, self.y,
                        color=color, bold=True,strike=strike,highlight=highlight)

            G.screen.Display(" "*self.width, self.x+1, self.y,highlight=highlight)
        else:                                   # We need truncation
            if self.taskname[first_row_size-1] != ' ':
                if self.front:
                    G.screen.Display(self.taskname[:first_row_size-1]+"-",
                                     self.x, self.y + status_length + 1,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                else:
                    G.screen.Display(self.taskname[:first_row_size-1]+"-",
                                     self.x, self.y,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                G.screen.Display(truncate(self.taskname[first_row_size-1:],self.width),
                                 self.x+1, self.y,
                                 color=color, bold=True,strike=strike,highlight=highlight)
            elif self.taskname[first_row_size-1] == ' ':
                if self.front:
                    G.screen.Display(self.taskname[:first_row_size],
                                     self.x, self.y + status_length + 1,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                else:
                    G.screen.Display(self.taskname[:first_row_size],
                                     self.x, self.y,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                G.screen.Display(truncate(self.taskname[first_row_size:],self.width),
                                 self.x+1, self.y,
                                 color=color, bold=True,strike=strike,highlight=highlight)

    def HighlightName(self):
        self.DisplayName(self,highlight=True)

    def ToggleMarkUp(self):
        self.status.ToggleMarkUp()
        self.HighlightName()

    def ToggleMarkDown(self):
        self.status.ToggleMarkDown()
        self.HighlightName()

    def ToggleMark(self):
        self.status.ToggleMark()
        self.HighlightName()

    def ToggleDelete(self):
        self.status.ToggleDelete()
        self.HighlightName()

    def ToggleEdit(self):
        self.status.ToggleEdit()
        self.HighlightName()

    def EnterNewName(self):
        # Used for changing names of checklist items
        # and adding new items
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x, self.y)
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x+1, self.y)
        newName = G.screen.StringInput(self.x, self.y)
        self.task.newName = newName
        self.taskname = newName # Will be restored if changes are cancelled

        # Clear it up a bit
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x, self.y)
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x+1, self.y)

        self.HighlightName()

    def ShowChecklist(self):
        self.task.ShowChecklist(self)

    def ChangePriority(self, key):
        self.task.ChangePriority(key)
        self.status.ToggleEdit()

    def ChangeDueDate(self, date):
        if self.task_type != "todo":
            return

        self.task.ChangeDueDate(date)
        self.status.SetDue(H.DateTime(date).DueDateFormat())
        self.SetStatusXY()
        self.status.ToggleEdit()

    def RemoveDueDate(self):
        if self.task_type != "todo":
            return

        self.task.RemoveDueDate()
        self.status.SetDue("")
        self.status.ToggleEdit()

    def SetWeekly(self, repeat):
        if self.task_type != "daily":
            return

        self.task.SetWeekly(repeat)
        self.status.ToggleEdit()

    def SetEvery(self, days):
        if self.task_type != "daily":
            return

        self.task.SetEvery(days)
        self.status.ToggleEdit()

    def SetDirection(self, up=True, down=True):
        if self.task_type != "habit":
            return

        if self.task_type != "checklist" and self.task.isChallenge:
            # Cannot change direction of a challenge<commit_msg>Fixing bugs while changing difficulty, due date etc. in challenge tasks<commit_after>""" Module "Menu" : Menu classes

    All classes required to implement menus including task menus, chat menus
    etc.
"""
# Standard Library Imports
import textwrap
import curses
import time

# Custom Module Imports

import config as C
from screen import Screen
import global_objects as G
import helper as H
import debug as DEBUG
import task as T

def truncate(string, size):
    return (string[:size-3]+"...") if len(string)>size else string

class MenuItem(object):
    """ A class for storing a single menu item. It will contain the task object
    as well as the status object. It is general enough to be used as a
    checklist item, and an actual task item"""

    def __init__(self, task, task_type, taskname,
                 width = -1, front = True):
        self.task = task
        self.task_type = task_type

        self.taskname = taskname

        if self.task_type == "habit":
            if self.task.up and self.task.down:
                self.status = H.Status("habit")
            elif self.task.up:
                self.status = H.Status("habitpos")
            elif self.task.down:
                self.status = H.Status("habitneg")
            else:
                self.status = H.Status("unscoredhabit")

            # Set Coordinates for a task
            self.task.SetXY(C.SCR_MAX_MENU_ROWS+7, 5)

            if self.task.isChallenge:
                self.status.isChallenge = True

        elif self.task_type == "todo" or self.task_type == "daily":
            checklist_tuple = self.task.ChecklistTuple()
            dueDate = getattr(self.task, "dueDate", "")
            self.status = H.Status(self.task_type, checklist_tuple, dueDate)

            # Set Coordinates for a task
            self.task.SetXY(C.SCR_MAX_MENU_ROWS+7, 5)

            if self.task.isChallenge:
                self.status.isChallenge = True

        else: # task_type = 'checklist'
            self.status = H.Status(self.task_type)


        self.x = 0
        self.y = 0

        # Width specification
        if width == -1:
            self.width = C.SCR_MENU_ITEM_WIDTH
        else:
            self.width = width

        # Should the status be at the front or the back (True/False
        # respectively)
        self.front = front


    def SetXY(self, x=0, y=0):
        self.x = x
        self.y = y
        self.SetStatusXY()

    def SetStatusXY(self):
        if self.front:
            self.status.SetXY(self.x, self.y + self.status.ReturnLenString() - 2)
        else:
            self.status.SetXY(self.x, self.y + self.width - 1)


    def DisplayName(self, color=0,highlight=False):
        if hasattr(self.task, "color"):
            color = self.task.color

        #Current task is higlighted, display the details
        if(highlight):
            self.task.Display()

        status_length = self.status.ReturnLenString()
        first_row_size = self.width - status_length - 1

        # Display Task Name
        G.screen.Display(" "*self.width,  self.x,self.y,
                         color=C.SCR_COLOR_NEUTRAL,bold=True)
        G.screen.Display(" "*(first_row_size+1), self.x,
                           self.y+status_length,highlight=highlight)
        G.screen.Display(" "*self.width,self.x+1,self.y,
                color=color,highlight=highlight)


        # Show the attributes that can be set (mark,delete, up,down,etc)
        self.status.Display()

        #Add a gray tick if it's completed
        if hasattr(self.task, 'completed') and self.task.completed:
            G.screen.Display(C.SYMBOL_TICK, self.x,self.y + status_length,
                    color=C.SCR_COLOR_NEUTRAL, bold=True,highlight=highlight)

        #If we are set to delete, strikethrough the task name
        strike=self.status.attributes.get(C.SYMBOL_DELETE, False)

        #Print the task name
        if len(self.taskname) < first_row_size: # No need to truncate
            if self.front:
                G.screen.Display(self.taskname, self.x, self.y + status_length + 1,
                        color=color, bold=True,strike=strike,highlight=highlight)

            else:
                G.screen.Display(self.taskname, self.x, self.y,
                        color=color, bold=True,strike=strike,highlight=highlight)

            G.screen.Display(" "*self.width, self.x+1, self.y,highlight=highlight)
        else:                                   # We need truncation
            if self.taskname[first_row_size-1] != ' ':
                if self.front:
                    G.screen.Display(self.taskname[:first_row_size-1]+"-",
                                     self.x, self.y + status_length + 1,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                else:
                    G.screen.Display(self.taskname[:first_row_size-1]+"-",
                                     self.x, self.y,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                G.screen.Display(truncate(self.taskname[first_row_size-1:],self.width),
                                 self.x+1, self.y,
                                 color=color, bold=True,strike=strike,highlight=highlight)
            elif self.taskname[first_row_size-1] == ' ':
                if self.front:
                    G.screen.Display(self.taskname[:first_row_size],
                                     self.x, self.y + status_length + 1,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                else:
                    G.screen.Display(self.taskname[:first_row_size],
                                     self.x, self.y,
                                     color=color, bold=True,strike=strike,highlight=highlight)
                G.screen.Display(truncate(self.taskname[first_row_size:],self.width),
                                 self.x+1, self.y,
                                 color=color, bold=True,strike=strike,highlight=highlight)

    def HighlightName(self):
        self.DisplayName(self,highlight=True)

    def ToggleMarkUp(self):
        self.status.ToggleMarkUp()
        self.HighlightName()

    def ToggleMarkDown(self):
        self.status.ToggleMarkDown()
        self.HighlightName()

    def ToggleMark(self):
        self.status.ToggleMark()
        self.HighlightName()

    def ToggleDelete(self):
        self.status.ToggleDelete()
        self.HighlightName()

    def ToggleEdit(self):
        self.status.ToggleEdit()
        self.HighlightName()

    def EnterNewName(self):
        # Used for changing names of checklist items
        # and adding new items
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x, self.y)
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x+1, self.y)
        newName = G.screen.StringInput(self.x, self.y)
        self.task.newName = newName
        self.taskname = newName # Will be restored if changes are cancelled

        # Clear it up a bit
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x, self.y)
        G.screen.Display(" "*(C.SCR_Y - self.y - 1), self.x+1, self.y)

        self.HighlightName()

    def ShowChecklist(self):
        self.task.ShowChecklist(self)

    def ChangePriority(self, key):
        self.task.ChangePriority(key)
        self.status.ToggleEdit()

    def ChangeDueDate(self, date):
        if self.task_type != "todo":
            return

        if self.task_type != "checklist" and self.task.isChallenge:
            # Cannot change the due-date parameter of a challenge
            DEBUG.Display("Cannot change the due-date for a challenge TODO")
            return

        self.task.ChangeDueDate(date)
        self.status.SetDue(H.DateTime(date).DueDateFormat())
        self.SetStatusXY()
        self.status.ToggleEdit()

    def RemoveDueDate(self):
        if self.task_type != "todo":
            return

        if self.task_type != "checklist" and self.task.isChallenge:
            # Cannot change the due-date parameter of a challenge
            DEBUG.Display("Cannot change the due-date for a challenge TODO")
            return

        self.task.RemoveDueDate()
        self.status.SetDue("")
        self.status.ToggleEdit()

    def SetWeekly(self, repeat):
        if self.task_type != "daily":
            return

        if self.task_type != "checklist" and self.task.isChallenge:
            # Cannot change the 'weekdays' parameter of a challenge
            DEBUG.Display("Cannot change the 'weekdays' parameter of a challenge daily task")
            return

        self.task.SetWeekly(repeat)
        self.status.ToggleEdit()

    def SetEvery(self, days):
        if self.task_type != "daily":
            return

        if self.task_type != "checklist" and self.task.isChallenge:
            # Cannot change the 'every x days' parameter of a challenge
            DEBUG.Display("Cannot change the 'every x days' parameter of a challenge daily task")
            return

        self.task.SetEvery(days)
        self.status.ToggleEdit()

    def SetDirection(self, up=True, down=True):
        if self.task_type != "habit":
            return

        if self.task_type != "checklist" and self.task.isChallenge:
            # Cannot change direction of a challenge
{'fraction_non_alphanumeric': 0.105376101197199, 'fraction_numerical': 0.003840072283713576, 'mean_word_length': 1.830722506393862, 'pattern_counts': {'":': 14, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5488801', 'n_tokens_mistral': 5378, 'n_tokens_neox': 5033, 'n_words': 1163}