5

If you run Anaconda on windows, you have an activate.bat file which concludes with this line to put your current conda env on the prompt:

set PROMPT=[%CONDA_DEFAULT_ENV%] $P$G

If you run cmder on windows, there is a nice lua script to customize your prompt:

function lambda_prompt_filter()
    clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "λ")
end

clink.prompt.register_filter(lambda_prompt_filter, 40)

These two scripts do not play very nicely with each other. Clink has an API that seems like I could use to incorporate the change from activate.bat, but I cannot figure out how to call it from a batch file.

My overall goal is to merge these two prompts into the nicer Cmder-style. My thought is to create an environment variable, change activate.bat to check for the existence of the variable, and, if so, call the Clink API to change the prompt instead of set PROMPT. At that point I would think I could create a new filter to cleanly merge the value in. I can't figure out how to call the API from the batch file, though.

Other solutions welcome.

EDIT: Partial, non-working solution

require "os" -- added to top of file, rest in filter function
local sub = os.getenv("CONDA_DEFAULT_ENV")
if sub == nil then
    sub = ""
end
print(sub)
clink.prompt.value = string.gsub(clink.prompt.value, "{conda}", sub)

I added a {conda} in the prompt definition at the very beginning; removed the prompt statement from activate.bat, and added this to git_prompt_filter. Prior to using activate, everything is fine - the {conda} gets suppressed by the ''. However, if I use activate and switch into a folder with a git repo to trigger the change, I see:

{conda}C:\...

Does os.getenv not get user set variables? Don't know what else the problem would be. I also tried adding a print, it doesn't print out the contents of CONDA... either.

schodge
  • 891
  • 2
  • 16
  • 29
  • `os.getenv` is caching the value, use `clink.get_env`: https://github.com/mridgers/clink/blob/master/docs/api.md#clinkget_envenv_var_name – Jan Katins Dec 03 '15 at 12:33

3 Answers3

3

This is what I do to reset the prompt and add the conda env name to the prompt:

---
 -- Find out the basename of a file/directory (last element after \ or /
 -- @return {basename}
---
function basename(inputstr)
        sep = "\\/"
        local last = nil
        local t={} ; i=1
        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
                --t[i] = str
                --i = i + 1
                last = str
        end
        return last
end

---
 -- Find out current conda env
 -- @return {false|conda env name}
---
function get_conda_env()
    env_path = clink.get_env('CONDA_DEFAULT_ENV')
    if env_path then
        basen = basename(env_path)
        return basen
    end
    return false
end

---
 -- after conda activate: reset prompt and add conda env name 
---
function conda_prompt_filter()
    -- reset to original, e.g. after conda activate destroyed it...
    if string.match(clink.prompt.value, "{lamb}") == nil then
        -- orig: $E[1;32;40m$P$S{git}{hg}$S$_$E[1;30;40m{lamb}$S$E[0m
        -- color codes: "\x1b[1;37;40m"
        cwd = clink.get_cwd()
        prompt = "\x1b[1;32;40m{cwd} {git}{hg} \n\x1b[1;30;40m{lamb} \x1b[0m"
        new_value = string.gsub(prompt, "{cwd}", cwd)
        clink.prompt.value = new_value
    end
    -- add in conda env name
    local conda_env = get_conda_env()
    if conda_env then
        clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "["..conda_env.."] {lamb}")
    end
end

clink.prompt.register_filter(conda_prompt_filter, 10)
Jan Katins
  • 2,219
  • 1
  • 25
  • 35
3

I want to build on @Jan-Schulz answer since it didn't exactly work for me in April 2017.

  1. Instead of editing cmder/vendor/clink/clink.lua I added custom code into cmder/config/prompt.lua which is not overwritten on upgrade (You can add additional modifications to cmder prompt in this file as well using the clink lua api)

  2. I was having an issue where the {lamb} was not being replaced with the proper λ character so I added another filter to run at the end of all processing.

---
 -- Find out the basename of a file/directory (last element after \ or /
 -- @return {basename}
---
function basename(inputstr)
        sep = "\\/"
        local last = nil
        local t={} ; i=1
        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
                --t[i] = str
                --i = i + 1
                last = str
        end
        return last
end

---
 -- Find out current conda env
 -- @return {false|conda env name}
---
function get_conda_env()
    env_path = clink.get_env('CONDA_DEFAULT_ENV')
    if env_path then
        basen = basename(env_path)
        return basen
    end
    return false
end

---
 -- after conda activate: reset prompt and add conda env name 
---
function conda_prompt_filter()
    -- reset to original, e.g. after conda activate destroyed it...
    if string.match(clink.prompt.value, "{lamb}") == nil then
        -- orig: $E[1;32;40m$P$S{git}{hg}$S$_$E[1;30;40m{lamb}$S$E[0m
        -- color codes: "\x1b[1;37;40m"
        cwd = clink.get_cwd()
        prompt = "\x1b[1;32;40m{cwd} {git}{hg} \n\x1b[1;30;40m{lamb} \x1b[0m"
        new_value = string.gsub(prompt, "{cwd}", cwd)
        clink.prompt.value = new_value
    end
    -- add in conda env name
    local conda_env = get_conda_env()
    if conda_env then
        clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "["..conda_env.."] {lamb}")
    end
end


function fix_lamb()
    if string.match(clink.prompt.value, "{lamb}") ~= nil then
        clink.prompt.value = string.gsub(clink.prompt.value, "{lamb}", "λ")
    end
end

clink.prompt.register_filter(conda_prompt_filter, 1)
clink.prompt.register_filter(fix_lamb, 999)
ethanpil
  • 2,522
  • 2
  • 24
  • 34
0

Why not just delete the line from activate.bat and do all the logic in your cmder profile? CONDA_DEFAULT_ENV will be empty if no environment is active.

asmeurer
  • 86,894
  • 26
  • 169
  • 240
  • I was anticipating deleting that line from activate, but was trying to figure out how I (instead) call the Clink API from the batch file to let it know to update the prompt. Are you suggesting to always cat in the CONDA_DEFAULT_ENV to the prompt? I had thought the lambda_prompt_filter() was only called once to setup the prompt, but looking at again, it probably is being called every time a prompt is displayed. Will investigate. – schodge Aug 05 '14 at 20:21
  • Even if it isn't setup every time, you should hopefully be able to get the environment variable to be dereferenced every time. – asmeurer Aug 06 '14 at 04:18
  • 1
    By the way, hopefully a future version of conda will use the changeps1 option on Windows like it does on OS X and Linux, allowing you to disable that line with a configuration setting. We don't have enough Windows experts to work on it to give it the love it deserves (but pull requests are welcome). – asmeurer Aug 06 '14 at 04:21
  • I've gotten this almost working, but os.getenv() in Lua on windows doesn't seem to get user-specific variables. See above. – schodge Oct 02 '14 at 01:37