📜  使用 Node.js 的 Todo List CLI 应用程序

📅  最后修改于: 2022-05-13 01:56:33.380000             🧑  作者: Mango

使用 Node.js 的 Todo List CLI 应用程序

CLI对于开发人员来说是一个非常强大的工具。我们将学习如何为命令行创建一个简单的 Todo List 应用程序。我们已经将 TodoList 视为 Web 开发和 android 开发的初学者项目,但 CLI 应用程序是我们不常听到的东西。

先决条件:

  • 下载并安装了最新版本的 Node.js。
  • 文本编辑器,例如 VSCode、atom 等。
  • 应该安装 NPM。
  • 基本了解 JavaScript、es6 特性等。

通过mkdir 创建一个新目录,并通过cd进入该目录并键入命令npm init 启动一个空节点项目。

注意:我们不会在这个项目中使用任何第三方模块。

项目目录:现在项目目录应该包含两个文件,package.json 和 index.js,如下所示:

我们的待办事项列表应用程序中的一些基本功能如下:

执行:

创建一个index.js文件并将以下代码写入其中

Javascript
// Requiring module
const fs = require('fs');
  
// Accessing arguments
const args = process.argv;
  
// The "index.js" is 8 characters long 
// so -8 removes last 8 characters
const currentWorkingDirectory = args[1].slice(0, -8);


Javascript
if (fs.existsSync(currentWorkingDirectory + 'todo.txt') === false) {
  let createStream = fs.createWriteStream('todo.txt');
  createStream.end();
}
if (fs.existsSync(currentWorkingDirectory + 'done.txt') === false) {
  let createStream = fs.createWriteStream('done.txt');
  createStream.end();
}


Javascript
const InfoFunction = () => {
  const UsageText = `
Usage :-
$ node index.js add "todo item"  # Add a new todo
$ node index.js ls               # Show remaining todos
$ node index.js del NUMBER       # Delete a todo
$ node index.js done NUMBER      # Complete a todo
$ node index.js help             # Show usage
$ node index.js report           # Statistics`;
  
  console.log(UsageText);
};


Javascript
const listFunction = () => {
  
  // Create a empty array
  let data = []; 
    
  // Read from todo.txt and convert it
  // into a string
  const fileData = fs.readFileSync(
    currentWorkingDirectory + 'todo.txt')
  .toString(); 
    
  // Split the string and store into array
  data = fileData.split('\n'); 
    
  // Filter the string for any empty lines in the file
  let filterData = data.filter(function (value) {
    return value !== '';
  }); 
    
  if (filterData.length === 0) {
    console.log('There are no pending todos!');
  }
    
  for (let i = 0; i < filterData.length; i++) {
    console.log((filterData.length - i) + '. ' 
    + filterData[i]);
  }
};


Javascript
const addFunction = () => {
  
  // New todo string argument is stored
  const newTask = args[3]; 
    
  // If argument is passed
  if (newTask) { 
    
    // Create a empty array
    let data = []; 
  
    // Read the data from file todo.txt and 
    // convert it in string
    const fileData = fs
      .readFileSync(currentWorkingDirectory + 'todo.txt')
      .toString(); 
        
    // New task is added to previous data  
    fs.writeFile(
      currentWorkingDirectory + 'todo.txt',
      newTask + '\n' + fileData, 
        
      function (err) {
  
        // Handle if there is any error
        if (err) throw err; 
          
        // Logs the new task added
        console.log('Added todo: "' + newTask + '"'); 
      },
    );
  } else { 
  
    // If argument was no passed
    console.log('Error: Missing todo string. Nothing added!');
  }
};


