chrisant996 / clink

Bash's powerful command line editing in cmd.exe
https://chrisant996.github.io/clink/
GNU General Public License v3.0
3.69k stars 144 forks source link

uninject / deactivate clink #584

Closed bwagner closed 7 months ago

bwagner commented 8 months ago

Is there a way to reverse inject? clink uninject so to speak? I often cooperate with others who abhor my shell settings, so it would be very useful to move in and out of clink.

chrisant996 commented 8 months ago

No. It isn't safe to unhook system APIs after hooking them.

Do you mean you want some environment variable that can be set to tell Clink to stop intercepting the prompt and input? So that you could run set CLINK_DISABLE=1 and then cmd.exe would behave as if Clink weren't injected, and then later run set CLINK_DISABLE=0 and then Clink would start working again?

Two of the reasons I've been reluctant to add something like that are:

  1. Inevitably, there will be reports about Clink not working, and after a bunch of time spent on investigation it will turn out that CLINK_DISABLE had been set and forgotten. I do not want to waste time on that sort of support problem.
  2. It isn't clear why that would be an important or necessary feature.

Why not instead create a profile that looks and behaves like plain cmd.exe? And run set CLINK_PROFILE=c:\plain_profile to "disable" Clink? Etc.

bwagner commented 8 months ago

Thank you. In fact, I was thinking of a clink uninject command. But I understand it's not often asked for. Thank you!

chrisant996 commented 8 months ago

I was thinking of a clink uninject command. But I understand it's not often asked for.

Literally un-injecting Clink isn't safe. It can leave cmd.exe unstable.

It could potentially be feasible to disable Clink, though, via an environment variable. Or to switch profiles to one that looks and acts as if Clink weren't injected, even though it is.

Cube707 commented 7 months ago

just my two cents:

I successfully use CLINK_NOAUTORUN to temporarily disable clink, running this will drop me into a bare cmd session which I can exit at any time to get clink back:

set CLINK_NOAUTORUN=1 && cmd & set CLINK_NOAUTORUN=

:: do stuff

exit

The third command is optional and just ensures CLINK_NOAUTORUN is cleaned up when the sub-process exits. Once you run it clink remembers it so it's much less of a hassle to reuse than one would think..


@chrisant996 I cant find CLINK_DISABLE in the docs? is this a typo?

Welding-Torch commented 7 months ago

I think that a clink uninject is extremely necessary. Only Windows Terminal on my machine supports nerd fonts. What about plain old cmd.exe? That can't show nerd font icons, and so my prompt looks bad. I don't want that if I have to use cmd.exe for something minimal. I want to be able to uninject clink.

image

And if clink can't be uninjected, is there a command I can use to see the default prompt (just for the current session) instantly instead of my custom prompt? That could be a solution. It should be a short command, not like the aforementioned set CLINK_PROFILE=c:\plain_profile.

Thanks.

Welding-Torch commented 7 months ago

Also, CLINK_DISABLE doesn't work for me either. Like @Cube707 mentioned.

chrisant996 commented 7 months ago

Also, CLINK_DISABLE doesn't work for me either. Like @Cube707 mentioned.

@Cube707 @Welding-Torch There is no such thing as CLINK_DISABLE. I think you've misread the comments here.

chrisant996 commented 7 months ago

just my two cents:

I successfully use CLINK_NOAUTORUN to temporarily disable clink, running this will drop me into a bare cmd session which I can exit at any time to get clink back:

The original poster wants a way to literally un-inject Clink from a CMD instance where Clink has already been injected. And that isn't safe to do -- it can make CMD crash or malfunction.

If you don't use autorun, then simply running cmd.exe gets you a CMD without Clink.

If you use autorun, then you're right that setting CLINK_NOAUTORUN and then starting a nested cmd.exe gets you a CMD without Clink.

I don't know whether that would meet the original poster's needs, but the original poster specifically wanted a way to evict Clink. Evicting Clink is not possible (without risking crashes and malfunctions in CMD).

However, it could be possibly to merely disable Clink without actually un-injecting Clink. The original poster said that wasn't good enough for them.

@chrisant996 I cant find CLINK_DISABLE in the docs? is this a typo?

I think you misread the comment. There is no CLINK_DISABLE. I asked the original poster if adding a CLINK_DISABLE would satisfy them, and they said no.

Welding-Torch commented 7 months ago

@chrisant996 Shall I open a new issue for this?

And if clink can't be uninjected, is there a command I can use to see the default prompt (just for the current session) instantly instead of my custom prompt? That could be a solution. It should be a short command, not like the aforementioned set CLINK_PROFILE=c:\plain_profile.

chrisant996 commented 7 months ago

I think that a clink uninject is extremely necessary.

I'm willing to design a way to disable Clink, or to disable parts of Clink.

@Cube707 @Welding-Torch Can you please describe the specific motivations behind wanting a way to "uninject" Clink? And specifically which parts/features of Clink you want to disable?

If you mean you literally want to evict the Clink DLLs after they've been injected, and unload them from the CMD process, then that specific operation isn't possible to do safely without potentially crashing CMD or causing malfunctions in CMD.

Or if it's acceptable for Clink to technically stay in memory as long as it's disabled, then there are plenty of other approaches that could be built.

You mentioned wanting to disable prompt filtering. That's only one piece of Clink. So it sounds like maybe you don't actually want to completely disable Clink. And the original poster mentioned other users being unfamiliar with Clink and wanting to avoid confusing them.

I have to take all of these kinds of things into account as part of designing a built-in mechanism for disabling Clink and/or parts of Clink.

Only Windows Terminal on my machine supports nerd fonts. What about plain old cmd.exe? That can't show nerd font icons, and so my prompt looks bad. I don't want that if I have to use cmd.exe for something minimal. I want to be able to uninject clink.

@Welding-Torch Yes it can. Plain cmd.exe can show nerd font icons, but by default the list of fonts in the Properties dialog only lists certain predefined fonts. But for example the clink-flex-prompt Readme has a section about how to get other fonts (such as Nerd Fonts) to show up in the font list for the old default conhost consoles in Windows.

And if clink can't be uninjected, is there a command I can use to see the default prompt (just for the current session) instantly instead of my custom prompt? That could be a solution. It should be a short command, not like the aforementioned set CLINK_PROFILE=c:\plain_profile.

