Skip to content
This repository has been archived by the owner on Dec 8, 2020. It is now read-only.

Commit

Permalink
Added the cargoCwd configuration parameter. (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
KalitaAlexey authored Feb 25, 2017
1 parent 2d73361 commit 539e9e3
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 83 deletions.
135 changes: 68 additions & 67 deletions doc/cargo_command_execution.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,114 @@
# Cargo Command Execution Page

The extension allows a developer to execute any of built-in cargo commands.
The extension allows a developer to execute any of the inbuilt Cargo commands.

These commands are:

* bench
* build
* check
* clean
* clippy
* doc
* new
* run
* test
* update
* `bench`
* `build`
* `check`
* `clean`
* `clippy`
* `doc`
* `new`
* `run`
* `test`
* `update`

These commands available through the command palette (CTRL+P).

These commands have prefix `"Cargo: "`.
These commands are available through the command palette (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>) and have the prefix `"Cargo: "`.

## Execute Command On Save

The extension supports executing a command after saving the document opened in the active text document.
The extension supports executing some of these commands after saving the active document.

The `"rust.actionOnSave"` configuration parameter specifies which command to execute.

The possible values are:

* `"build"` - executes `"Cargo: Build"`
* `"check"` - executes `"Cargo: Check"`
* `"clippy"` - executes `"Cargo: Clippy"`
* `"run"` - executes `"Cargo: Run"`
* `"test"` - executes `"Cargo: Test"`
* `null` - the extension does nothing (default)

## Finding Out Cargo.toml

The `"rust.actionOnSave"` configuration parameter specifies a command to execute.
Before executing the command, the extension needs to find out which `Cargo.toml` to use. The extension uses the following algorithm:

The possible values:
* Try to determine the current working directory from the active text editor

* `"build"` - the extension executes `"Cargo: Build"`
* `"check"` - the extension executes `"Cargo: Check"`
* `"clippy"` - the extension executes `"Cargo: Clippy"`
* `"run"` - the extension executes `"Cargo: Run"`
* `"test"` - the extension executes `"Cargo: Test"`
* `null` - the extension does nothing
If all of the following conditions are met:

By default, it is `null`.
* There is an active text editor
* A file opened in the editor is within the workspace (the directory opened in VS Code)
* There is a `Cargo.toml` in the same directory as the active file or in any of the parent directories within the workspace

## Current Working Directory Determination
Then use the `Cargo.toml` file that was found.

The extension executes a cargo command in some directory. To find out which directory the extension should use, the extension uses the following algorithm:
* Try using the previous `Cargo.toml` file
* Try using the `Cargo.toml` from the workspace

* Try making out the current working directory from the active text editor
If the extension fails to find a `Cargo.toml`, an error message is shown.

If all of the conditions are met:
## Finding Out The Working Directory

* There is an active text editor
* A file opened in the editor is in the workspace (the opened directory)
* There is a `Cargo.toml` file near the file or in the parent directories within the workspace
Before executing a Cargo command, the extension must find out which directory to execute the command in.

Then use the directory containing the `Cargo.toml` file.
The extension supports the `"rust.cargoCwd"` configuration parameter with the following possible values:

* Try using the previous current working directory
* Try using the workspace
* `"/some/path"` - the extension uses the specified path as the command's working directory
* `null` - the directory containing the chosen `Cargo.toml` is used as Cargo's working directory (default `cargo` behavior)

## Configuration Parameters

### Cargo Path

The `"rust.cargoPath"` configuration parameter specifies a path to the cargo's executable.
The `"rust.cargoPath"` configuration parameter specifies a path to the `cargo` executable with the following possible values:

The possible values:
* `"/some/path"` - the extension would try to use the path
* `null` - the extension would try to use `cargo` from the `PATH` environment variable.

* `"Some path"` - the extension would try to use the path
* `null` - the extension would try to use cargo from the `PATH` variable of the environment.

If cargo isn't available the extension can't execute a cargo command.
If `cargo` isn't available, the extension can't execute any Cargo commands.

### Cargo Environment

The `"rust.cargoEnv"` configuration parameter specifies an environment which would be added to the general environment for executing a cargo command.
The `"rust.cargoEnv"` configuration parameter specifies an environment variable which would be added to the general environment when executing a Cargo command.

The possible values:
The possible values are:

* Some object (`{ "RUST_BACKTRACE": 1 }`)
* `{ "Some": object }`
* `null`

#### Examples

```json
"rust.cargoEnv": { "RUST_BACKTRACE": 1 }
```

### Setting An Action To Handle Starting A New Command If There Is Another Command Running

The `"rust.actionOnStartingCommandIfThereIsRunningCommand"` configuration parameter specifies what the extension should do in case of starting a new command if there is another command running.
The `"rust.actionOnStartingCommandIfThereIsRunningCommand"` configuration parameter specifies what the extension should do in case of starting a new command if there is a previous command running.

The possible values are:

* `"Stop running command"` - the extension will stop another running command and start a new one
* `"Stop running command"` - the extension will stop the previous running command and start a new one
* `"Ignore new command"` - the extension will ignore a request to start a new command
* `"Show dialog to let me decide"` - the extension will show an information box to let the user decide whether or not to stop a running command


### Passing Arguments

The extension supports several configuration parameters:
The extension supports several configuration parameters used to pass arguments on to the appropriate commands:

* `"rust.buildArgs"`
* `"rust.checkArgs"`
* `"rust.clippyArgs"`
* `"rust.runArgs"`
* `"rust.testArgs"`

The type of these configuration parameters is an array of strings.

These configuration parameters specify arguments which are passed to an appropriate command.
These parameters each take an array of strings. For example, you could configure the extension to execute `cargo build --features some_feature`.

It is useful when you want the extension to execute `cargo build --features some_feature`.

These configuration parameters are used when one of the following commands is invoked:
These parameters are used when one of the following commands is invoked:

* `"Cargo: Build"`
* `"Cargo: Check"`
Expand All @@ -126,11 +132,10 @@ The extension supports several configuration parameters:
* `"rust.customRunConfigurations"`
* `"rust.customTestConfigurations"`

The type of these configuration parameters is an array of objects.
The object must have the following fields:
The type of these parameters is an array of objects and each object must have the following fields:

* `"title"` - a string. It is shown as the label of a quick pick item if a cargo command has several custom configurations
* `"args"` - an array of strings. If a custom configuration is chosen, a cargo command is executed with the arguments from the custom configuration
* `"title"` - a string. It is shown as the label of a quick pick item if a Cargo command has more than one custom configuration
* `"args"` - an array of strings. If a custom configuration is chosen, a Cargo command is executed with the arguments that were defined

These configuration parameters are used when one of the following commands is invoked:

Expand All @@ -140,17 +145,13 @@ These configuration parameters are used when one of the following commands is in
* `"Cargo: Run using custom configuration"`
* `"Cargo: Test using custom configuration"`

If any of the following commands is invoked, the extension decides what to do.

If none of the custom configurations for the command is defined the extension shows an error message.

If only one custom configuration for the command is defined the extension executes the command with the arguments from the custom configuration.

If many custom configurations for the command are defined the extension shows a quick pick with titles of the custom configurations to let a developer decide.

If a developer cancels the quick pick the extension does nothing.
When one of these commands is invoked, the extension decides what to do:

If a developer chooses an item the extension executes the command with the arguments from the chosen configuration.
* If there are no custom configurations defined for the command, the extension shows an error message.
* If only one custom configuration for the command is defined, the extension executes the customized command.
* If more than one custom configuration is defined, the extension shows a quick pick view, listing the title of each configuration to let the developer decide.
* If a developer cancels the quick pick, the extension does nothing.
* If a developer chooses an item, the extension executes the customized command.

#### Examples

Expand Down
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@
"default": null,
"description": "Specifies custom variables to set when running cargo. Useful for crates which use env vars in their build.rs (like openssl-sys)."
},
"rust.cargoCwd": {
"type": [
"string",
"null"
],
"default": null,
"description": "Specifies the path of the directory where a cargo command would be executed"
},
"rust.executeCargoCommandInTerminal": {
"type": "boolean",
"default": false,
Expand Down Expand Up @@ -494,4 +502,4 @@
"elegant-spinner": "1.0.1",
"vscode-languageclient": "3.0.4"
}
}
}
59 changes: 44 additions & 15 deletions src/components/cargo/output_channel_task_manager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { join } from 'path';