Javascript
const deleteFunction = () => {
  
  // Store which index is passed
  const deleteIndex = args[3]; 
    
  // If index is passed
  if (deleteIndex) { 
    
    // Create a empty array
    let data = []; 
      
    // Read the data from file and convert
    // it into string
    const fileData = fs
      .readFileSync(currentWorkingDirectory + 'todo.txt')
      .toString(); 
        
    data = fileData.split('\n');
      
    // Filter the data for any empty lines
    let filterData = data.filter(function (value) {
      return value !== ''; 
    });
      
    // If delete index is greater than no. of task 
    // or less than zero
    if (deleteIndex > filterData.length || deleteIndex <= 0) {
      console.log(
        'Error: todo #' + deleteIndex 
            + ' does not exist. Nothing deleted.',
      );   
    } else {
  
      // Remove the task
      filterData.splice(filterData.length - deleteIndex, 1); 
        
      // Join the array to form a string
      const newData = filterData.join('\n'); 
        
      // Write the new data back in file
      fs.writeFile(
        currentWorkingDirectory + 'todo.txt',
        newData, 
        function (err) {
          if (err) throw err;
  
          // Logs the deleted index
          console.log('Deleted todo #' + deleteIndex); 
        },
      );
    }
  } else { 
  
    // Index argument was no passed
    console.log(
'Error: Missing NUMBER for deleting todo.');
  }
};


Javascript
const doneFunction = () => {
  
  // Store the index passed as argument
  const doneIndex = args[3]; 
    
  // If argument is passed
  if (doneIndex) { 
    
    // Empty array
    let data = []; 
      
    // Create a new date object
    let dateobj = new Date(); 
      
    // Convert it to string and slice only the
    // date part, removing the time part
    let dateString = dateobj.toISOString().substring(0, 10); 
      
    // Read the data from todo.txt
    const fileData = fs
      .readFileSync(currentWorkingDirectory + 'todo.txt')
      .toString(); 
      
    // Read the data from done.txt
    const doneData = fs
      .readFileSync(currentWorkingDirectory + 'done.txt')
      .toString(); 
        
    // Split the todo.txt data
    data = fileData.split('\n'); 
      
    // Filter for any empty lines
    let filterData = data.filter(function (value) {
      return value !== '';
    }); 
      
    // If done index is greater than no. of task or <=0
    if (doneIndex > filterData.length || doneIndex <= 0) {
      console.log('Error: todo #' 
          + doneIndex + ' does not exist.');
    } else {
  
      // Delete the task from todo.txt
      // data and store it
      const deleted = filterData.splice(
          filterData.length - doneIndex, 1);
        
      // Join the array to create a string
      const newData = filterData.join('\n'); 
        
      // Write back the data in todo.txt
      fs.writeFile(
        currentWorkingDirectory + 'todo.txt',
        newData, 
        function (err) {
          if (err) throw err;
        },
      );
        
      // Write the stored task in done.txt
      // along with date string
      fs.writeFile( 
        currentWorkingDirectory + 'done.txt',
        'x ' + dateString + ' ' + deleted 
         + '\n' + doneData,
        function (err) {
          if (err) throw err;
          console.log('Marked todo #' 
            + doneIndex + ' as done.');
        },
      );
    }
  } else { 
  
    // If argument was not passed
    console.log('Error: Missing NUMBER for'
        + ' marking todo as done.');
  }
};


Javascript
const reportFunction = () => {
  
    // Create empty array for data of todo.txt
    let todoData = [];
  
    // Create empty array for data of done.txt
    let doneData = [];
  
    // Create a new date object
    let dateobj = new Date();
  
    // Slice the date part
    let dateString = dateobj.toISOString().substring(0, 10);
  
    // Read data from both the files
    const todo = fs.readFileSync(currentWorkingDirectory
                + 'todo.txt').toString();
    const done = fs.readFileSync(currentWorkingDirectory
                + 'done.txt').toString();
  
    // Split the data from both files
    todoData = todo.split('\n');
  
    doneData = done.split('\n');
    let filterTodoData = todoData.filter(function(value) {
        return value !== '';
    });
  
    let filterDoneData = doneData.filter(function(value) {
  
        // Filter both the data for empty lines
        return value !== '';
    });
  
    console.log(
        dateString +
        ' ' +
        'Pending : ' +
        filterTodoData.length +
        ' Completed : ' +
        filterDoneData.length,
        // Log the stats calculated
    );
};


