Making a TIME Management Tool for the CLI (part 6)

This is the seventh day of my participation in the August More Text Challenge. For details, see “August More Text Challenge”.

preface

The previous article focused on generating report directives over a period of time:

  • timec -or --range <startTime>_<endTime> <filename1> <filename1> .....

Sometimes it is expected to directly export data for a day, month, or even a year, for which several date-related instructions will be extended

  • One day,timec -or --day [date]
  • One month:timec -or --month [month]
    • The default value is this year
  • One year:timec -or --year [year]
  • A month or a year:timec -or -Y [year] -M [month]
    • --month--yearUse a combination of
    • Among them-M.-YThese are abbreviations for the above two instructions

In addition to this section, this section will also move into a new chapter that begins the development of using instructions to manage tasks and transactions

This article will cover task-related instruction development: timec task [name]

This effect

The function development

This section will omit the five senses (which have appeared in previous articles)

Date-dependent instruction

Specific to day

The first is to designate a day:

  • throughoptionThis parameter is optional
  • throughcmdObjThe day attribute of gets the value passed in by the user
.option('-D, --day [date]'.'One day')
// Omit the actions code
const { day } = cmdObj
Copy the code

Repackage the function that outputs the report:

  • The parameters areThe start timewithThe end of time
    • In this way, the remaining several optional parameter instructions can be directly reused
const output = (s, e) = > {
  const outPutPath = getFilePath(cwd, `report-${outFileName}.md`)
  const json = getJSONByRange(content, s, e)
  if (json.length === 0) {
      console.log('No eligible data');
      return
  }
  const data = outPutReport(json)
  createFile(outPutPath, data, false)
  console.log('Export succeeded');
}
Copy the code

Check whether the date exists. If yes, the date is directly exported

  • The start and end times are both incoming dates
if (day) {
    return output(day, day)
}
Copy the code

Specific to the month

The usual rule is to register the instructions

.option('-M, --month [month]'.'One month')
Copy the code

If there are only months, the default year is this year, and the start and end time are respectively

  • nowYear-month-01
  • nowYear-month-days

How to quickly get the number of days in a month or year:

  1. DateThe constructor supports overloading of functions that take the year, month, and day arguments
  2. Which month isWe start at 0: “1-12” corresponds to “0-11” respectively
  3. When the parameter of the day part is passed in 0, it indicates the date of the last day of last month
  4. Call again at this pointgetDateMethod, the number of days in the target month is obtained

For example, the number of days from 2021 to August:

  • New Date (2021,8,0)
  • logoIn September 2021The date of the day before commencement, i.eAugust 31, 2021
  • getDateThe returned result is31
const days = new Date(year,month,0).getDate()
Copy the code

The export logic is as follows:

  • This year’s year is passednew Date().getFullYear()To obtain
if (month) {
    const year = new Date().getFullYear()
    return output(`${year}-${month}- 01 `.`${year}-${month}-The ${new Date(year, month, 0).getDate()}`)}Copy the code

Specific to the years

If it is a year, then the starting and ending times are:

  • year-01-01
  • year-12-31

There’s not much to say about this, just write it like you know it

.option('-Y, --year [year]'.'One year')
/ /... more code
if (year) {
    return output(`${year}- 01-01 `.`${year}- 12-31 `)}Copy the code

Specific to certain year certain month

This is what happens when the -m and -y arguments are used together

Only need to do a combination of the above two export logic, logic is simple

if (year && month) {
    return output(`${year}-${month}- 01 `.`${year}-${month}-The ${new Date(year, month, 0).getDate()}`)}Copy the code

A few date-related instructions are completed, and then the task related instructions begin

Task management command

The instruction format is as follows

timec task [name]
Copy the code

The name argument is optional and has the following logic:

  • When name is empty, all tasks are displayed and tasks in progress are marked
  • If the name does not exist, add it to the task list
  • When the name exists, set it to the task in progress

With the logic clear, go to development

Initialize the configuration file

Create a.config/record.json file in the project root directory

/ Users/sugar/Documents/fe - project/time - control ├ ─ ─ bin ├ ─ ─ the SRC ├ ─ ─test├─── ├─ ├─ ch.htm.pdf.pdf.pdf.pdf.pdf.pdf.pdf.pdf.PDF.PDF.PDF.PDF.PDFCopy the code

The configuration file structure is as follows:

{
    "recordFilepath": ""."tasks": []."defaultTaskIdx": - 1."thing": {
        "name": ""."startTime": "2021-01-01"."endTime": "2021-12-31"."pauseTime": "2021-12-26"}}Copy the code

The tasks property, which records all tasks, and the defaultTaskIdx property, which records the tasks currently in progress, are mainly used here

Registration instructions

Use commander.command to register a command:

  • Which USES[]Package parameter identifier This parameter is optional
/** * Create a task, switch tasks, and view the task list */
commander.command("task [name]")
    .alias('t')
    .description('check tasks/add task/checkout task')
    .action((name) = > {
        / /... The following section describes code
    })
Copy the code

Path of the configuration file

  • through__dirnameLocate the configuration file in a path relative to the configuration file
const configPath = path.join(__dirname, '.. /.config/record.json')
Copy the code

The JSON configuration file is imported through the require method

  • The content introduced is just an object, and you don’t need to call itJSON.parseconvert
const config = require(configPath)
Copy the code

Next comes the concrete business logic code

  • First determine whether to pass in the task namename
    • If no, determine whether there is a task. If there is a task, print it in sequence. If there is no task, print the prompt information
  • If the task name does not exist, it is added to the task listtasks
    • If yes, the task is set to an ongoing task, that is, updatedefaultTaskIdxThe value of the
  • The content of the configuration file is updated
const { tasks, defaultTaskIdx } = config
const idx = tasks.findIndex(v= > v === name)
if(! name){if(tasks.length===0) {console.log('no tasks, you can use command add task');
        console.log('timec task [name]');
        return 
    }
    tasks.forEach((v,i) = >{
        let mark = '[]'
        if(i===+defaultTaskIdx){
            mark = '[*]'
        }
        console.log(mark,v);
    })
    return
}
if (idx === -1) {
    tasks.push(name)
    if(tasks.length===1){
        config.defaultTaskIdx = 0
    }
    console.log('add task success');
}else{
    config.defaultTaskIdx = idx
    console.log('now use task:',tasks[idx]);
}
writeFileSync(configPath,JSON.stringify(config))
Copy the code

This directive is developed, the time is short, the code quality may not be too high

TODO: Follow-up optimization

summary

So far the following directives have been supported:

These instructions are not the final version, because the time is too tight, the design time is also short, later will continue to improve

other

Because of the limited free time each day, this article will stop there

If you don’t have enough, stay tuned for updates, or keep an eye on the status of the warehouse

Welcome to comment section to raise demand, exchange discussion

This series will continue to be updated and iterated until the first generation of the product is completed

  • The warehouse address