Repository: conda/conda

Issue:
conda 4.4 weird prompt addition in zsh
Before conda 4.4 my prompt with zsh would look like this, when I'm in my conda env `stable`:

![screenshot 2017-12-08 13 03 34](https://user-images.githubusercontent.com/69774/33783092-6ecd025c-dc18-11e7-8901-de81ac085f2c.png)

After the update to conda 4.4 (using the blog instructions), I have this:

![screenshot 2017-12-08 13 03 43](https://user-images.githubusercontent.com/69774/33783112-8784582c-dc18-11e7-9388-fa681f85de5a.png)

Note the addition of '\[\]' that was added after the environment ID.

How can I get rid of that?

Using zsh 5.4.2 on macOS 10.12.6


Discussion:

Resolving patch:
diff --git a/conda/activate.py b/conda/activate.py
--- a/conda/activate.py
+++ b/conda/activate.py
@@ -51,7 +51,7 @@ def __init__(self, shell, arguments=None):
             self.shift_args = 0
 
             self.unset_var_tmpl = 'unset %s'
-            self.set_var_tmpl = 'export %s="%s"'
+            self.set_var_tmpl = "export %s='%s'"
             self.run_script_tmpl = '. "%s"'
 
         elif shell == 'csh':
@@ -73,7 +73,7 @@ def __init__(self, shell, arguments=None):
             self.shift_args = 0
 
             self.unset_var_tmpl = 'del $%s'
-            self.set_var_tmpl = '$%s = "%s"'
+            self.set_var_tmpl = "$%s = '%s'"
             self.run_script_tmpl = 'source "%s"'
 
         elif shell == 'cmd.exe':
@@ -257,6 +257,8 @@ def build_activate(self, env_name_or_prefix):
             }
             deactivate_scripts = ()
 
+        self._update_prompt(set_vars, conda_prompt_modifier)
+
         return {
             'unset_vars': (),
             'set_vars': set_vars,
@@ -283,6 +285,7 @@ def build_deactivate(self):
         assert old_conda_shlvl > 0
         if old_conda_shlvl == 1:
             # TODO: warn conda floor
+            conda_prompt_modifier = ''
             unset_vars = (
                 'CONDA_PREFIX',
                 'CONDA_DEFAULT_ENV',
@@ -311,6 +314,8 @@ def build_deactivate(self):
             }
             activate_scripts = self._get_activate_scripts(new_prefix)
 
+        self._update_prompt(set_vars, conda_prompt_modifier)
+
         return {
             'unset_vars': unset_vars,
             'set_vars': set_vars,
@@ -399,6 +404,19 @@ def _replace_prefix_in_path(self, old_prefix, new_prefix, starting_path_dirs=Non
                 path_list.insert(idx, join(new_prefix, 'bin'))
         return self.path_conversion(path_list)
 
+    def _update_prompt(self, set_vars, conda_prompt_modifier):
+        if not context.changeps1:
+            return
+
+        if self.shell == 'posix':
+            ps1 = os.environ.get('PS1', '')
+            current_prompt_modifier = os.environ.get('CONDA_PROMPT_MODIFIER')
+            if current_prompt_modifier:
+                ps1 = re.sub(re.escape(current_prompt_modifier), r'', ps1)
+            set_vars.update({
+                'PS1': conda_prompt_modifier + ps1,
+            })
+
     def _default_env(self, prefix):
         if prefix == context.root_prefix:
             return 'base'


Test patch:
diff --git a/tests/test_activate.py b/tests/test_activate.py
--- a/tests/test_activate.py
+++ b/tests/test_activate.py
@@ -152,6 +152,8 @@ def test_build_activate_shlvl_0(self):
                     activator = Activator('posix')
                     builder = activator.build_activate(td)
                     new_path = activator.pathsep_join(activator._add_prefix_to_path(td))
+                    conda_prompt_modifier = "(%s) " % td
+                    ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
 
                     assert builder['unset_vars'] == ()
 
@@ -161,7 +163,8 @@ def test_build_activate_shlvl_0(self):
                         'CONDA_PREFIX': td,
                         'CONDA_SHLVL': 1,
                         'CONDA_DEFAULT_ENV': td,
-                        'CONDA_PROMPT_MODIFIER': "(%s) " % td,
+                        'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
+                        'PS1': ps1,
                     }
                     assert builder['set_vars'] == set_vars
                     assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
@@ -182,6 +185,8 @@ def test_build_activate_shlvl_1(self):
                     activator = Activator('posix')
                     builder = activator.build_activate(td)
                     new_path = activator.pathsep_join(activator._add_prefix_to_path(td))
+                    conda_prompt_modifier = "(%s) " % td
+                    ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
 
                     assert builder['unset_vars'] == ()
 
@@ -191,7 +196,8 @@ def test_build_activate_shlvl_1(self):
                         'CONDA_PREFIX_1': old_prefix,
                         'CONDA_SHLVL': 2,
                         'CONDA_DEFAULT_ENV': td,
-                        'CONDA_PROMPT_MODIFIER': "(%s) " % td,
+                        'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
+                        'PS1': ps1,
                     }
                     assert builder['set_vars'] == set_vars
                     assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
@@ -218,6 +224,8 @@ def test_build_activate_shlvl_2(self):
                     activator = Activator('posix')
                     builder = activator.build_activate(td)
                     new_path = activator.pathsep_join(activator._add_prefix_to_path(td))
+                    conda_prompt_modifier = "(%s) " % td
+                    ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
 
                     assert builder['unset_vars'] == ()
 
@@ -225,7 +233,8 @@ def test_build_activate_shlvl_2(self):
                         'PATH': new_path,
                         'CONDA_PREFIX': td,
                         'CONDA_DEFAULT_ENV': td,
-                        'CONDA_PROMPT_MODIFIER': "(%s) " % td,
+                        'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
+                        'PS1': ps1,
                     }
                     assert builder['set_vars'] == set_vars
                     assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
@@ -289,13 +298,16 @@ def test_build_deactivate_shlvl_2(self):
                         assert builder['unset_vars'] == ('CONDA_PREFIX_1',)
 
                         new_path = activator.pathsep_join(activator.path_conversion(original_path))
+                        conda_prompt_modifier = "(%s) " % old_prefix
+                        ps1 = conda_prompt_modifier + os.environ.get('PS1', '')
 
                         set_vars = {
                             'PATH': new_path,
                             'CONDA_SHLVL': 1,
                             'CONDA_PREFIX': old_prefix,
                             'CONDA_DEFAULT_ENV': old_prefix,
-                            'CONDA_PROMPT_MODIFIER': "(%s) " % old_prefix,
+                            'CONDA_PROMPT_MODIFIER': conda_prompt_modifier,
+                            'PS1': ps1,
                         }
                         assert builder['set_vars'] == set_vars
                         assert builder['activate_scripts'] == (activator.path_conversion(activate_d_1),)
@@ -327,6 +339,7 @@ def test_build_deactivate_shlvl_1(self):
                     assert builder['set_vars'] == {
                         'PATH': new_path,
                         'CONDA_SHLVL': 0,
+                        'PS1': os.environ.get('PS1', ''),
                     }
                     assert builder['activate_scripts'] == ()
                     assert builder['deactivate_scripts'] == (activator.path_conversion(deactivate_d_1),)
@@ -389,12 +402,13 @@ def test_posix_basic(self):
 
         new_path_parts = activator._add_prefix_to_path(self.prefix)
         assert activate_data == dals("""
-        export CONDA_DEFAULT_ENV="%(native_prefix)s"
-        export CONDA_PREFIX="%(native_prefix)s"
-        export CONDA_PROMPT_MODIFIER="(%(native_prefix)s) "
-        export CONDA_PYTHON_EXE="%(sys_executable)s"
-        export CONDA_SHLVL="1"
-        export PATH="%(new_path)s"
+        export CONDA_DEFAULT_ENV='%(native_prefix)s'
+        export CONDA_PREFIX='%(native_prefix)s'
+        export CONDA_PROMPT_MODIFIER='(%(native_prefix)s) '
+        export CONDA_PYTHON_EXE='%(sys_executable)s'
+        export CONDA_SHLVL='1'
+        export PATH='%(new_path)s'
+        export PS1='%(ps1)s'
         . "%(activate1)s"
         """) % {
             'converted_prefix': activator.path_conversion(self.prefix),
@@ -402,6 +416,7 @@ def test_posix_basic(self):
             'new_path': activator.pathsep_join(new_path_parts),
             'sys_executable': activator.path_conversion(sys.executable),
             'activate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'activate.d', 'activate1.sh')),
+            'ps1': '(%s) ' % self.prefix + os.environ.get('PS1', '')
         }
 
         with env_vars({
@@ -416,8 +431,8 @@ def test_posix_basic(self):
             reactivate_data = c.stdout
 
             assert reactivate_data == dals("""
-            export CONDA_PROMPT_MODIFIER="(%(native_prefix)s) "
-            export CONDA_SHLVL="1"
+            export CONDA_PROMPT_MODIFIER='(%(native_prefix)s) '
+            export CONDA_SHLVL='1'
             . "%(deactivate1)s"
             . "%(activate1)s"
             """) % {
@@ -438,13 +453,14 @@ def test_posix_basic(self):
             unset CONDA_PREFIX
             unset CONDA_PROMPT_MODIFIER
             unset CONDA_PYTHON_EXE
-            export CONDA_SHLVL="0"
-            export PATH="%(new_path)s"
+            export CONDA_SHLVL='0'
+            export PATH='%(new_path)s'
+            export PS1='%(ps1)s'
             . "%(deactivate1)s"
             """) % {
                 'new_path': new_path,
                 'deactivate1': activator.path_conversion(join(self.prefix, 'etc', 'conda', 'deactivate.d', 'deactivate1.sh')),
-
+                'ps1': os.environ.get('PS1', ''),
             }
 
     def test_cmd_exe_basic(self):
@@ -612,12 +628,12 @@ def test_xonsh_basic(self):
 
         new_path_parts = activator._add_prefix_to_path(self.prefix)
         assert activate_data == dals("""
-        $CONDA_DEFAULT_ENV = "%(native_prefix)s"
-        $CONDA_PREFIX = "%(native_prefix)s"
-        $CONDA_PROMPT_MODIFIER = "(%(native_prefix)s) "
-        $CONDA_PYTHON_EXE = "%(sys_executable)s"
-        $CONDA_SHLVL = "1"
-        $PATH = "%(new_path)s"
+        $CONDA_DEFAULT_ENV = '%(native_prefix)s'
+        $CONDA_PREFIX = '%(native_prefix)s'
+        $CONDA_PROMPT_MODIFIER = '(%(native_prefix)s) '
+        $CONDA_PYTHON_EXE = '%(sys_executable)s'
+        $CONDA_SHLVL = '1'
+        $PATH = '%(new_path)s'
         source "%(activate1)s"
         """) % {
             'converted_prefix': activator.path_conversion(self.prefix),
@@ -642,8 +658,8 @@ def test_xonsh_basic(self):
             rm_rf(reactivate_result)
 
             assert reactivate_data == dals("""
-            $CONDA_PROMPT_MODIFIER = "(%(native_prefix)s) "
-            $CONDA_SHLVL = "1"
+            $CONDA_PROMPT_MODIFIER = '(%(native_prefix)s) '
+            $CONDA_SHLVL = '1'
             source "%(deactivate1)s"
             source "%(activate1)s"
             """) % {
@@ -667,8 +683,8 @@ def test_xonsh_basic(self):
             del $CONDA_PREFIX
             del $CONDA_PROMPT_MODIFIER
             del $CONDA_PYTHON_EXE
-            $CONDA_SHLVL = "0"
-            $PATH = "%(new_path)s"
+            $CONDA_SHLVL = '0'
+            $PATH = '%(new_path)s'
             source "%(deactivate1)s"
             """) % {
                 'new_path': new_path,
@@ -931,7 +947,7 @@ def tearDown(self):
     def basic_posix(self, shell):
         shell.assert_env_var('CONDA_SHLVL', '0')
         shell.sendline('conda activate root')
-        shell.assert_env_var('PS1', '\$CONDA_PROMPT_MODIFIER.*')
+        shell.assert_env_var('PS1', '(base).*')
         shell.assert_env_var('CONDA_SHLVL', '1')
         shell.sendline('conda activate "%s"' % self.prefix)
         shell.assert_env_var('CONDA_SHLVL', '2')
@@ -959,10 +975,10 @@ def test_dash_basic_integration(self):
             shell.sendline('env | sort')
             self.basic_posix(shell)
 
-    # @pytest.mark.skipif(not which('zsh'), reason='zsh not installed')
-    # def test_zsh_basic_integration(self):
-    #     with InteractiveShell('zsh') as shell:
-    #         self.basic_posix(shell)
+    @pytest.mark.skipif(not which('zsh'), reason='zsh not installed')
+    def test_zsh_basic_integration(self):
+        with InteractiveShell('zsh') as shell:
+            self.basic_posix(shell)
 
     @pytest.mark.skipif(not which('cmd.exe'), reason='cmd.exe not installed')
     def test_cmd_exe_basic_integration(self):