Javascript
switch (args[2]) {
  case 'add': {
    addFunction();
    break;
  }
  
  case 'ls': {
    listFunction();
    break;
  }
  
  case 'del': {
    deleteFunction();
    break;
  }
    
  case 'done': {
    doneFunction();
    break;
  }
    
  case 'help': {
    InfoFunction();
    break;
  }
    
  case 'report': {
    reportFunction();
    break;
  }
    
  default: {
    InfoFunction();
    // We will display help when no 
    // argument is passed or invalid
    // argument  is passed
  }
}


Javascript
const fs = require('fs');
  
const args = process.argv;
  
// The "index.js" is 8 characters long so -8
// removes last 8 characters
const currentWorkingDirectory = args[1].slice(0, -8);
  
  
if (fs.existsSync(currentWorkingDirectory +
        'todo.txt') === false) {
    let createStream = fs.createWriteStream('todo.txt');
    createStream.end();
}
if (fs.existsSync(currentWorkingDirectory +
        'done.txt') === false) {
    let createStream = fs.createWriteStream('done.txt');
    createStream.end();
}
  
const InfoFunction = () => {
    const UsageText = `
Usage :-
$ node index.js add "todo item"  # Add a new todo
$ node index.js ls               # Show remaining todos
$ node index.js del NUMBER       # Delete a todo
$ node index.js done NUMBER      # Complete a todo
$ node index.js help             # Show usage
$ node index.js report           # Statistics`;
  
    console.log(UsageText);
};
  
const listFunction = () => {
  
    // Create a empty array
    let data = [];
  
    // Read from todo.txt and convert it into a string
    const fileData = fs
        .readFileSync(currentWorkingDirectory +
            'todo.txt').toString();
  
    // Split the string and store into array
    data = fileData.split('\n');
  
    // Filter the string for any empty lines in the file
    let filterData = data.filter(function(value) {
        return value !== '';
    });
  
    if (filterData.length === 0) {
        console.log('There are no pending todos!');
    }
    for (let i = 0; i < filterData.length; i++) {
        console.log((filterData.length - i) + '. ' +
            filterData[i]);
    }
};
  
const addFunction = () => {
  
    // New todo string argument is stored
    const newTask = args[3];
  
    // If argument is passed
    if (newTask) {
  
        // create a empty array
        let data = [];
  
        // Read the data from file todo.txt and
        // convert it in string
        const fileData = fs
            .readFileSync(currentWorkingDirectory +
                'todo.txt').toString();
  
        // New task is added to previous data
        fs.writeFile(
            currentWorkingDirectory + 'todo.txt',
            newTask + '\n' + fileData,
  
            function(err) {
  
                // Handle if there is any error
                if (err) throw err;
  
                // Logs the new task added
                console.log('Added todo: "' + newTask + '"');
            },
        );
    } else {
  
        // If argument was no passed
        console.log('Error: Missing todo string.' +
            ' Nothing added!');
    }
};
  
const deleteFunction = () => {
  
    // Store which index is passed
    const deleteIndex = args[3];
  
    // If index is passed
    if (deleteIndex) {
  
        // Create a empty array
        let data = [];
  
        // Read the data from file and convert
        // it into string
        const fileData = fs
            .readFileSync(currentWorkingDirectory +
                'todo.txt').toString();
  
        data = fileData.split('\n');
        let filterData = data.filter(function(value) {
  
            // Filter the data for any empty lines
            return value !== '';
        });
  
        // If delete index is greater than no. of task
        // or less than zero
        if (deleteIndex > filterData.length || deleteIndex <= 0) {
            console.log(
                'Error: todo #' + deleteIndex +
                ' does not exist. Nothing deleted.',
            );
  
        } else {
              
            // Remove the task
            filterData.splice(filterData.length - deleteIndex, 1);
              
            // Join the array to form a string
            const newData = filterData.join('\n');
              
            // Write the new data back in file
            fs.writeFile(
                currentWorkingDirectory + 'todo.txt',
                newData, 
                function(err) {
                    if (err) throw err;
  
                    // Logs the deleted index
                    console.log('Deleted todo #' + deleteIndex);
                },
            );
        }
    } else {
  
        // Index argument was no passed
        console.log('Error: Missing NUMBER for deleting todo.');
    }
};
  
