Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSCode integration results in an inconsistent environment #2299

Closed
1 of 3 tasks
selimb opened this issue Apr 19, 2020 · 52 comments
Closed
1 of 3 tasks

VSCode integration results in an inconsistent environment #2299

selimb opened this issue Apr 19, 2020 · 52 comments

Comments

@selimb
Copy link

selimb commented Apr 19, 2020

First of all, a million thanks for this project. <3

Purpose of the issue

  • Bug report (encountered problems/errors)
  • Feature request (request for new functionality)
  • Question

Version Information

Cmder: 1.3.14.982
ConEmu 191012
OsVer: 10.0.19559.x64

Background

My ConEmu task is:

-new_console:d:D:\ cmd /k ""%ConEmuDir%\..\init.bat" /f /nix_tools 0"

and I launch cmder.exe with this shortcut:

%CMDER_ROOT%\Cmder.exe /C "%DOTFILES_ROOT%\cmder"

where DOTFILES_ROOT is my local dotfiles Git repo.

In the wiki, it's recommended to add the following to vscode's settings.json:

  "terminal.integrated.shellArgs.windows": [
    "/k",
    "%CMDER_ROOT%\\vendor\\bin\\vscode_init.cmd"
  ],

At the time of this writing, vscode_init.cmd merely calls init.bat without any arguments.

Problem 1

If I don't launch Visual Studio Code from cmder (e.g. Windows Explorer context menu, Start Menu, Desktop shortcut, etc.), the options to init.bat are not the same as in my ConEmu task. Additionally, this means my %DOTFILES_ROOT%\cmder user config is not picked up.

Workaround 1

I worked around this by adding a wrapper init.bat and duplicating vscode_init.cmd:

:: %DOTFILES_ROOT%\cmder\init.bat
"%CMDER_ROOT%\vendor\init.bat" /c "%DOTFILES_ROOT%\cmder" /f /nix_tools 0
:: %DOTFILES_ROOT%\cmder\vscode_init.cmd
:: Copied from cmder's vscode_init, but adjusted to call our init.bat
@echo off
IF [%1] == [] (
    REM -- manually opened console (Ctrl + Shift + `) --
    CALL "%~dp0init.bat"
) ELSE (
    REM -- task --
    CALL cmd %*
    exit
)

modifying the ConEmu task to:

-new_console:d:D:\ cmd /k ""%DOTFILES_ROOT%\cmder\init.bat""

and the vscode settings.json to:

    "terminal.integrated.shellArgs.windows": [
        "/k",
        "%DOTFILES_ROOT%\\cmder\\vscode_init.cmd"
    ]

This ensures parity between init.bat options in the ConEmu task and in the vscode shellArgs.

This actually leads to a second (probably less important) problem:

Problem 2

If I launch vscode from Cmder (code ., or similar), then PATH is effectively "re-enhanced", resulting in a PATH like:

PATH=[cmder init.bat][cmder init.bat][global]

where [cmder init.bat] are the modifications made to PATH by init.bat and my user configuration, and [global] is the global (system?) value of PATH.

I believe by removing the /f option to init.bat, cmder's PATH enhancements will not be duplicated, but my user configuration still will (unless I were to use lib_path as well?).

In most cases, I agree that duplicated values in PATH is merely unsightly. However, it can be a problem if modifications to PATH (let's call them [session]) are made after launching Cmder but before launching vscode. This results in something like:

PATH=[cmder init.bat][session][cmder init.bat][global]

All of our projects at work require setting up PATH (and other envs) before launching vscode, i.e. the workflow is something like:

  • start Cmder
  • cd [project_dir]
  • scripts\edit.bat (this prepends [session] to PATH and launches vscode)
  • scripts\test.bat (this prepends [session] to PATH and runs the tests)

So why is it problematic? Simply because it means the environment I get in a vscode terminal isn't the same as the environment I run the tests in, and in fact isn't even the same as the environment that VSCode tasks (such as running the tests and debugging) run in. I haven't come across any problems with this yet, but it bothers me.

Workaround 2

My workaround for the above was to tweak my init.bat to use CMDER_CONFIGURED (which isn't used anywhere AFAICT?):

if not defined CMDER_CONFIGURED goto :first

:: Copied from cmder's init.bat
"%CMDER_ROOT%\vendor\clink\clink_x%architecture%.exe" inject --quiet --profile "%CMDER_USER_CONFIG%" --scripts "%CMDER_ROOT%\vendor" || exit /b
:: PATH and friends already set. Aliases are the only thing that don't persist, for some reason
alias /reload >nul || exit /b
exit /b 0

:first
"%CMDER_ROOT%\vendor\init.bat" /c "%DOTFILES_ROOT%\cmder" /f /nix_tools 0
exit /b %ERRORLEVEL%

Conclusion

Re: problem 1: Am I missing something?

Problem 2 can probably be avoided by not using /f and using lib_path enhance_path in my user_profile.cmd? Would it be worth mentioning that somewhere (sincere apologies if it already is).

@stale
Copy link

stale bot commented May 19, 2020

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in a week if no further activity occurs. Thank you for your contribution(s).

@stale stale bot added the 👀 Awaiting Response Waiting to hear back from the issue reporter. label May 19, 2020
@stale
Copy link

stale bot commented May 29, 2020

This issue has been automatically closed due to it not having any activity since it was marked as stale. Thank you for your contribution(s).

@stale stale bot closed this as completed May 29, 2020
@daxgames
Copy link
Member

@selimb sorry I just saw this after the bot closed it. There is a lot here to take in. Great explanation! I think I understand the issue.

/f bypasses the %lib_path% enhance_path protections from duplicating path entries already present. It's a trade off, with /f you lose a little functionality to get speed.

%CMDER_CONFIGURED% was added to allow re-running init.bat skipping all Cmder non-user config and only re-run the user part of the config in %cmder_root%\config or in /c [path]. I cannot remember if it actually is used for it's intended purpose or not, I will need to look.

Without actually testing it I believe your conclusion is correct and you are correct the libs are not documented anywhere other than in the libs themselves.

Re-opening.

@daxgames daxgames reopened this May 29, 2020
@stale stale bot removed the 👀 Awaiting Response Waiting to hear back from the issue reporter. label May 29, 2020
@daxgames
Copy link
Member

@selimb Did my response make any sense?

I am not sure there is much we can do to resolve the issue any better than you have already done. To be honest it took me a little while to wrap my head around what you came up with as a workaround. Pretty slick solution!

The Visual Studio Code integration was a user bolt-on enhancement and is limited to very basic Cmder init.bat since we cannot pass args to init.bat via settings.json without destroying VSCode's Task functionality.

The only thing I could suggest that might be a possibility as another workaround is to set these globally on Windows:

CMDER_USER_BIN=%DOTFILES_ROOT%\cmder\bin
CMDER_USER_CONFIG=%DOTFILES_ROOT%\cmder\config

No custom init.bat or vscode_init.bat wrappers or vendor\init.bat edits required. This will affect all Cmder sessions no matter how where they are launched from.

Also don't use /f if the duplicate path enhancement bugs you.

@selimb
Copy link
Author

selimb commented May 31, 2020

@daxgames Thanks for replying!

The only thing I could suggest that might be a possibility as another workaround is to set these globally on Windows:

Oh, that's neat. Are those variables documented somewhere? I'll give that a try. I'm guessing that doesn't allow you to specify other options such as /nix_tools 0?

The Visual Studio Code integration was a user bolt-on enhancement and is limited to very basic Cmder init.bat

Ah! Wasn't aware of that. Would it be worth a quick mention in the docs? Not necessarily a full workaround, but at least knowing that it's deliberately a simplistic solution might have (personally) saved me some time.

@daxgames
Copy link
Member

You could also set nix_tools=0 globally. Let me know if these suggestions help.

@selimb
Copy link
Author

selimb commented May 31, 2020

I'll try to get back to you tomorrow.

@daxgames
Copy link
Member

daxgames commented May 31, 2020

Another option might be to set the env variable in the settings.json:

{
  "terminal.integrated.shell.windows": "cmd.exe",
  "terminal.integrated.env.windows": {
    "CMDER_ROOT": "[cmder_root]",
    "CMDER_USER_BIN": "%DOTFILES_ROOT%\\cmder\\bin",
    "CMDER_USER_CONFIG": "%DOTFILES_ROOT%\\cmder\\config",
    "nix_tools": "0"
  },
  "terminal.integrated.shellArgs.windows": [
    "/k",
    "%CMDER_ROOT%\\vendor\\bin\\vscode_init.cmd"
  ]
}

Note: I have not tried this but it should work.

@selimb
Copy link
Author

selimb commented Jun 1, 2020

@daxgames Using CMDER_USER_BIN and CMDER_USER_CONFIG works, although nix_tools is systematically overriden in init.bat and can only be read from the command-line.

I guess what would fully solve the problem is if the arguments to init.bat could be entirely set from an env. var. Could CMDER_USER_FLAGS be appended to instead of overriden?

%CMDER_CONFIGURED% was added to allow re-running init.bat skipping all Cmder non-user config and only re-run the user part of the config in %cmder_root%\config or in /c [path]. I cannot remember if it actually is used for it's intended purpose or not, I will need to look.

Aaah. Not 100% what I'm after then (unless I use %lib_path% enhance_path in my user config, which I guess I could).

@daxgames
Copy link
Member

daxgames commented Jun 2, 2020

We can fix the nix_tools and other variables override.

@selimb
Copy link
Author

selimb commented Jun 4, 2020

Note that I'm OK with my workaround. If you feel it doesn't add much value to users, feel free to close the issue.

@daxgames
Copy link
Member

daxgames commented Jun 4, 2020

@selimb I think it would be better to make it more useable. I will take care of it and let you know.

@daxgames
Copy link
Member

daxgames commented Jun 7, 2020

@selimb Ceckout https://ci.appveyor.com/project/MartiUK/cmder/builds/33372802/artifacts

Init.bat skips to user config if %CMDER_CONFIGURED% == 1
Init.bat allows setting vars used by command line args globally in windows.

@selimb
Copy link
Author

selimb commented Jun 8, 2020

@daxgames Awesome! Thanks. I'll try it out today.

@selimb
Copy link
Author

selimb commented Jun 9, 2020

@daxgames I grabbed the new build and reverted to the vanilla setup:

  • My ConEmu task is now: -new_console:d:D:\ cmd /k ""%ConEmuDir%\..\init.bat" "
  • My VSCode setting is simply:
  "terminal.integrated.shell.windows": "C:\\Windows\\System32\\cmd.exe",
  "terminal.integrated.shellArgs.windows": [
    "/k",
    "%CMDER_ROOT%\\vendor\\bin\\vscode_init.cmd"
  ],

I set these variables globally: CMDER_USER_BIN, CMDER_USER_CONFIG, NIX_TOOL=0, and I have the following in %CMDER_USER_CONFIG%\user_profile.cmd:

%lib_path% enhance_path "%HOME%\.local\bin"

And everything works as I would've liked/expected, except for the fact that the VSCode terminal is no longer "clink-enabled":

image

whereas it should be:

image

That's why I needed to have:

:: Copied from cmder's init.bat
"%CMDER_ROOT%\vendor\clink\clink_%clink_architecture%.exe" inject --quiet --profile "%CMDER_USER_CONFIG%" --scripts "%CMDER_ROOT%\vendor" || exit /b

in my init.bat tweak (see Workaround 2).

To be honest I have no idea how clink works, so perhaps there's another way of accomplishing the same thing.

@daxgames
Copy link
Member

daxgames commented Jun 9, 2020

Probably need to remove the "CMDER_CONFIGURED" skipping to user config.

@daxgames
Copy link
Member

daxgames commented Jun 9, 2020

@daxgames
Copy link
Member

daxgames commented Jun 9, 2020

Another possibility would be to move the skip below the clink enablement. This does that.

@selimb
Copy link
Author

selimb commented Jun 9, 2020

Both options solve the problem (unsurprisingly). I'm wondering though: why should CMDER_CONFIGURED re-run user config? Personally, I would prefer it do as little as possible. Similarly to Problem 2 in the original post, say I have some environment variable that controls global preferences for a tool, like PYTEST_ADDOPTS=-vv --tb=short, in user_profile.cmd. If I set PYTEST_ADDOPTS to something else and then launch vscode, the vscode prompt will re-run user_profile.cmd and reset PYTEST_ADDOPTS to -vv --tb=short. I guess I could use if not defined everywhere? I also wouldn't need to use %lib_path%, and could use /f if I wanted to. In other words: much less gotchas.

@daxgames
Copy link
Member

daxgames commented Jun 9, 2020

The original intent was so user config changes could be tested simply by re-running %cmder_root%\vendor\init.bat but I see your point. The original intent could be accomplished another way. I'll fix it.

@daxgames
Copy link
Member

daxgames commented Jun 9, 2020

@selimb
Copy link
Author

selimb commented Jun 15, 2020

@daxgames Apologies for the delay. Just gave the new build a shot today. Using the same setup as in #2299 (comment), it all works great. For reference:

  • Launching VSCode from Windows Explorer picks up my user configuration.
  • Launching VSCode from Cmder does not re-run my user config scripts, but correctly enables clink.

@selimb
Copy link
Author

selimb commented Jun 15, 2020

I just noticed something though: it seems that fast_init is set too soon, which results in a bunch of:

'debug_output' is not recognized as an internal or external command,
operable program or batch file.
'debug_output' is not recognized as an internal or external command,
operable program or batch file.

fast_init used to be set only in var_loop, after "initializing" lib_console. Now it's set prior to initializing lib_console, and because of the early exit /b it never gets a chance to set lib_console=call "%~dp0lib_console.cmd" .

@daxgames
Copy link
Member

@selimb I will need to look.

@daxgames
Copy link
Member

@selimb I did a release before I remembered to look at this so the issue you reported is still in 1.3.15. it is however fixed in this

@selimb
Copy link
Author

selimb commented Jun 29, 2020

@daxgames Bit confused re: the emails I've been getting XD
Which release should I be testing with now? If the fast_init bug is fixed, I think that fixes everything discussed in this issue.

Again, thanks for your time on this.

@daxgames
Copy link
Member

daxgames commented Jul 1, 2020

@selimb the fix as coded fixes you but others. See: #2311 (comment)

So I need to try and figure out how to fix both.

@daxgames
Copy link
Member

daxgames commented Jul 1, 2020

@selimb This build.

With this settings.json:

    "terminal.integrated.shell.windows": "cmd.exe",
    "terminal.integrated.env.windows": {
      "CMDER_CONFIGURED": "2",
      "debug_output": "0",
      "verbose_output": "0",
      "fast_init": "1",
      "nix_tools": "0",
      "cmder_user_bin": "%DOTFILES_ROOT%\\cmder\\bin",
      "cmder_user_config": "%DOTFILES_ROOT%\\cmder\\config"
    },
    "terminal.integrated.shellArgs.windows": [
      "/k",
      "%USERPROFILE%\\cmder\\vendor\\bin\\vscode_init.cmd"
    ],

Note: The %DOTFILES_ROOT% above may need to be spelled out and not an env var.

Should get you what you want without causing #2311 (comment)

@daxgames
Copy link
Member

daxgames commented Jul 2, 2020

@selimb Thinking of making one more change that will change the usage of CMDER_CONFIGURED again.

Currently:

CMDER_CONFIGURED == 0

  • Runs all Cmder and Cmder User Config

CMDER_CONFIGURED == 1

  • Skips Cmder Config and starts at Cmder User Config.

CMDER_CONFIGURED == 2

  • Skips All Cmder Config and leaves aliases broken.

Future:

CMDER_CONFIGURED == 0

  • Runs all Cmder and Cmder User Config

CMDER_CONFIGURED == 1

  • Skips Cmder Config and starts at Cmder User Config.

CMDER_CONFIGURED == 2

  • Skips Cmder Config, Enables User Aliases, skips everything else.

CMDER_CONFIGURED == 3

  • Skips All Cmder Config and leaves aliases broken.

@selimb Question: Is CMDER_CONFIGURED == 3 necessary?

I am asking you because:

  1. You asked for it.
  2. It leaves a broken shell with no aliases.

@selimb
Copy link
Author

selimb commented Jul 3, 2020

CMDER_CONFIGURED == 3 does not seem necessary.

Is CMDER_CONFIGURED == 2 roughly equivalent to this?

"%CMDER_ROOT%\vendor\clink\clink_x%architecture%.exe" inject --quiet --profile "%CMDER_USER_CONFIG%" --scripts "%CMDER_ROOT%\vendor" || exit /b
alias /reload >nul || exit /b

Because that's exactly what I found to be the absolute minimum code necessary to bootstrap a new vscode terminal when vscode was launched from cmder.

@daxgames
Copy link
Member

daxgames commented Jul 3, 2020

@selimb yes you are correct.

@selimb
Copy link
Author

selimb commented Jul 3, 2020

Then the "future" implementation of CMDER_CONFIGURED == 2 should fix this issue. I'm wondering though: who/what sets CMDER_CONFIGURED to 2 (as opposed to 1 or )? If I just have "CMDER_CONFIGURED": 2 in "terminal.integrated.env.windows", doesn't that mean that vscode terminals launched from an instance of vscode that wasn't spawned from cmder, e.g. "Open with Code" in Windows Explorer, will not run the cmder and user config? In other words, this flow:

  • launch cmder -- runs cmder + user config
  • run code . in cmder -- vscode instance inherits cmder environment
  • open terminal in vscode with CMDER_CONFIGURED=2-- only need to set up aliases and clink

will not result in the same environment (and possibly be broken?) as:

  • launch vscode from Windows Explorer -- only inherits "global" environment
  • open terminal in vscode with CMDER_CONFIGURED=2 -- only sets up aliases and clink??

Hope this makes sense.

@selimb
Copy link
Author

selimb commented Jul 3, 2020

Why is this:

CMDER_CONFIGURED == 1
Skips Cmder Config and starts at Cmder User Config.

even necessary?

I believe the bug reported in #2311 (comment) isn't quite a "separate" bug -- I forgot to test aliases, apologies for that. What I mean is:

when spawn the splitted task, USER_CONFIG_START session would be skipped, leading spawned task without user defined aliases/profile.

The aliases indeed (for some reason that I ignore, more on this below) don't persist through either task splits or vscode terminals, but the "profile" (which I assume is environment variables) definitely do persist through both task splits and vscode terminals.

Reloading the aliases does not require rerunning the whole user config. It merely requires an alias /reload. There's a single caveat though: it will only reload whatever ALIASES happens to point to, so alias files in profile.d will probably not be reloaded?

@daxgames
Copy link
Member

daxgames commented Jul 3, 2020

@selimb you do not have to set CMDER_CONFIGURED in the settings.json. It was just an example.

I guess I need to understand your use cases and desired outcomes.

  1. Launch Cmder then code.exe from Cmder.
  2. Launch code.exe from a Windows shortcut.
  3. Launch code.exe from a shell extension.

@daxgames
Copy link
Member

daxgames commented Jul 5, 2020

@selimb ignore my last that build was bad:

Try this build
Follow this wiki

I tested this build in all 3 use cases I listed above with a properly configured vscode_init_args.cmd file and I think it will work for you.

@selimb
Copy link
Author

selimb commented Jul 7, 2020

@daxgames Nice. I'll try this out thoroughly today.

@selimb
Copy link
Author

selimb commented Jul 11, 2020

Sorry for taking so long.

This made me realize that the user config gets called when splitting the window. I ended up going with something similar to what I had initially, although I no longer have to rely on the internals and can simply set CMDER_CONFIGURED=2 instead.

Thanks for your patience on this.

Noticed a few things that need fixing in the vscode integration wiki page:

  • "Substitute both [cmder_root] with your Cmder installation directory."
    • [cmder_root] isn't used on that page anymore?
  • "Edit either the %cmder_root%\"bin\vscode_init_args.cmd ..."
    • There's an extra quote right before bin

@selimb selimb closed this as completed Jul 11, 2020
@daxgames
Copy link
Member

@selimb so the pr is good to go?

@daxgames
Copy link
Member

@selimb wiki fixed.

@daxgames
Copy link
Member

daxgames commented Jul 11, 2020

Thanks for your patience on this.

You too.

This made me realize that the user config gets called when splitting the window.

That's why enhance_path and enhance_path_recursive exist but neither work with /f.

I ended up going with something similar to what I had initially, although I no longer have to rely on the internals and can simply set CMDER_CONFIGURED=2 instead.

So you are not using the new %cmder_root%\vendor\vscode_init.cmd ?

I still think this is a better way to work for the average Cmder VSCode user than what we had before. Definitely more flexible?

It would be great if you could post your final setup so others could benefit in case the out of the box experience does not fit.

@selimb
Copy link
Author

selimb commented Jul 11, 2020

@daxgames Actually I got mixed up with my setup. Turns out the CMDER_CONFIGURED=2 option behaves as if CMDER_CONFIGURED was not set at all -- I left some comments on the PR.

@selimb selimb reopened this Jul 11, 2020
@selimb
Copy link
Author

selimb commented Jul 11, 2020

This made me realize that the user config gets called when splitting the window.

That's why enhance_path and enhance_path_recursive exist but neither work with /f.

That indeed works for PATH, but not for other variables.

I guess I need to understand your use cases and desired outcomes.

Here goes. Let's start with a few definitions:

  • "root terminal": The terminal you get in a new cmder tab, or in a vscode terminal if vscode was spawned outside of a cmder terminal (e.g. from windows explorer or the start menu).
  • "child terminal": The terminal you get when splitting a cmder terminal, or a vscode terminal if vscode was spawned from cmder (code .)
  • "init.bat options": Options like /nix_tools 0 and /f
  • "identical terminals": When the output of set is identical, and when aliases and clink still work.

Given that I:

  • keep my dotfiles (including cmder/conemu configuration) under version control and push/pull them from multiple machines.
  • use the /nix_tools and /c init.bat options.
  • have the following user_profile.cmd (clipped for brevity):
set "PYTEST_ADDOPTS=-v --tb=short"
set "PATH=%HOME%\.local\bin;%PATH%"

My requirements:

  1. Easy to keep configuration under version control and in sync between machines.
  2. I want to define init.bat options exactly once, and have them be used in a cmder terminal or vscode root terminal. In other words, I want root cmder and root vscode terminals to be identical.
  • I don't mind using env. vars for this, but they're harder (not impossible) to keep in sync and in version control. The fewer env. vars, the better.
  1. I want child terminals to be identical to their parent terminals. Here's a sample workflow with expected output:
# spawn cmder terminal
λ set PYTEST_ADDOPTS=-x
λ set PATH=D:\Python37;%PATH%
# spawn child terminal (vscode or split cmder)
# EXPECTED: aliases still work, and clink/cmder prompt is enabled
λ echo %PYTEST_ADDOPTS%
# EXPECTED: -x
λ echo %PATH%
# EXPECTED: D:\Python37;%HOME%\.local\bin;...

@selimb
Copy link
Author

selimb commented Jul 11, 2020

So you are not using the new %cmder_root%\vendor\vscode_init.cmd ?
I still think this is a better way to work for the average Cmder VSCode user than what we had before. Definitely more flexible?

Indeed, it's definitely an improvement! I thought it violated requirement 2., but I guess it wouldn't if I used the env. vars instead of the cmdline options.

What's currently stopping me, however, is requirement 3 for cmder child terminals. The reason is: init.bat always overrides CMDER_CONFIGURED to 1 before exiting, so even if I set CMDER_CONFIGURED=2 in, say, my user_profile, that wouldn't work.

EDIT: I don't think I ever understood why the CMDER_CONFIGURED=1 behaviour is desirable.

@daxgames
Copy link
Member

daxgames commented Jul 11, 2020

I thought it violated requirement 2., but I guess it wouldn't if I used the env. vars instead of the cmdline options.

I don't understand this statement.

What's currently stopping me, however, is requirement 3 for cmder child terminals. The reason is: init.bat always overrides CMDER_CONFIGURED to 1 before exiting, so even if I set CMDER_CONFIGURED=2 in, say, my user_profile, that wouldn't work.

That's easy to fix. Try this, edit init.bat as shown below and let me know if it works.

if not defined CMDER_CONFIGURED set CMDER_CONFIGURED=1

EDIT: I don't think I ever understood why the CMDER_CONFIGURED=1 behaviour is desirable.

CMDER_CONFIGURED=1 causes init.bat to skip the Cmder part of config and start at the user config section. This allows a user to edit their config and rerun init.bat without having to start a new terminal to rapidly apply user config edits without having to rerun all the default Cmder bits that never change.

@selimb
Copy link
Author

selimb commented Jul 11, 2020

I thought it violated requirement 2., but I guess it wouldn't if I used the env. vars instead of the cmdline options.

I don't understand this statement.

With the latest build, there's 2 ways to ensure root cmder and root vscode terminals use the same init.bat options:

  1. Define command-line options in the ConEmu task, e.g. cmd /k ""%ConEmuDir%\..\init.bat" /c ... /f /nix_tools 0", and re-define the options in vscode_init_args.cmd
  2. Globally define CMDER_USER_BIN, CMDER_USER_CONFIG, NIX_TOOLS, FAST_INIT

The former violates "I want to define init.bat options exactly once", and the latter works, but env. vars are harder to keep in sync (unless it's a single one). What I mean by that is: I have a setup.bat batch file that bootstraps the environment. It sets/prompts for stuff (using setx) like CMDER_ROOT, GIT_INSTALL_ROOT, it overrides the clink.lua file, etc. This would be where I set things like CMDER_USER_BIN, NIX_TOOLS and FAST_INIT.

Now, let's say I use FAST_INIT=1 today, and run that script. This will globally set fast_init in my user variables. Tomorrow, I decide I no longer want fast_init, so I remove it from setup.bat. Rerunning setup.bat will obviously not unset the variable from my machines (plural). Sure, I could set FAST_INIT=0 instead, but will I remember this a year from now? Maybe not.

On the other hand, if I only had to set CMDER_USER_FLAGS, then changing that from /f /nix_tools 0 /c ... to /nix_tools 0 /c ... (remove /f) will obviously work. I still have to re-run setup.bat (which I don't necessarily re-run on every sync), but considering I've just modified it I can probably trust myself to do that XD

So, basically, would you be open to reviewing a PR that adds support for this CMDER_USER_FLAGS (or maybe CMDER_INIT_ARGS is a better name)?

What's currently stopping me, however, is requirement 3 for cmder child terminals. The reason is: init.bat always overrides CMDER_CONFIGURED to 1 before exiting, so even if I set CMDER_CONFIGURED=2 in, say, my user_profile, that wouldn't work.

That's easy to fix. Try this, edit init.bat as shown below and let me know if it works.

if not defined CMDER_CONFIGURED set CMDER_CONFIGURED=1

That would work indeed.

EDIT: I don't think I ever understood why the CMDER_CONFIGURED=1 behaviour is desirable.

CMDER_CONFIGURED=1 causes init.bat to skip the Cmder part of config and start at the user config section. This allows a user to edit their config and rerun init.bat without having to start a new terminal to rapidly apply user config edits without having to rerun all the default Cmder bits that never change.

Ah. Personally: I don't spend a significant portion of my time tinkering with my user config, and really wouldn't mind having to create a new tab (instead of a split) in that specific (rare) case, especially if it's (in my opinion) harmful otherwise.

@daxgames
Copy link
Member

PRs are always welcome and will be reviewed.

I don't understand how CMDER_CONFIGURED=1 behavior could be harmful. I have never had an issue with it. Do you have an example?

@selimb
Copy link
Author

selimb commented Jul 14, 2020

I don't understand how CMDER_CONFIGURED=1 behavior could be harmful. I have never had an issue with it. Do you have an example?

In the example workflow I posted, it would result prepend %HOME%\.local\bin to PATH and set PYTEST_ADDOPTS=-v —tb=short instead of -x, unless I was careful to use %lib_path% and if not defined PYTEST_ADDOPTS. This means that the child terminal would not be identical, which I’ve found to be problematic.

@daxgames
Copy link
Member

@selimb

I am trying to understand so I tested your sample workflow by doing the following:

  1. Open Cmder
  2. Set the variables you suggested.
    λ set PYTEST_ADDOPTS=-x
    λ set PATH=D:\Python37;%PATH%
    
  3. Split the terminal vertically using a Conemu macro bound to Ctrl++Shift+v.
  4. Ran code.exe, and opened a terminal.
  5. Verified the variables in all three shells.

See screenshot below:

image

The only difference is selected in the top right duplicated terminal and was not done by Cmder. I assume Conemu did this when duplicating the terminal vertically.

@selimb
Copy link
Author

selimb commented Jul 15, 2020

Interesting. What does your user_profile look like? How could it not override pytest_addopts?

@daxgames
Copy link
Member

I did not do that part. I simply did what was in number 3 of your workflow.

If I define those settings, as below, in the user_profile.cmd then the user_profile.cmd settings win obviously.

set "PYTEST_ADDOPTS=-v --tb=short"
set "PATH=%HOME%\.local\bin;%PATH%"

However if I do this all is good:

if not defined PYTEST_ADDOPTS set "PYTEST_ADDOPTS=-v --tb=short"

set fast_init=0

%lib_path% enhance_path "%HOME%\.local\bin"

set fast_init=1

I just did a new commit and using it I get the below if I set CMDER_CONFIGURED=2 before splitting or launching code.exe:

image

@selimb
Copy link
Author

selimb commented Jul 23, 2020

@daxgames Sorry for taking so long to get back to this. Went on vacation.

Right, if you're careful enough in user_profile.cmd and use if not defined and lib_path, you don't need CMDER_CONFIGURED=2. But IMO it's not ideal, so I still think CMDER_CONFIGURED=2 is a nice addition.

I was asking whether CMDER_CONFIGURED=1 was useful so that CMDER_CONFIGURED=2 could maybe become the default instead. I guess that's not happening, and it's OK.

For reference, here's my updated setup using https://ci.appveyor.com/project/MartiUK/cmder/builds/34261352/artifacts

Global environment variables (that I set in a bootstrapping script):

  • %DOTFILES_ROOT%: Where my dotfiles are stored (usually %USERPROFILE%\dotfiles)
  • %CMDER_ROOT%: As in the docs.

%DOTFILES_ROOT%\cmder\init.bat:

:: wrapper around cmder's init.bat so we can use the same options from VSCode and ConEmu Tasks
@echo off
call "%CMDER_ROOT%\vendor\init.bat" /c "%DOTFILES_ROOT%\cmder" /nix_tools 0 /f || exit /b

%DOTFILES_ROOT%\cmder\vscode_init.cmd:

:: Copied from cmder's vscode_init, but adjusted to call our init.bat
@echo off
IF [%1] == [] (
    REM -- manually opened console (Ctrl + Shift + `) --
    CALL "%~dp0init.bat"
) ELSE (
    REM -- task --
    CALL cmd %*
    exit
)

