From fd84eeefebc16e566a18d7400d3afff1c10e9bf6 Mon Sep 17 00:00:00 2001 From: Jen-Chieh Shen Date: Sat, 25 Feb 2023 17:56:23 -0800 Subject: [PATCH] fix(process): Workaround for arguments that contain whitespaces (#129) * fix(process): Workaround for arguments that contain whitespaces * changelog * Fix eval command * Remove useless function * change eval test --- .gitignore | 3 +++ CHANGELOG.md | 1 + cmds/core/emacs.js | 4 ++-- cmds/core/eval.js | 34 +++++++++++++++++++++++++++++++++- cmds/core/exec.js | 6 +++--- cmds/core/run.js | 6 +----- lisp/core/eval.el | 17 ++++++++++++----- src/util.js | 27 +++++++++++++++++++++++++-- test/commands/local/run.sh | 2 +- 9 files changed, 81 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index f7c2881c..1275f459 100644 --- a/.gitignore +++ b/.gitignore @@ -143,6 +143,9 @@ dist # internal test _test/ +# emacs +emacs_backtrace.txt + # ignore generated files *.elc diff --git a/CHANGELOG.md b/CHANGELOG.md index 156ebb44..5ae09d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how * feat: Add capability to search through path (#119) * Support DSL `package-descriptor` (#124) * Resolve the potential symlink to the bash script (#24, #125, and #126) +* Workaround for arguments that contain whitespaces (#128 and #129) ## 0.7.x > Released Sep 08, 2022 diff --git a/cmds/core/emacs.js b/cmds/core/emacs.js index 072c7144..916784d3 100644 --- a/cmds/core/emacs.js +++ b/cmds/core/emacs.js @@ -35,12 +35,12 @@ exports.builder = async (yargs) => { exports.handler = async (argv) => { let _path = UTIL.el_script('core/emacs'); - let default_cmd = ['-Q', '-l', _path]; + let default_cmd = ['emacs', '-Q', '-l', _path]; let rest = process.argv.slice(3); let cmd = default_cmd.concat(rest); UTIL.setup_env(); - let proc = child_process.spawn('emacs', cmd, { stdio: 'inherit' }); + let proc = child_process.spawn(UTIL.cli_args(cmd), { stdio: 'inherit', shell: true }); proc.on('close', function (code) { if (code == 0) return; diff --git a/cmds/core/eval.js b/cmds/core/eval.js index 3f7705d3..4f1c2b67 100644 --- a/cmds/core/eval.js +++ b/cmds/core/eval.js @@ -19,6 +19,9 @@ "use strict"; +const fs = require('fs'); +const child_process = require("child_process"); + exports.command = ['eval [form]']; exports.desc = 'Evaluate lisp form with a proper PATH'; exports.builder = { @@ -30,5 +33,34 @@ exports.builder = { }; exports.handler = async (argv) => { - await UTIL.e_call(argv, 'core/eval', '\"' + argv.form.replace(/[\\$'"]/g, "\\$&") + '\"'); + // setup environment, so Emacs can receive it + process.env.EASK_HOMEDIR = global.EASK_HOMEDIR; + + await UTIL.e_call(argv, 'core/eval', argv.form); + + if (!fs.existsSync(global.EASK_HOMEDIR)) { + return; + } + + console.log(''); + + let epf = global.EASK_HOMEDIR + 'exec-path'; + let lpf = global.EASK_HOMEDIR + 'load-path'; + + process.env.PATH = fs.readFileSync(epf, 'utf8'); + process.env.EMACSLOADPATH = fs.readFileSync(lpf, 'utf8');; + + let expressions = process.argv.slice(3); + + // XXX: Just replace `form` property, this is combined expression + argv.form = expressions.join(' '); + + let cmd = ['emacs', '--batch', '--eval', argv.form]; + + let proc = child_process.spawn(UTIL.cli_args(cmd), { stdio: 'inherit', shell: true }); + + proc.on('close', function (code) { + if (code == 0) return; + throw 'Exit with code: ' + code; + }); }; diff --git a/cmds/core/exec.js b/cmds/core/exec.js index 7f92554a..351b9992 100644 --- a/cmds/core/exec.js +++ b/cmds/core/exec.js @@ -43,15 +43,15 @@ exports.handler = async (argv) => { return; } + console.log(''); + let epf = global.EASK_HOMEDIR + 'exec-path'; let lpf = global.EASK_HOMEDIR + 'load-path'; process.env.PATH = fs.readFileSync(epf, 'utf8'); process.env.EMACSLOADPATH = fs.readFileSync(lpf, 'utf8');; - let program = cmd[0]; - let rest = cmd.slice(1); - let proc = child_process.spawn(program, rest, { stdio: 'inherit', shell: true }); + let proc = child_process.spawn(UTIL.cli_args(cmd), { stdio: 'inherit', shell: true }); proc.on('close', function (code) { if (code == 0) return; diff --git a/cmds/core/run.js b/cmds/core/run.js index dcf7eebc..105c145e 100644 --- a/cmds/core/run.js +++ b/cmds/core/run.js @@ -65,11 +65,7 @@ function startCommand(commands, count) { let command = commands[count]; console.log('[RUN]: ' + command); - let splitted = command.split(' '); - - let program = splitted[0]; - let rest = splitted.slice(1); - let proc = child_process.spawn(program, rest, { stdio: 'inherit', shell: true }); + let proc = child_process.spawn(command, { stdio: 'inherit', shell: true }); proc.on('close', function (code) { if (code == 0) { diff --git a/lisp/core/eval.el b/lisp/core/eval.el index e160cda5..00a53e2a 100644 --- a/lisp/core/eval.el +++ b/lisp/core/eval.el @@ -14,12 +14,19 @@ (file-name-directory (nth 1 (member "-scriptload" command-line-args)))) nil t) -(require 'thingatpt) +(eask-load "core/exec") (eask-start - (let ((form (eask-argv 0))) - (with-temp-buffer - (insert (thing-at-point--read-from-whole-string form)) - (eval-buffer)))) + (eask-defvc< 27 (eask-pkg-init)) ; XXX: remove this after we drop 26.x + (eask-setup-paths) + (ignore-errors (delete-directory eask-homedir t)) ; clean up + + (if-let ((name (eask-argv 0))) + (eask-with-progress + (ansi-green "Exporting environment variables... ") + (eask--export-env) + (ansi-green "done ✓")) + (eask-info "✗ (No expression found)") + (eask-help "core/eval"))) ;;; core/eval.el ends here diff --git a/src/util.js b/src/util.js index feb4bfdf..6777ddc2 100644 --- a/src/util.js +++ b/src/util.js @@ -22,6 +22,28 @@ const path = require('path'); const child_process = require("child_process"); +/** + * Form CLI arguments into a single string. + * @param { Array } argv - Argument vector. + */ +function cli_args(argv) { + let result = ''; + let first = true; + argv.forEach(function (element) { + // XXX: We wrap double quotes if the string contains spaces + if (/\s/g.test(element)) { + element = element.replaceAll('\"', '\\"'); // escape double quotes + element = '\"' + element + '\"'; + } + if (first) + result += element; + else + result += ' ' + element; + first = false; + }); + return result; +} + /* * Remove `undefined` item from the array * @param { Array } arr - target array @@ -118,7 +140,7 @@ async function e_call(argv, script, ...args) { return new Promise(resolve => { let _path = el_script(script); - let cmd_base = ['-Q', '--script', _path]; + let cmd_base = ['emacs', '-Q', '--script', _path]; let cmd_args = args.flat(); let cmd_global = _global_options(argv).flat(); let cmd = cmd_base.concat(cmd_args).concat(cmd_global); @@ -133,7 +155,7 @@ async function e_call(argv, script, ...args) { console.log('[DEBUG] emacs ' + cmd.join(' ')); setup_env(); - let proc = child_process.spawn('emacs', cmd, { stdio: 'inherit' }); + let proc = child_process.spawn(cli_args(cmd), { stdio: 'inherit', shell: true }); proc.on('close', function (code) { if (code == 0) { @@ -148,6 +170,7 @@ async function e_call(argv, script, ...args) { /* * Module Exports */ +module.exports.cli_args = cli_args; module.exports.plugin_dir = plugin_dir; module.exports.def_flag = def_flag; module.exports.setup_env = setup_env; diff --git a/test/commands/local/run.sh b/test/commands/local/run.sh index e337ee87..cf69f31a 100644 --- a/test/commands/local/run.sh +++ b/test/commands/local/run.sh @@ -57,7 +57,7 @@ eask run test eask run -all # Exection -eask eval '(progn (message "Hello World!~"))' +eask eval "(progn (require 'mini.emacs.pkg.1))" # Linter eask lint checkdoc