const doneFunction = () => {
      
    // Store the index passed as argument
    const doneIndex = args[3];
      
    // If argument is passed
    if (doneIndex) {
          
        // Empty array
        let data = [];
          
        // Create a new date object
        let dateobj = new Date();
          
        // Convert it to string and slice only the
        //  date part, removing the time part
        let dateString = dateobj.toISOString()
                    .substring(0, 10);
          
        // Read the data from todo.txt
        const fileData = fs
            .readFileSync(currentWorkingDirectory
                + 'todo.txt').toString();
          
        // Read the data from done.txt
        const doneData = fs
            .readFileSync(currentWorkingDirectory
                + 'done.txt').toString();
          
        // Split the todo.txt data
        data = fileData.split('\n');
          
        // Filter for any empty lines
        let filterData = data.filter(function(value) {
            return value !== '';
        });
          
        // If done index is greater than
        // no. of task or <=0
        if (doneIndex > filterData.length || doneIndex <= 0) {
            console.log('Error: todo #' + doneIndex 
                    + ' does not exist.');
              
        } else {
              
            // Delete the task from todo.txt data
            // and store it
            const deleted = filterData.splice(
                filterData.length - doneIndex, 1);
              
            // Join the array to create a string
            const newData = filterData.join('\n');
              
            // Write back the data in todo.txt
            fs.writeFile(
                currentWorkingDirectory + 'todo.txt',
                newData,
                  
                function(err) {
                    if (err) throw err;
                },
            );
            fs.writeFile(
  
                // Write the stored task in done.txt
                // along with date string
                currentWorkingDirectory + 'done.txt',
                'x ' + dateString + ' ' + deleted 
                                + '\n' + doneData,
                function(err) {
                    if (err) throw err;
                    console.log('Marked todo #' 
                        + doneIndex + ' as done.');
                },
            );
        }
    } else {
        // If argument was not passed
        console.log('Error: Missing NUMBER for '
                +  'marking todo as done.');
    }
};
  
const reportFunction = () => {
      
    // Create empty array for data of todo.txt
    let todoData = [];
      
    // Create empty array for data of done.txt
    let doneData = [];
      
    // Create a new date object
    let dateobj = new Date();
      
    // Slice the date part
    let dateString = dateobj.toISOString()
                    .substring(0, 10);
      
    // Read data from both the files
    const todo = fs.readFileSync(
            currentWorkingDirectory 
            + 'todo.txt').toString();
  
    const done = fs.readFileSync(
        currentWorkingDirectory 
        + 'done.txt').toString();
  
    // Split the data from both files
    todoData = todo.split('\n');
      
    doneData = done.split('\n');
    let filterTodoData = todoData.filter(function(value) {
        return value !== '';
    });
    let filterDoneData = doneData.filter(function(value) {
        return value !== '';
        // Filter both the data for empty lines
    });
    console.log(
        dateString +
        ' ' +
        'Pending : ' +
        filterTodoData.length +
        ' Completed : ' +
        filterDoneData.length,
        // Log the stats calculated
    );
};
  
switch (args[2]) {
    case 'add':
        {
            addFunction();
            break;
        }
  
    case 'ls':
        {
            listFunction();
            break;
        }
  
    case 'del':
        {
            deleteFunction();
            break;
        }
  
    case 'done':
        {
            doneFunction();
            break;
        }
  
    case 'help':
        {
            InfoFunction();
            break;
        }
  
    case 'report':
        {
            reportFunction();
            break;
        }
  
    default:
        {
            InfoFunction();
            // We will display help when no 
            // argument is passed or invalid
            // argument  is passed
        }
}


说明:我们将在一个名为todo.txt的文件中写入 todo 任务,当它们完成时,它们将从todo.txt中删除并写入done.txt 。该报告将显示已完成的待办事项数量以及剩余的待办事项数量。首先,我们将导入fs 模块,这将使我们能够访问文件系统。