%DOTFILES_ROOT%\cmder\config\user_profile.cmd:

:: set CMDER_CONFIGURED=2 to skip cmder+user config (except essential bootstrapping like aliases and clink)
:: if we've already been init'd
set CMDER_CONFIGURED=2

set "PYTEST_ADDOPTS=-v --tb=short"
set "PATH=%HOME%\.local\bin;%PATH%"

vscode user settings.json:

{
  "terminal.integrated.shell.windows": "C:\\Windows\\System32\\cmd.exe",
  "terminal.integrated.shellArgs.windows": [
    "/k",
    "%DOTFILES_ROOT%\\cmder\\vscode_init.cmd"
  ]
}

conemu task:

-new_console:d:D:\ cmd /k ""%DOTFILES_ROOT%\cmder\init.bat""

This satisfies all requirements defined in #2299 (comment). It's actually not much different than what I described in the original comment: the only difference is I no longer need this hack in my custom init.bat:

:: Copied from cmder's init.bat
"%CMDER_ROOT%\vendor\clink\clink_x%architecture%.exe" inject --quiet --profile "%CMDER_USER_CONFIG%" --scripts "%CMDER_ROOT%\vendor" || exit /b
:: PATH and friends already set. Aliases are the only thing that don't persist, for some reason
alias /reload >nul || exit /b

@daxgames Finally, I'd be happy to close this issue (once #2339 gets merged). Note that, unfortunately, I'm still not using bin\vscode_init_args.cmd, because it violates requirement 2.

I want to define init.bat options exactly once, and have them be used in a cmder terminal or vscode root terminal.

@daxgames
Copy link
Member

1.3.16 Released

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants