[6a3a178] | 1 | # External Editor
|
---|
| 2 |
|
---|
| 3 | [![ExternalEditor on Travis CI](https://img.shields.io/travis/mrkmg/node-external-editor.svg?style=flat-square)](https://travis-ci.org/mrkmg/node-external-editor/branches)
|
---|
| 4 | [![ExternalEditor on NPM](https://img.shields.io/npm/v/external-editor.svg?style=flat-square)](https://www.npmjs.com/package/external-editor)
|
---|
| 5 | [![ExternalEditor uses the MIT](https://img.shields.io/npm/l/external-editor.svg?style=flat-square)](https://opensource.org/licenses/MIT)
|
---|
| 6 |
|
---|
| 7 |
|
---|
| 8 | A node module to edit a string with a users preferred text editor using $VISUAL or $ENVIRONMENT.
|
---|
| 9 |
|
---|
| 10 | Version: 3.1.0
|
---|
| 11 |
|
---|
| 12 | As of version 3.0.0, the minimum version of node supported is 4.
|
---|
| 13 |
|
---|
| 14 | ## Install
|
---|
| 15 |
|
---|
| 16 | `npm install external-editor --save`
|
---|
| 17 |
|
---|
| 18 | ## Usage
|
---|
| 19 |
|
---|
| 20 | A simple example using the `.edit` convenience method
|
---|
| 21 |
|
---|
| 22 | import {edit} from "external-editor";
|
---|
| 23 | const data = edit('\n\n# Please write your text above');
|
---|
| 24 | console.log(data);
|
---|
| 25 |
|
---|
| 26 | A full featured example
|
---|
| 27 |
|
---|
| 28 | import {ExternalEditor, CreateFileError, ReadFileError, RemoveFileError} from "external-editor"
|
---|
| 29 |
|
---|
| 30 | try {
|
---|
| 31 | const editor = new ExternalEditor();
|
---|
| 32 | const text = editor.run() // the text is also available in editor.text
|
---|
| 33 |
|
---|
| 34 | if (editor.last_exit_status !== 0) {
|
---|
| 35 | console.log("The editor exited with a non-zero code");
|
---|
| 36 | }
|
---|
| 37 | } catch (err) {
|
---|
| 38 | if (err instanceOf CreateFileError) {
|
---|
| 39 | console.log('Failed to create the temporary file');
|
---|
| 40 | } else if (err instanceOf ReadFileError) {
|
---|
| 41 | console.log('Failed to read the temporary file');
|
---|
| 42 | } else if (err instanceOf LaunchEditorError) {
|
---|
| 43 | console.log('Failed to launch your editor');
|
---|
| 44 | } else {
|
---|
| 45 | throw err;
|
---|
| 46 | }
|
---|
| 47 | }
|
---|
| 48 |
|
---|
| 49 | // Do things with the text
|
---|
| 50 |
|
---|
| 51 | // Eventually call the cleanup to remove the temporary file
|
---|
| 52 | try {
|
---|
| 53 | editor.cleanup();
|
---|
| 54 | } catch (err) {
|
---|
| 55 | if (err instanceOf RemoveFileError) {
|
---|
| 56 | console.log('Failed to remove the temporary file');
|
---|
| 57 | } else {
|
---|
| 58 | throw err
|
---|
| 59 | }
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 |
|
---|
| 63 | #### API
|
---|
| 64 | **Convenience Methods**
|
---|
| 65 |
|
---|
| 66 | - `edit(text, config)`
|
---|
| 67 | - `text` (string) *Optional* Defaults to empty string
|
---|
| 68 | - `config` (Config) *Optional* Options for temporary file creation
|
---|
| 69 | - **Returns** (string) The contents of the file
|
---|
| 70 | - Could throw `CreateFileError`, `ReadFileError`, or `LaunchEditorError`, or `RemoveFileError`
|
---|
| 71 | - `editAsync(text, callback, config)`
|
---|
| 72 | - `text` (string) *Optional* Defaults to empty string
|
---|
| 73 | - `callback` (function (error, text))
|
---|
| 74 | - `error` could be of type `CreateFileError`, `ReadFileError`, or `LaunchEditorError`, or `RemoveFileError`
|
---|
| 75 | - `text`(string) The contents of the file
|
---|
| 76 | - `config` (Config) *Optional* Options for temporary file creation
|
---|
| 77 |
|
---|
| 78 |
|
---|
| 79 | **Errors**
|
---|
| 80 |
|
---|
| 81 | - `CreateFileError` Error thrown if the temporary file could not be created.
|
---|
| 82 | - `ReadFileError` Error thrown if the temporary file could not be read.
|
---|
| 83 | - `RemoveFileError` Error thrown if the temporary file could not be removed during cleanup.
|
---|
| 84 | - `LaunchEditorError` Error thrown if the editor could not be launched.
|
---|
| 85 |
|
---|
| 86 | **External Editor Public Methods**
|
---|
| 87 |
|
---|
| 88 | - `new ExternalEditor(text, config)`
|
---|
| 89 | - `text` (string) *Optional* Defaults to empty string
|
---|
| 90 | - `config` (Config) *Optional* Options for temporary file creation
|
---|
| 91 | - Could throw `CreateFileError`
|
---|
| 92 | - `run()` Launches the editor.
|
---|
| 93 | - **Returns** (string) The contents of the file
|
---|
| 94 | - Could throw `LaunchEditorError` or `ReadFileError`
|
---|
| 95 | - `runAsync(callback)` Launches the editor in an async way
|
---|
| 96 | - `callback` (function (error, text))
|
---|
| 97 | - `error` could be of type `ReadFileError` or `LaunchEditorError`
|
---|
| 98 | - `text`(string) The contents of the file
|
---|
| 99 | - `cleanup()` Removes the temporary file.
|
---|
| 100 | - Could throw `RemoveFileError`
|
---|
| 101 |
|
---|
| 102 | **External Editor Public Properties**
|
---|
| 103 |
|
---|
| 104 | - `text` (string) *readonly* The text in the temporary file.
|
---|
| 105 | - `editor.bin` (string) The editor determined from the environment.
|
---|
| 106 | - `editor.args` (array) Default arguments for the bin
|
---|
| 107 | - `tempFile` (string) Path to temporary file. Can be changed, but be careful as the temporary file probably already
|
---|
| 108 | exists and would need be removed manually.
|
---|
| 109 | - `lastExitStatus` (number) The last exit code emitted from the editor.
|
---|
| 110 |
|
---|
| 111 | **Config Options**
|
---|
| 112 |
|
---|
| 113 | - `prefix` (string) *Optional* A prefix for the file name.
|
---|
| 114 | - `postfix` (string; *Optional* A postfix for the file name. Useful if you want to provide an extension.
|
---|
| 115 | - `mode` (number) *Optional* Which mode to create the file with. e.g. 644
|
---|
| 116 | - `template` (string) *Optional* A template for the filename. See [tmp](https://www.npmjs.com/package/tmp).
|
---|
| 117 | - `dir` (string) *Optional* Which path to store the file.
|
---|
| 118 |
|
---|
| 119 | ## Errors
|
---|
| 120 |
|
---|
| 121 | All errors have a simple message explaining what went wrong. They all also have an `originalError` property containing
|
---|
| 122 | the original error thrown for debugging purposes.
|
---|
| 123 |
|
---|
| 124 | ## Why Synchronous?
|
---|
| 125 |
|
---|
| 126 | Everything is synchronous to make sure the editor has complete control of the stdin and stdout. Testing has shown
|
---|
| 127 | async launching of the editor can lead to issues when using readline or other packages which try to read from stdin or
|
---|
| 128 | write to stdout. Seeing as this will be used in an interactive CLI environment, I made the decision to force the package
|
---|
| 129 | to be synchronous. If you know a reliable way to force all stdin and stdout to be limited only to the child_process,
|
---|
| 130 | please submit a PR.
|
---|
| 131 |
|
---|
| 132 | If async is really needed, you can use `editAsync` or `runAsync`. If you are using readline or have anything else
|
---|
| 133 | listening to the stdin or you write to stdout, you will most likely have problem, so make sure to remove any other
|
---|
| 134 | listeners on stdin, stdout, or stderr.
|
---|
| 135 |
|
---|
| 136 | ## Demo
|
---|
| 137 |
|
---|
| 138 | [![asciicast](https://asciinema.org/a/a1qh9lypbe65mj0ivfuoslz2s.png)](https://asciinema.org/a/a1qh9lypbe65mj0ivfuoslz2s)
|
---|
| 139 |
|
---|
| 140 | ## Breaking Changes from v2 to v3
|
---|
| 141 |
|
---|
| 142 | - NodeJS 0.12 support dropped.
|
---|
| 143 | - Switched to named imports.
|
---|
| 144 | - All "snake_cased" variables and properties are now "camelCased".
|
---|
| 145 | - `ExternalEditor.temp_file` is now `ExternalEditor.tempFile`.
|
---|
| 146 | - `ExternalEditor.last_exit_status` is now `ExternalEditor.lastExitStatus`.
|
---|
| 147 | - `Error.original_error` is now `Error.originalError`.
|
---|
| 148 |
|
---|
| 149 | ## License
|
---|
| 150 |
|
---|
| 151 | The MIT License (MIT)
|
---|
| 152 |
|
---|
| 153 | Copyright (c) 2016-2018 Kevin Gravier
|
---|
| 154 |
|
---|
| 155 | Permission is hereby granted, free of charge, to any person obtaining a copy
|
---|
| 156 | of this software and associated documentation files (the "Software"), to deal
|
---|
| 157 | in the Software without restriction, including without limitation the rights
|
---|
| 158 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
---|
| 159 | copies of the Software, and to permit persons to whom the Software is
|
---|
| 160 | furnished to do so, subject to the following conditions:
|
---|
| 161 |
|
---|
| 162 | The above copyright notice and this permission notice shall be included in all
|
---|
| 163 | copies or substantial portions of the Software.
|
---|
| 164 |
|
---|
| 165 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
---|
| 166 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
| 167 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
---|
| 168 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
---|
| 169 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
---|
| 170 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
---|
| 171 | SOFTWARE.
|
---|