然后,我们将使用process.argv获取传递的参数并将它们存储在名为args的变量中。 process.argv返回一个数组,其中包含节点模块的位置、当前工作目录和传递的其他参数。我们将通过删除文件名来检索cwd

接下来,我们将检查 cwd 中是否已经存在todo.txtdone.txt ,如果没有,我们将创建它们,如下所示:

Javascript

if (fs.existsSync(currentWorkingDirectory + 'todo.txt') === false) {
  let createStream = fs.createWriteStream('todo.txt');
  createStream.end();
}
if (fs.existsSync(currentWorkingDirectory + 'done.txt') === false) {
  let createStream = fs.createWriteStream('done.txt');
  createStream.end();
}

现在我们将创建不同的函数来显示使用情况、添加待办事项、删除待办事项等。它们将根据传递的参数被调用。

信息函数:显示使用格式。当帮助作为参数传递或没有参数传递时,它将被调用。

Javascript

const InfoFunction = () => {
  const UsageText = `
Usage :-
$ node index.js add "todo item"  # Add a new todo
$ node index.js ls               # Show remaining todos
$ node index.js del NUMBER       # Delete a todo
$ node index.js done NUMBER      # Complete a todo
$ node index.js help             # Show usage
$ node index.js report           # Statistics`;
  
  console.log(UsageText);
};

列表函数:它将从 todo.txt 中读取数据并以相应的数字显示它们。最近显示在顶部,数字最大。

Javascript

const listFunction = () => {
  
  // Create a empty array
  let data = []; 
    
  // Read from todo.txt and convert it
  // into a string
  const fileData = fs.readFileSync(
    currentWorkingDirectory + 'todo.txt')
  .toString(); 
    
  // Split the string and store into array
  data = fileData.split('\n'); 
    
  // Filter the string for any empty lines in the file
  let filterData = data.filter(function (value) {
    return value !== '';
  }); 
    
  if (filterData.length === 0) {
    console.log('There are no pending todos!');
  }
    
  for (let i = 0; i < filterData.length; i++) {
    console.log((filterData.length - i) + '. ' 
    + filterData[i]);
  }
};

添加函数:它会从 todo.txt 中读取内容,添加新的 todo,然后在 todo.txt 中重写。

注意:由于我们在 JavaScript 中写入和读取文件时没有设置文件中指针位置的功能,所以每次添加新数据时,我们都必须读取数据,进行修改,然后重新写入回来了。

Javascript

const addFunction = () => {
  
  // New todo string argument is stored
  const newTask = args[3]; 
    
  // If argument is passed
  if (newTask) { 
    
    // Create a empty array
    let data = []; 
  
    // Read the data from file todo.txt and 
    // convert it in string
    const fileData = fs
      .readFileSync(currentWorkingDirectory + 'todo.txt')
      .toString(); 
        
    // New task is added to previous data  
    fs.writeFile(
      currentWorkingDirectory + 'todo.txt',
      newTask + '\n' + fileData, 
        
      function (err) {
  
        // Handle if there is any error
        if (err) throw err; 
          
        // Logs the new task added
        console.log('Added todo: "' + newTask + '"'); 
      },
    );
  } else { 
  
    // If argument was no passed
    console.log('Error: Missing todo string. Nothing added!');
  }
};

删除函数:它会从todo.txt中读取数据,删除相应的任务,并将数据重新写入文件中。

Javascript

const deleteFunction = () => {
  
  // Store which index is passed
  const deleteIndex = args[3]; 
    
  // If index is passed
  if (deleteIndex) { 
    
    // Create a empty array
    let data = []; 
      
    // Read the data from file and convert
    // it into string
    const fileData = fs
      .readFileSync(currentWorkingDirectory + 'todo.txt')
      .toString(); 
        
    data = fileData.split('\n');
      
    // Filter the data for any empty lines
    let filterData = data.filter(function (value) {
      return value !== ''; 
    });
      
    // If delete index is greater than no. of task 
    // or less than zero
    if (deleteIndex > filterData.length || deleteIndex <= 0) {
      console.log(
        'Error: todo #' + deleteIndex 
            + ' does not exist. Nothing deleted.',
      );   
    } else {
  
      // Remove the task
      filterData.splice(filterData.length - deleteIndex, 1); 
        
      // Join the array to form a string
      const newData = filterData.join('\n'); 
        
      // Write the new data back in file
      fs.writeFile(
        currentWorkingDirectory + 'todo.txt',
        newData, 
        function (err) {
          if (err) throw err;
  
          // Logs the deleted index
          console.log('Deleted todo #' + deleteIndex); 
        },
      );
    }
  } else { 
  
    // Index argument was no passed
    console.log(
'Error: Missing NUMBER for deleting todo.');
  }
};

