Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions src-node/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const fs = require('fs');
const fsPromise = require('fs').promises;
const path = require('path');
const os = require('os');
const {lintFile} = require("./ESLint/service");
let openModule, open; // dynamic import when needed

Expand Down Expand Up @@ -146,6 +147,86 @@
});
}

/**
* If it's a dir that exists, returns that
* If it's a file, it returns the parent directory if it exists
* If no parent exists, it returns the original path.
*
* @param {string} cwd - The path to validate.
* @returns {string} - An existing directory or the original path.
*/
function _getValidDirectory(cwd) {
let currentPath = path.resolve(cwd);
const exists = fs.existsSync(currentPath);

if (exists) {
const isPathDir = fs.statSync(currentPath).isDirectory();
if(isPathDir){
return currentPath;
}
return path.dirname(currentPath);
}

currentPath = path.dirname(currentPath);
if(fs.existsSync(currentPath)){
return currentPath;
}

// If no valid directory is found, fallback to the original cwd
return cwd;
}

/**
* Opens a native terminal window with the specified current working directory.
* Returns a Promise that resolves if the terminal starts successfully, or rejects if it fails.
*
* @param {string} cwd - The directory to open the terminal in.
* @param {boolean} usePowerShell - Whether to use PowerShell instead of cmd on Windows.
* @returns {Promise<void>} - Resolves if the terminal starts, rejects otherwise.
*/
function openNativeTerminal({cwd, usePowerShell = false}) {
return new Promise((resolve, reject) => {
const platform = os.platform();
cwd = _getValidDirectory(cwd);
let command;

if (platform === 'win32') {
if (usePowerShell) {
command = `start powershell -NoExit -Command "Set-Location -Path '${cwd}'"`;
} else {
command = `start cmd /K "cd /D ${cwd}"`;
}
} else if (platform === 'darwin') {
command = `open -a Terminal "${cwd}"`;
} else {
command = `
if command -v gnome-terminal > /dev/null 2>&1; then
gnome-terminal --working-directory="${cwd}";
elif command -v konsole > /dev/null 2>&1; then
konsole --workdir "${cwd}";
elif command -v xfce4-terminal > /dev/null 2>&1; then
xfce4-terminal --working-directory="${cwd}";
elif command -v xterm > /dev/null 2>&1; then
xterm -e "cd '${cwd}' && bash";
else
echo "No supported terminal emulator found.";
exit 1;
fi
`;
}

// Execute the terminal command
exec(command, (error) => {
if (error) {
reject(new Error(`Failed to start terminal: ${error.message}`));
} else {
resolve();
}
});
});
}


