diff --git a/plugins/mercurial/README.md b/plugins/mercurial/README.md
index 19d4a17b1..44c70b22f 100644
--- a/plugins/mercurial/README.md
+++ b/plugins/mercurial/README.md
@@ -49,13 +49,25 @@ plugins=(... mercurial)
   PROMPT='${ret_status}%{$fg_bold[green]%}%p %{$fg[cyan]%}%c %{$fg_bold[blue]%}$(git_prompt_info)$(hg_prompt_info)%{$fg_bold[blue]%} % %{$reset_color%}'
   ```
 
-You can also redefine additional vars used in the plugin (after Oh My Zsh is sourced):
+You can define the below variables to customize the prompt, after Oh-My-Zsh is source.  The prompt will be generated in this order:
+
+1. PREFIX variable.
+2. IDENTIFY variable, which is used with "hg identify --template":
+    * Branch name, if not "default".
+    * Bookmarks, if any.  The active bookmark will have '*' appended.
+    * Tags, if any.
+3. Either the DIRTY or CLEAN variables.
+4. SUFFIX variable.
+
+Spaces are only needed to separate non-empty parts, but no space will be inserted before DIRTY or CLEAN.
 
 ```zsh
-ZSH_THEME_HG_PROMPT_PREFIX="%{$fg_bold[magenta]%}hg:(%{$fg[red]%}"
-ZSH_THEME_HG_PROMPT_SUFFIX="%{$reset_color%}"
-ZSH_THEME_HG_PROMPT_DIRTY="%{$fg[magenta]%}) %{$fg[yellow]%}✗%{$reset_color%}"
+ZSH_THEME_HG_PROMPT_PREFIX="%{$fg[magenta]%}hg:(%{$fg[red]%}"
+ZSH_THEME_HG_PROMPT_IDENTIFY='{separate(" ",ifeq(branch,"default","",branch),"{activebookmark}*",tags)}'
+    # See "hg help templates"; the default is $ZSH_THEME_HG_PROMPT_IDENTIFY_DEFAULT.
+ZSH_THEME_HG_PROMPT_DIRTY="%{$fg[magenta]%}) %{$fg_bold[yellow]%}✗"
 ZSH_THEME_HG_PROMPT_CLEAN="%{$fg[magenta]%})"
+ZSH_THEME_HG_PROMPT_SUFFIX="%{$reset_color%}"
 ```
 
 ### Display repo branch and directory status in prompt
diff --git a/plugins/mercurial/mercurial.plugin.zsh b/plugins/mercurial/mercurial.plugin.zsh
index 9b85d02f6..58f79edce 100644
--- a/plugins/mercurial/mercurial.plugin.zsh
+++ b/plugins/mercurial/mercurial.plugin.zsh
@@ -73,46 +73,32 @@ function hg_get_bookmark_name() {
   echo "$(<"$dir/.hg/bookmarks.current")"
 }
 
+ZSH_THEME_HG_PROMPT_IDENTIFY_DEFAULT='{separate(" ",ifeq(branch,"default","",branch),strip(bookmarks % "{bookmark}{ifeq(bookmark,activebookmark,"*")} "),tags)}'
+
 function hg_prompt_info {
-  local dir branch dirty
-  if ! dir=$(hg_root); then
+  if ! hg_root >/dev/null; then
     return
   fi
 
-  if [[ ! -f "$dir/.hg/branch" ]]; then
-    branch=default
-  else
-    branch="$(<"$dir/.hg/branch")"
+  local pieces dirty
+  if ! pieces="$(hg identify -T'{if(dirty,"x","-")} '"${ZSH_THEME_HG_PROMPT_IDENTIFY:-$ZSH_THEME_HG_PROMPT_IDENTIFY_DEFAULT}")"; then
+    return
+  fi
+  dirty="${pieces%% *}"
+  pieces="${pieces#* }"
+  dirty="${dirty%-}"
+
+  # Check for untracked files unless that is disabled or the repo is already known to be dirty.
+  if [[ x"${DISABLE_UNTRACKED_FILES_DIRTY-}" != xtrue && -z "$dirty" ]]; then
+    dirty="$(hg status -u --template=x 2>/dev/null | head -c1; [[ 0 = ${pipestatus[1]} ]] || echo error)"
+    case "$dirty" in
+      error) return ;;
+    esac
   fi
 
-  dirty="$(hg_dirty)"
-
-  echo "${ZSH_THEME_HG_PROMPT_PREFIX}${branch:gs/%/%%}${dirty}${ZSH_THEME_HG_PROMPT_SUFFIX}"
-}
-
-function hg_dirty {
-  # Do nothing if clean / dirty settings aren't defined
-  if [[ -z "$ZSH_THEME_HG_PROMPT_DIRTY" && -z "$ZSH_THEME_HG_PROMPT_CLEAN" ]]; then
-    return
-  fi
-
-  # Check if there are modifications
-  local hg_status
-  if [[ "$DISABLE_UNTRACKED_FILES_DIRTY" = true ]]; then
-    if ! hg_status="$(hg status -q 2>/dev/null)"; then
-      return
-    fi
-  else
-    if ! hg_status="$(hg status 2>/dev/null)"; then
-      return
-    fi
-  fi
-
-  # grep exits with 0 when dirty
-  if command grep -Eq '^\s*[ACDIMR!?L].*$' <<< "$hg_status"; then
-    echo $ZSH_THEME_HG_PROMPT_DIRTY
-    return
-  fi
-
-  echo $ZSH_THEME_HG_PROMPT_CLEAN
+  case "$dirty" in
+    ?*) dirty="$ZSH_THEME_HG_PROMPT_DIRTY" ;;
+    '') dirty="$ZSH_THEME_HG_PROMPT_CLEAN" ;;
+  esac
+  echo "${ZSH_THEME_HG_PROMPT_PREFIX}${pieces:gs/%/%%}$dirty${ZSH_THEME_HG_PROMPT_SUFFIX}"
 }