完成函数:该函数将从todo.txt读取数据,将其拆分为一个数组,存储要标记为完成的任务,从todo.txt中删除它,将数据重新写入todo.txt 。现在我们将在done.txt 中写入我们存储的已删除任务以及当前日期。

Javascript

const doneFunction = () => {
  
  // Store the index passed as argument
  const doneIndex = args[3]; 
    
  // If argument is passed
  if (doneIndex) { 
    
    // Empty array
    let data = []; 
      
    // Create a new date object
    let dateobj = new Date(); 
      
    // Convert it to string and slice only the
    // date part, removing the time part
    let dateString = dateobj.toISOString().substring(0, 10); 
      
    // Read the data from todo.txt
    const fileData = fs
      .readFileSync(currentWorkingDirectory + 'todo.txt')
      .toString(); 
      
    // Read the data from done.txt
    const doneData = fs
      .readFileSync(currentWorkingDirectory + 'done.txt')
      .toString(); 
        
    // Split the todo.txt data
    data = fileData.split('\n'); 
      
    // Filter for any empty lines
    let filterData = data.filter(function (value) {
      return value !== '';
    }); 
      
    // If done index is greater than no. of task or <=0
    if (doneIndex > filterData.length || doneIndex <= 0) {
      console.log('Error: todo #' 
          + doneIndex + ' does not exist.');
    } else {
  
      // Delete the task from todo.txt
      // data and store it
      const deleted = filterData.splice(
          filterData.length - doneIndex, 1);
        
      // Join the array to create a string
      const newData = filterData.join('\n'); 
        
      // Write back the data in todo.txt
      fs.writeFile(
        currentWorkingDirectory + 'todo.txt',
        newData, 
        function (err) {
          if (err) throw err;
        },
      );
        
      // Write the stored task in done.txt
      // along with date string
      fs.writeFile( 
        currentWorkingDirectory + 'done.txt',
        'x ' + dateString + ' ' + deleted 
         + '\n' + doneData,
        function (err) {
          if (err) throw err;
          console.log('Marked todo #' 
            + doneIndex + ' as done.');
        },
      );
    }
  } else { 
  
    // If argument was not passed
    console.log('Error: Missing NUMBER for'
        + ' marking todo as done.');
  }
};

报表函数:它会从todo.txtdone.txt读取数据,计算每个任务的数量,并显示有多少任务已完成,有多少待定。

Javascript

const reportFunction = () => {
  
    // Create empty array for data of todo.txt
    let todoData = [];
  
    // Create empty array for data of done.txt
    let doneData = [];
  
    // Create a new date object
    let dateobj = new Date();
  
    // Slice the date part
    let dateString = dateobj.toISOString().substring(0, 10);
  
    // Read data from both the files
    const todo = fs.readFileSync(currentWorkingDirectory
                + 'todo.txt').toString();
    const done = fs.readFileSync(currentWorkingDirectory
                + 'done.txt').toString();
  
    // Split the data from both files
    todoData = todo.split('\n');
  
    doneData = done.split('\n');
    let filterTodoData = todoData.filter(function(value) {
        return value !== '';
    });
  
    let filterDoneData = doneData.filter(function(value) {
  
        // Filter both the data for empty lines
        return value !== '';
    });
  
    console.log(
        dateString +
        ' ' +
        'Pending : ' +
        filterTodoData.length +
        ' Completed : ' +
        filterDoneData.length,
        // Log the stats calculated
    );
};

