///////////////////////////////////////////////////////////////////////////
| 604 | |
| 605 | //////////////////////////////////////////////////////////////////////////////// |
| 606 | CmdEdit::editResult CmdEdit::editFile(Task& task) { |
| 607 | // Check for file permissions. |
| 608 | Directory location(Context::getContext().config.get("data.location")); |
| 609 | if (!location.writable()) throw std::string("Your data.location directory is not writable."); |
| 610 | |
| 611 | // Create a temp file name in data.location. |
| 612 | std::stringstream file; |
| 613 | file << "task." << task.get("uuid").substr(0, 8) << ".task"; |
| 614 | |
| 615 | // Determine the output date format, which uses a hierarchy of definitions. |
| 616 | // rc.dateformat.edit |
| 617 | // rc.dateformat |
| 618 | auto dateformat = Context::getContext().config.get("dateformat.edit"); |
| 619 | if (dateformat == "") dateformat = Context::getContext().config.get("dateformat"); |
| 620 | |
| 621 | // Change directory for the editor, doing nothing on error. |
| 622 | auto current_dir = Directory::cwd(); |
| 623 | chdir(location._data.c_str()); |
| 624 | |
| 625 | // Check if the file already exists, if so, bail out |
| 626 | Path filepath = Path(file.str()); |
| 627 | if (filepath.exists()) throw std::string("Task is already being edited."); |
| 628 | |
| 629 | // Format the contents, T -> text, write to a file. |
| 630 | auto before = formatTask(task, dateformat); |
| 631 | auto before_orig = before; |
| 632 | File::write(file.str(), before); |
| 633 | |
| 634 | // Determine correct editor: .taskrc:editor > $VISUAL > $EDITOR > vi |
| 635 | auto editor = Context::getContext().config.get("editor"); |
| 636 | char* peditor = getenv("VISUAL"); |
| 637 | if (editor == "" && peditor) editor = std::string(peditor); |
| 638 | peditor = getenv("EDITOR"); |
| 639 | if (editor == "" && peditor) editor = std::string(peditor); |
| 640 | if (editor == "") editor = "vi"; |
| 641 | |
| 642 | // Complete the command line. |
| 643 | editor += ' '; |
| 644 | editor += '"' + file.str() + '"'; |
| 645 | |
| 646 | ARE_THESE_REALLY_HARMFUL: |
| 647 | bool changes = false; // No changes made. |
| 648 | |
| 649 | // Launch the editor. |
| 650 | std::cout << format("Launching '{1}' now...\n", editor); |
| 651 | int exitcode = system(editor.c_str()); |
| 652 | auto captured_errno = errno; |
| 653 | if (0 == exitcode) |
| 654 | std::cout << "Editing complete.\n"; |
| 655 | else { |
| 656 | std::cout << format("Editing failed with exit code {1}.\n", exitcode); |
| 657 | if (-1 == exitcode) std::cout << std::strerror(captured_errno) << '\n'; |
| 658 | File::remove(file.str()); |
| 659 | return CmdEdit::editResult::error; |
| 660 | } |
| 661 | |
| 662 | // Slurp file. |
| 663 | std::string after; |