There currently isn't a built-in mechanism. I'm willing to build one, but there are a lot of questions that need to be answered first. (And if fonts are the only motivation then maybe it isn't needed after all?)

In the meantime:

Approach # 1

What about the suggestion from @Cube707 ? You could make a batch script noclink.cmd which starts a nested cmd without Clink: noclink.cmd

@echo off
setlocal
set CLINK_NOAUTORUN=1
cmd.exe /k

Approach # 2

You could make a Lua script that disables prompt filtering when an environment variable is set: disablepromptfilters.lua

-- This disables Clink's prompt filtering when an environment variable
-- CLINK_DISABLE_PROMPT_FILTERS is set.
--
-- For example, running this at the command prompt, or in a batch script:
--      set CLINK_DISABLE_PROMPT_FILTERS=1
--
-- Clear it again later to reenable prompt filtering.
--      set CLINK_DISABLE_PROMPT_FILTERS=

-- You can change the name of the variable by changing envname below.
local envname = "CLINK_DISABLE_PROMPT_FILTERS"

local nono = clink.promptfilter(-999999999)
function nono:filter(prompt)
    if os.getenv(envname) then
        return prompt, false
    end
end

And there are some other ways as well. Different users and different workflows or motivations may prefer different degrees of disablement or different ways of initiating the disablement.

bwagner commented 7 months ago

just my two cents: I successfully use CLINK_NOAUTORUN to temporarily disable clink, running this will drop me into a bare cmd session which I can exit at any time to get clink back:

The original poster wants a way to literally un-inject Clink from a CMD instance where Clink has already been injected. And that isn't safe to do -- it can make CMD crash or malfunction.

If you don't use autorun, then simply running cmd.exe gets you a CMD without Clink.

If you use autorun, then you're right that setting CLINK_NOAUTORUN and then starting a nested cmd.exe gets you a CMD without Clink.

I don't know whether that would meet the original poster's needs, but the original poster specifically wanted a way to evict Clink. Evicting Clink is not possible (without risking crashes and malfunctions in CMD).

However, it could be possibly to merely disable Clink without actually un-injecting Clink. The original poster said that wasn't good enough for them.

@chrisant996 I cant find CLINK_DISABLE in the docs? is this a typo?

I think you misread the comment. There is no CLINK_DISABLE. I asked the original poster if adding a CLINK_DISABLE would satisfy them, and they said no.

In fact, if there were a way to have clink temporarily mimic its absence, that would be fine for my purpose!

chrisant996 commented 7 months ago

In fact, if there were a way to have clink temporarily mimic its absence, that would be fine for my purpose!

@bwagner Oh ok can you review this comment and the two solutions it mentions?

Also, can you review the bulleted list of questions in that comment, and share your thoughts? E.g. is there any interest in also being able to selectively disable parts of Clink, such as keeping completions and input line coloring but disabling prompt filtering.

chrisant996 commented 7 months ago

@chrisant996 Shall I open a new issue for this?

And if clink can't be uninjected, is there a command I can use to see the default prompt (just for the current session) instantly instead of my custom prompt? That could be a solution. It should be a short command, not like the aforementioned set CLINK_PROFILE=c:\plain_profile.

@Welding-Torch I think this current issue is sufficient for tracking the conversation and collecting answers for the many relevant design questions. Do you feel two issues are needed? What would differentiate the two issues from each other? (I'm open to having two issues, but I don't understand what would be different between them.)

Also @Welding-Torch, the stated motivation (cmd.exe can't use nerd fonts) is inaccurate (see notes in this comment). Are there other motivations for disabling Clink? Do Approach # 1 or Approach # 2 in this comment meet your needs?

chrisant996 commented 7 months ago

The clink-gizmos repo now includes a noclink command.

Try it out. Does it meet the needs? If not, please describe what's not good, why it's not good, and what you'd like to see instead.

Welding-Torch commented 7 months ago

Hi @chrisant996,

Before your 1st reply, I looked at @Cube707 's method for creating a new cmd without clink, and implemented that into an alias for windows. So now when I type clinkoff, this script runs:

@echo off
echo Clink is set to off. Type exit when you're done :) && echo: 
set CLINK_NOAUTORUN=1 && cmd & set CLINK_NOAUTORUN=

Then after reading your reply in which you wrote disablepromptfilters.lua, I added that .lua script to my clink scripts directory, and then created a new alias. So now when I type promptoff, this script runs:

@echo off
set CLINK_DISABLE_PROMPT_FILTERS=1

I'm pretty happy with this setup. I've got exactly what I wanted 👍.


Do you feel two issues are needed?

Not at all, I only asked that because you referred to "original poster" multiple times and that gave the impression you wanted a separate issue.

Plain cmd.exe can show nerd font icons, but by default the list of fonts in the Properties dialog only lists certain predefined fonts. But for example the clink-flex-prompt Readme has a section about how to get other fonts (such as Nerd Fonts) to show up in the font list for the old default conhost consoles in Windows.

I had a look and man, I am not doing all that. Looks like an incredibly long and convoluted method to do something simple.

Try it out. Does it meet the needs? If not, please describe what's not good, why it's not good, and what you'd like to see instead.

This is amazing! Though personally I feel like this is such a useful command it should be included in clink by default. But that's just my two cents.

Thank you!

chrisant996 commented 7 months ago

I had a look and man, I am not doing all that. Looks like an incredibly long and convoluted method to do something simple.

@Welding-Torch it's one quick and simple step, for each font you want to be able to select.

Since you said "not doing all that" and "incredibly long and convoluted" but the step is neither long nor convoluted, it makes me wonder whether there's been some kind of misunderstanding.

Welding-Torch commented 7 months ago

It is not "one quick and simple step". That superuser.com answer is long. Sure, installing the font itself is a few commands in PowerShell, but the actual checks you have to go through for the font are frustrating. For example, I use Hack Nerd Font found here. I followed along with the steps to install it, but it didn't show up when I went to cmd.exe -> Properties. I'm not sure if Hack Nerd Font passes all the checks needed, and if it doesn't, then I'm not sure what the nearest Nerd font including glyphs(icons) is accepted.

chrisant996 commented 7 months ago

It is not "one quick and simple step". That superuser.com answer is long. Sure, installing the font itself is a few commands in PowerShell, but the actual checks you have to go through for the font are frustrating. For example, I use Hack Nerd Font found here. I followed along with the steps to install it, but it didn't show up when I went to cmd.exe -> Properties. I'm not sure if Hack Nerd Font passes all the checks needed, and if it doesn't, then I'm not sure what the nearest Nerd font including glyphs(icons) is accepted.

Yes I see now. Apparently I have always gotten lucky -- all of the fonts I've ever added have worked. But that was just an anomalously lucky experience.

chrisant996 commented 7 months ago

Oh, even stranger -- I didn't even need to do anything to make these fonts show up:

They all seem to automatically show up in the list for me.

Sorry that it's being frustrating. It's outside of Clink's control, unfortunately.

On a slightly related note, i.e. simplifying the prompt to contain less fanciness and be less disorienting for other users who try to use the computer:

clink-flex-prompt has a default key binding Ctrl-Alt-Shift-Z which toggles the prompt info ASCII mode (or back out), where any Nerd Font icons or Unicode line drawing characters or Powerline symbols or etc are stripped. (It can only affect the current prompt and future prompts -- it cannot retroactively rewrite what's already been printed in the past into the terminal screen buffer.)

I use that before I copy/paste text from my console into an email, so that recipients of the email don't see gibberish where icons or etc would have been visible on my screen.

chrisant996 commented 7 months ago

Deactivating Clink isn't something that fits as being built into Clink at this time. There isn't a good way to make a clink disable command or other direct clink commands for this (because of the necessary cross-process communication), and literally evicting Clink out of the cmd.exe process isn't possible to do safely.

Instead, there is a noclink script in the clink-gizmos repo.

And at its core it is simply "start a new nested cmd.exe". And if you have autorun configured, then it's "set CLINK_NOAUTORUN=1 and then start a new nested cmd.exe". Those aren't deactivating Clink in the current cmd.exe -- instead they are starting a new cmd.exe without activating Clink in the first place.

I'm reluctant to build something in Clink that "deactivates Clink" when in fact that's not really what it does at all. I feel that would be misleading, and also promotes confusion.

Welding-Torch commented 7 months ago

Update:

I chose Fira Code Regular Nerd Font Complete Mono Windows Compatible. And finally- it works. image