现在由于我们已经创建了所有函数,现在我们将只放置一个 switch 语句并根据传递的参数调用函数。

Javascript

switch (args[2]) {
  case 'add': {
    addFunction();
    break;
  }
  
  case 'ls': {
    listFunction();
    break;
  }
  
  case 'del': {
    deleteFunction();
    break;
  }
    
  case 'done': {
    doneFunction();
    break;
  }
    
  case 'help': {
    InfoFunction();
    break;
  }
    
  case 'report': {
    reportFunction();
    break;
  }
    
  default: {
    InfoFunction();
    // We will display help when no 
    // argument is passed or invalid
    // argument  is passed
  }
}

文件名:index.js我们最终的 index.js 文件将如下所示:

Javascript

const fs = require('fs');
  
const args = process.argv;
  
// The "index.js" is 8 characters long so -8
// removes last 8 characters
const currentWorkingDirectory = args[1].slice(0, -8);
  
  
if (fs.existsSync(currentWorkingDirectory +
        'todo.txt') === false) {
    let createStream = fs.createWriteStream('todo.txt');
    createStream.end();
}
if (fs.existsSync(currentWorkingDirectory +
        'done.txt') === false) {
    let createStream = fs.createWriteStream('done.txt');
    createStream.end();
}
  
const InfoFunction = () => {
    const UsageText = `
Usage :-
$ node index.js add "todo item"  # Add a new todo
$ node index.js ls               # Show remaining todos
$ node index.js del NUMBER       # Delete a todo
$ node index.js done NUMBER      # Complete a todo
$ node index.js help             # Show usage
$ node index.js report           # Statistics`;
  
    console.log(UsageText);
};
  
const listFunction = () => {
  
    // Create a empty array
    let data = [];
  
    // Read from todo.txt and convert it into a string
    const fileData = fs
        .readFileSync(currentWorkingDirectory +
            'todo.txt').toString();
  
    // Split the string and store into array
    data = fileData.split('\n');
  
    // Filter the string for any empty lines in the file
    let filterData = data.filter(function(value) {
        return value !== '';
    });
  
    if (filterData.length === 0) {
        console.log('There are no pending todos!');
    }
    for (let i = 0; i < filterData.length; i++) {
        console.log((filterData.length - i) + '. ' +
            filterData[i]);
    }
};
  
const addFunction = () => {
  
    // New todo string argument is stored
    const newTask = args[3];
  
    // If argument is passed
    if (newTask) {
  
        // create a empty array
        let data = [];
  
        // Read the data from file todo.txt and
        // convert it in string
        const fileData = fs
            .readFileSync(currentWorkingDirectory +
                'todo.txt').toString();
  
        // New task is added to previous data
        fs.writeFile(
            currentWorkingDirectory + 'todo.txt',
            newTask + '\n' + fileData,
  
            function(err) {
  
                // Handle if there is any error
                if (err) throw err;
  
                // Logs the new task added
                console.log('Added todo: "' + newTask + '"');
            },
        );
    } else {
  
        // If argument was no passed
        console.log('Error: Missing todo string.' +
            ' Nothing added!');
    }
};
  
const deleteFunction = () => {
  
    // Store which index is passed
    const deleteIndex = args[3];
  
    // If index is passed
    if (deleteIndex) {
  
        // Create a empty array
        let data = [];
  
        // Read the data from file and convert
        // it into string
        const fileData = fs
            .readFileSync(currentWorkingDirectory +
                'todo.txt').toString();
  
        data = fileData.split('\n');
        let filterData = data.filter(function(value) {
  
            // Filter the data for any empty lines
            return value !== '';
        });
  
        // If delete index is greater than no. of task
        // or less than zero
        if (deleteIndex > filterData.length || deleteIndex <= 0) {
            console.log(
                'Error: todo #' + deleteIndex +
                ' does not exist. Nothing deleted.',
            );
  
        } else {
              
            // Remove the task
            filterData.splice(filterData.length - deleteIndex, 1);
              
            // Join the array to form a string
            const newData = filterData.join('\n');
              
            // Write the new data back in file
            fs.writeFile(
                currentWorkingDirectory + 'todo.txt',
                newData, 
                function(err) {
                    if (err) throw err;
  
                    // Logs the deleted index
                    console.log('Deleted todo #' + deleteIndex);
                },
            );
        }
    } else {
  
        // Index argument was no passed
        console.log('Error: Missing NUMBER for deleting todo.');
    }
};
  