async function ESLintFile({text, fullFilePath, projectFullPath}) {
return lintFile(text, fullFilePath, projectFullPath);
}
Expand All @@ -161,5 +242,6 @@
exports.openUrlInBrowser = openUrlInBrowser;
exports.getEnvironmentVariable = getEnvironmentVariable;
exports.ESLintFile = ESLintFile;
exports.openNativeTerminal = openNativeTerminal;
exports._loadNodeExtensionModule = _loadNodeExtensionModule;
exports._npmInstallInFolder = _npmInstallInFolder;
12 changes: 12 additions & 0 deletions src/command/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ define(function (require, exports, module) {
/** Submenu for zoom options */
exports.VIEW_ZOOM_SUBMENU = "zoom-view-submenu";

/** Submenu for Open in project context menu */
exports.OPEN_IN_SUBMENU = "file-open-in-submenu";

/** Submenu for Open in working set context menu */
exports.OPEN_IN_SUBMENU_WS = "file-open-in-submenu-ws";

/** Increases editor font size */
exports.VIEW_INCREASE_FONT_SIZE = "view.increaseFontSize"; // ViewCommandHandlers.js _handleIncreaseFontSize()

Expand Down Expand Up @@ -334,6 +340,12 @@ define(function (require, exports, module) {
/** Shows current file in OS file explorer */
exports.NAVIGATE_SHOW_IN_OS = "navigate.showInOS"; // DocumentCommandHandlers.js handleShowInOS()

/** Shows current file in OS Terminal */
exports.NAVIGATE_OPEN_IN_TERMINAL = "navigate.openInTerminal";

/** Shows current file in open powershell in Windows os */
exports.NAVIGATE_OPEN_IN_POWERSHELL = "navigate.openInPowerShell";

/** Opens quick open dialog */
exports.NAVIGATE_QUICK_OPEN = "navigate.quickOpen"; // QuickOpen.js doFileSearch()

Expand Down
16 changes: 13 additions & 3 deletions src/command/DefaultMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ define(function (require, exports, module) {
return err;
}
_setContextMenuItemsVisible(isPresent, [Commands.FILE_RENAME,
Commands.NAVIGATE_SHOW_IN_FILE_TREE, Commands.NAVIGATE_SHOW_IN_OS]);
Commands.NAVIGATE_SHOW_IN_FILE_TREE, Commands.NAVIGATE_SHOW_IN_OS, Commands.NAVIGATE_OPEN_IN_TERMINAL]);
});
}
}
Expand Down Expand Up @@ -297,7 +297,12 @@ define(function (require, exports, module) {
workingset_cmenu.addMenuItem(Commands.FILE_SAVE);
workingset_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_FILE_TREE);
if(Phoenix.isNativeApp){
workingset_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);
let subMenu = workingset_cmenu.addSubMenu(Strings.CMD_OPEN_IN, Commands.OPEN_IN_SUBMENU_WS);
subMenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);
subMenu.addMenuItem(Commands.NAVIGATE_OPEN_IN_TERMINAL);
if (brackets.platform === "win") {
subMenu.addMenuItem(Commands.NAVIGATE_OPEN_IN_POWERSHELL);
}
}
workingset_cmenu.addMenuDivider();
workingset_cmenu.addMenuItem(Commands.FILE_COPY);
Expand Down Expand Up @@ -331,7 +336,12 @@ define(function (require, exports, module) {
project_cmenu.addMenuItem(Commands.FILE_NEW);
project_cmenu.addMenuItem(Commands.FILE_NEW_FOLDER);
if(Phoenix.isNativeApp){
project_cmenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);
let subMenu = project_cmenu.addSubMenu(Strings.CMD_OPEN_IN, Commands.OPEN_IN_SUBMENU);
subMenu.addMenuItem(Commands.NAVIGATE_SHOW_IN_OS);
subMenu.addMenuItem(Commands.NAVIGATE_OPEN_IN_TERMINAL);
if (brackets.platform === "win") {
subMenu.addMenuItem(Commands.NAVIGATE_OPEN_IN_POWERSHELL);
}
}
project_cmenu.addMenuDivider();
project_cmenu.addMenuItem(Commands.FILE_CUT);
Expand Down
25 changes: 23 additions & 2 deletions src/document/DocumentCommandHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ define(function (require, exports, module) {
LanguageManager = require("language/LanguageManager"),
NewFileContentManager = require("features/NewFileContentManager"),
NodeConnector = require("NodeConnector"),
NodeUtils = require("utils/NodeUtils"),
_ = require("thirdparty/lodash");

/**
Expand Down Expand Up @@ -1959,6 +1960,20 @@ define(function (require, exports, module) {
}
}

function openDefaultTerminal() {
const entry = ProjectManager.getSelectedItem();
if (entry && entry.fullPath) {
NodeUtils.openNativeTerminal(entry.fullPath);
}
}

function openPowerShell() {
const entry = ProjectManager.getSelectedItem();
if (entry && entry.fullPath) {
NodeUtils.openNativeTerminal(entry.fullPath, true);
}
}

function raceAgainstTime(promise, timeout = 2000) {
const timeoutPromise = new Promise((_resolve, reject) => {
setTimeout(() => {
Expand Down Expand Up @@ -2251,11 +2266,13 @@ define(function (require, exports, module) {
exports._parseDecoratedPath = _parseDecoratedPath;

// Set some command strings
var quitString = Strings.CMD_QUIT,
showInOS = Strings.CMD_SHOW_IN_OS;
let quitString = Strings.CMD_QUIT,
showInOS = Strings.CMD_SHOW_IN_FILE_MANAGER,
defaultTerminal = Strings.CMD_OPEN_IN_TERMINAL;
if (brackets.platform === "win") {
quitString = Strings.CMD_EXIT;
showInOS = Strings.CMD_SHOW_IN_EXPLORER;
defaultTerminal = Strings.CMD_OPEN_IN_CMD;
} else if (brackets.platform === "mac") {
showInOS = Strings.CMD_SHOW_IN_FINDER;
}
Expand Down Expand Up @@ -2304,6 +2321,10 @@ define(function (require, exports, module) {

// Special Commands
CommandManager.register(showInOS, Commands.NAVIGATE_SHOW_IN_OS, handleShowInOS);
CommandManager.register(defaultTerminal, Commands.NAVIGATE_OPEN_IN_TERMINAL, openDefaultTerminal);
if (brackets.platform === "win") {
CommandManager.register(Strings.CMD_OPEN_IN_POWER_SHELL, Commands.NAVIGATE_OPEN_IN_POWERSHELL, openPowerShell);
}
CommandManager.register(Strings.CMD_NEW_BRACKETS_WINDOW, Commands.FILE_NEW_WINDOW, handleFileNewWindow);
CommandManager.register(quitString, Commands.FILE_QUIT, handleFileCloseWindow);
CommandManager.register(Strings.CMD_SHOW_IN_TREE, Commands.NAVIGATE_SHOW_IN_FILE_TREE, handleShowInTree);
Expand Down
10 changes: 7 additions & 3 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ define({
"CMD_FILE_REFRESH": "Refresh File Tree",
"CMD_FILE_SHOW_FOLDERS_FIRST": "Sort Folders First",
"CMD_QUIT": "Quit",
"CMD_OPEN_IN": "Open In",
// Used in native File menu on Windows
"CMD_EXIT": "Exit",

Expand Down Expand Up @@ -594,9 +595,12 @@ define({
"CMD_NEXT_DOC_LIST_ORDER": "Next Document in List",
"CMD_PREV_DOC_LIST_ORDER": "Previous Document in List",
"CMD_SHOW_IN_TREE": "Show in File Tree",
"CMD_SHOW_IN_EXPLORER": "Show in Explorer",
"CMD_SHOW_IN_FINDER": "Show in Finder",
"CMD_SHOW_IN_OS": "Show in OS Files",
"CMD_SHOW_IN_EXPLORER": "Windows File Explorer",
"CMD_SHOW_IN_FINDER": "macOS Finder",
"CMD_SHOW_IN_FILE_MANAGER": "File Manager",
"CMD_OPEN_IN_TERMINAL": "Terminal",
"CMD_OPEN_IN_CMD": "Command Prompt",
"CMD_OPEN_IN_POWER_SHELL": "Power Shell",
"CMD_SWITCH_PANE_FOCUS": "Switch Pane Focus",

// Debug menu commands
Expand Down
18 changes: 18 additions & 0 deletions src/utils/NodeUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,23 @@ define(function (require, exports, module) {
});
}

/**
* Runs ESLint on a file
* This is only available in the native app
*
* @param {string} cwd the working directory of terminal
* @param {boolean} [usePowerShell]
*/
async function openNativeTerminal(cwd, usePowerShell = false) {
if(!Phoenix.isNativeApp) {
throw new Error("openNativeTerminal not available in browser");
}
return utilsConnector.execPeer("openNativeTerminal", {
cwd: window.fs.getTauriPlatformPath(cwd),
usePowerShell
});
}

if(NodeConnector.isNodeAvailable()) {
// todo we need to update the strings if a user extension adds its translations. Since we dont support
// node extensions for now, should consider when we support node extensions.
Expand Down Expand Up @@ -195,6 +212,7 @@ define(function (require, exports, module) {
exports.openUrlInBrowser = openUrlInBrowser;
exports.ESLintFile = ESLintFile;
exports.getEnvironmentVariable = getEnvironmentVariable;
exports.openNativeTerminal = openNativeTerminal;

/**
* checks if Node connector is ready
Expand Down
Loading