import { DiagnosticCollection, languages, window } from 'vscode';

import { ConfigurationManager } from '../configuration/configuration_manager';
Expand Down Expand Up @@ -53,25 +55,51 @@ export class OutputChannelTaskManager {
cwd: string,
parseOutput: boolean
): Promise<void> {
function extendArgs(): void {
if (parseOutput) {
// Prepend arguments with arguments making cargo print output in JSON.
switch (command) {
case 'build':
case 'check':
case 'clippy':
case 'test':
case 'run':
args = ['--message-format', 'json'].concat(args);
break;
}
const cargoCwd = this.configurationManager.getCargoCwd();

/**
* Prepends the manifest path to arguments
* if the command should be executed in a directory
* which differs from the directory containing Cargo.toml.
*/
function prependArgsWithManifestPathIfRequired(): void {
if (cargoCwd === undefined || cargoCwd === cwd) {
return;
}

const manifestPath = join(cwd, 'Cargo.toml');

args = ['--manifest-path', manifestPath].concat(args);
}

function prependArgsWithMessageFormatIfRequired(): void {
if (!parseOutput) {
return;
}

// Prepare arguments with a command
args = [command].concat(args);
// Prepend arguments with arguments making cargo print output in JSON.
switch (command) {
case 'build':
case 'check':
case 'clippy':
case 'test':
case 'run':
args = ['--message-format', 'json'].concat(args);
break;
}
}

extendArgs();
prependArgsWithMessageFormatIfRequired();

prependArgsWithManifestPathIfRequired();

// Prepend arguments with a command.
args = [command].concat(args);

// Change cwd if the user specified custom cwd.
if (cargoCwd !== undefined) {
cwd = cargoCwd;
}

this.runningTask = new Task(
this.configurationManager,
Expand All @@ -82,6 +110,7 @@ export class OutputChannelTaskManager {

this.runningTask.setStarted(() => {
this.channel.clear();
this.channel.append(`Working directory: ${cwd}\n`);
this.channel.append(`Started cargo ${args.join(' ')}\n\n`);

this.diagnostics.clear();
Expand Down
12 changes: 12 additions & 0 deletions src/components/cargo/terminal_task_manager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { join } from 'path';

import { ExtensionContext, Terminal, window, workspace } from 'vscode';

import { CommandStartHandleResult, Helper } from './helper';
Expand Down Expand Up @@ -80,6 +82,16 @@ export class TerminalTaskManager {

setEnvironmentVariables();

const cargoCwd = this.configurationManager.getCargoCwd();

if (cargoCwd !== undefined && cargoCwd !== cwd) {
const manifestPath = join(cwd, 'Cargo.toml');

args = ['--manifest-path', manifestPath].concat(args);

cwd = cargoCwd;
}

// Change the current directory to a specified directory
this.runningTerminal.sendText(`cd "${cwd}"`);

Expand Down
6 changes: 6 additions & 0 deletions src/components/configuration/configuration_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ export class ConfigurationManager {
return cargoEnv || {};
}

public getCargoCwd(): string | undefined {
const cargoCwd = ConfigurationManager.getPathConfigParameter('cargoCwd');

return cargoCwd;
}

public getCargoPath(): string {
const rustsymPath = ConfigurationManager.getPathConfigParameter('cargoPath');

Expand Down

0 comments on commit 539e9e3

Please sign in to comment.