const doneFunction = () => {
      
    // Store the index passed as argument
    const doneIndex = args[3];
      
    // If argument is passed
    if (doneIndex) {
          
        // Empty array
        let data = [];
          
        // Create a new date object
        let dateobj = new Date();
          
        // Convert it to string and slice only the
        //  date part, removing the time part
        let dateString = dateobj.toISOString()
                    .substring(0, 10);
          
        // Read the data from todo.txt
        const fileData = fs
            .readFileSync(currentWorkingDirectory
                + 'todo.txt').toString();
          
        // Read the data from done.txt
        const doneData = fs
            .readFileSync(currentWorkingDirectory
                + 'done.txt').toString();
          
        // Split the todo.txt data
        data = fileData.split('\n');
          
        // Filter for any empty lines
        let filterData = data.filter(function(value) {
            return value !== '';
        });
          
        // If done index is greater than
        // no. of task or <=0
        if (doneIndex > filterData.length || doneIndex <= 0) {
            console.log('Error: todo #' + doneIndex 
                    + ' does not exist.');
              
        } else {
              
            // Delete the task from todo.txt data
            // and store it
            const deleted = filterData.splice(
                filterData.length - doneIndex, 1);
              
            // Join the array to create a string
            const newData = filterData.join('\n');
              
            // Write back the data in todo.txt
            fs.writeFile(
                currentWorkingDirectory + 'todo.txt',
                newData,
                  
                function(err) {
                    if (err) throw err;
                },
            );
            fs.writeFile(
  
                // Write the stored task in done.txt
                // along with date string
                currentWorkingDirectory + 'done.txt',
                'x ' + dateString + ' ' + deleted 
                                + '\n' + doneData,
                function(err) {
                    if (err) throw err;
                    console.log('Marked todo #' 
                        + doneIndex + ' as done.');
                },
            );
        }
    } else {
        // If argument was not passed
        console.log('Error: Missing NUMBER for '
                +  'marking todo as done.');
    }
};
  
const reportFunction = () => {
      
    // Create empty array for data of todo.txt
    let todoData = [];
      
    // Create empty array for data of done.txt
    let doneData = [];
      
    // Create a new date object
    let dateobj = new Date();
      
    // Slice the date part
    let dateString = dateobj.toISOString()
                    .substring(0, 10);
      
    // Read data from both the files
    const todo = fs.readFileSync(
            currentWorkingDirectory 
            + 'todo.txt').toString();
  
    const done = fs.readFileSync(
        currentWorkingDirectory 
        + 'done.txt').toString();
  
    // Split the data from both files
    todoData = todo.split('\n');
      
    doneData = done.split('\n');
    let filterTodoData = todoData.filter(function(value) {
        return value !== '';
    });
    let filterDoneData = doneData.filter(function(value) {
        return value !== '';
        // Filter both the data for empty lines
    });
    console.log(
        dateString +
        ' ' +
        'Pending : ' +
        filterTodoData.length +
        ' Completed : ' +
        filterDoneData.length,
        // Log the stats calculated
    );
};
  
switch (args[2]) {
    case 'add':
        {
            addFunction();
            break;
        }
  
    case 'ls':
        {
            listFunction();
            break;
        }
  
    case 'del':
        {
            deleteFunction();
            break;
        }
  
    case 'done':
        {
            doneFunction();
            break;
        }
  
    case 'help':
        {
            InfoFunction();
            break;
        }
  
    case 'report':
        {
            reportFunction();
            break;
        }
  
    default:
        {
            InfoFunction();
            // We will display help when no 
            // argument is passed or invalid
            // argument  is passed
        }
}

运行应用程序的步骤:

使用以下命令运行index.js文件:

node index.js

输出: