Initial checkin

This commit is contained in:
2024-10-08 17:58:44 +09:00
commit 847d7d3c59
260 changed files with 50744 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# Unix lines endings in bash script files
*.sh text eol=lf
themes/* text eol=lf

View File

@@ -0,0 +1,3 @@
*~
*.bak
.idea/

View File

@@ -0,0 +1,23 @@
Copyright (c) 2016, Martin Gondermann
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,396 @@
# Informative git prompt for bash and fish
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/magicmonty/bash-git-prompt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
This prompt is a port of the "Informative git prompt for zsh" which you can
find [here](https://github.com/olivierverdier/zsh-git-prompt)
A ``bash`` prompt that displays information about the current git repository.
In particular the branch name, difference with remote branch, number of files
staged, changed, etc.
(an original idea from this [blog post][]).
`gitstatus.sh` and `git-prompt-help.sh` added by [AKS](http://github.com/aks).
# ATTENTION! Breaking changes!
**If you use this prompt already, please update your `.git-prompt-colors.sh`,
if you have one. It now contains a function named `define_git_prompt_colors()` or `override_git_prompt_colors()`!**
**Please see the ``Custom.bgptemplate`` in the ``themes`` subdirectory of the installation directory!**
**You can now also use the function `override_git_prompt_colors()`. It should define the variable `GIT_PROMPT_THEME_NAME`
and call the function `reload_git_prompt_colors <ThemeName>` like follows:**
```sh
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Custom" # needed for reload optimization, should be unique
# Place your overrides here
...
}
# load the theme
reload_git_prompt_colors "Custom"
```
The advantage of this approach is, that you only need to specify the parts, that are different to the Default theme.
---
**The variable `GIT_PROMPT_SHOW_LAST_COMMAND_INDICATOR` was replaced with a more general placeholder
named ``_LAST_COMMAND_INDICATOR_``, which is replaced by the state of the last executed command. It is now activated by default.**
## Examples
The prompt may look like the following:
![Example prompt](gitprompt.png)
* ``(master↑3|✚1)``: on branch ``master``, ahead of remote by 3 commits, 1 file changed but not staged
* ``(status|●2)``: on branch ``status``, 2 files staged
* ``(master|✚7…)``: on branch ``master``, 7 files changed, some files untracked
* ``(master|✖2✚3)``: on branch ``master``, 2 conflicts, 3 files changed
* ``(master|⚑2)``: on branch ``master``, 2 stash entries
* ``(experimental↓2↑3|✔)``: on branch ``experimental``; your branch has diverged by 3 commits, remote by 2 commits; the repository is otherwise clean
* ``(:70c2952|✔)``: not on any branch; parent commit has hash ``70c2952``; the repository is otherwise clean
## Prompt Structure
By default, the general appearance of the prompt is::
(<branch> <upstream branch> <branch tracking>|<local status>)
The symbols are as follows:
- Local Status Symbols
- ``✔``: repository clean
- ``●n``: there are ``n`` staged files
- ``✖n``: there are ``n`` files with merge conflicts
- ``✖-n``: there are ``n`` staged files waiting for removal
- ``✚n``: there are ``n`` changed but *unstaged* files
- ``…n``: there are ``n`` untracked files
- ``⚑n``: there are ``n`` stash entries
- Upstream branch
- Shows the remote tracking branch
- Disabled by default
- Enable by setting GIT_PROMPT_SHOW_UPSTREAM=1
- Branch Tracking Symbols
- ``↑n``: ahead of remote by ``n`` commits
- ``↓n``: behind remote by ``n`` commits
- ``↓m↑n``: branches diverged, other by ``m`` commits, yours by ``n`` commits
- ``L``: local branch, not remotely tracked
- Branch Symbol:<br />
When the branch name starts with a colon ``:``, it means it's actually a hash, not a branch (although it should be pretty clear, unless you name your branches like hashes :-)
## Installation
### via [Homebrew][homebrew] on Mac OS X
- Run `brew update`
- Run `brew install bash-git-prompt` for the last stable release or `brew install --HEAD bash-git-prompt` for the
latest version directly from the repository
- Now you can source the file in your `~/.bash_profile` as follows:
```sh
if [ -f "$(brew --prefix)/opt/bash-git-prompt/share/gitprompt.sh" ]; then
__GIT_PROMPT_DIR=$(brew --prefix)/opt/bash-git-prompt/share
GIT_PROMPT_ONLY_IN_REPO=1
source "$(brew --prefix)/opt/bash-git-prompt/share/gitprompt.sh"
fi
```
### via Git clone
- Clone this repository to your home directory.
```sh
git clone https://github.com/magicmonty/bash-git-prompt.git ~/.bash-git-prompt --depth=1
```
Add to the `~/.bashrc`:
```
if [ -f "$HOME/.bash-git-prompt/gitprompt.sh" ]; then
GIT_PROMPT_ONLY_IN_REPO=1
source $HOME/.bash-git-prompt/gitprompt.sh
fi
```
### install for the fish shell
- If you cloned the repo to a directory other then ~/.bash-git-prompt , set __GIT_PROMPT_DIR in ~/.config/fish/config.fish
to that path
- To install as an option in the fish_config GUI
```sh
sudo install -m 666 gitprompt.fish /usr/share/fish/tools/web_config/sample_prompts/
fish_config
```
to install the bash-git-prompt as a choice under the prompt tab of the web config. Selecting this will copy it to
~/.config/fish/functions/fish_prompt.fish
- You can also do
```sh
mkdir -p ~/.config/fish/functions/
cp gitprompt.fish ~/.config/fish/functions/fish_prompt.fish
```
to overwrite the current prompt with the bash-git-prompt directly
### All configs for .bashrc
```sh
# Set config variables first
GIT_PROMPT_ONLY_IN_REPO=1
# GIT_PROMPT_FETCH_REMOTE_STATUS=0 # uncomment to avoid fetching remote status
# GIT_PROMPT_IGNORE_SUBMODULES=1 # uncomment to avoid searching for changed files in submodules
# GIT_PROMPT_WITH_VIRTUAL_ENV=0 # uncomment to avoid setting virtual environment infos for node/python/conda environments
# GIT_PROMPT_SHOW_UPSTREAM=1 # uncomment to show upstream tracking branch
# GIT_PROMPT_SHOW_UNTRACKED_FILES=normal # can be no, normal or all; determines counting of untracked files
# GIT_PROMPT_SHOW_CHANGED_FILES_COUNT=0 # uncomment to avoid printing the number of changed files
# GIT_PROMPT_STATUS_COMMAND=gitstatus_pre-1.7.10.sh # uncomment to support Git older than 1.7.10
# GIT_PROMPT_START=... # uncomment for custom prompt start sequence
# GIT_PROMPT_END=... # uncomment for custom prompt end sequence
# as last entry source the gitprompt script
# GIT_PROMPT_THEME=Custom # use custom theme specified in file GIT_PROMPT_THEME_FILE (default ~/.git-prompt-colors.sh)
# GIT_PROMPT_THEME_FILE=~/.git-prompt-colors.sh
# GIT_PROMPT_THEME=Solarized # use theme optimized for solarized color scheme
source ~/.bash-git-prompt/gitprompt.sh
```
You can set the `GIT_PROMPT_SHOW_UNTRACKED_FILES` variable to `no` or `normal` to speed things up if you have lots of
untracked files in your repository. This can be the case for build systems that put their build artifacts in
the subdirectory structure of the git repository. Setting it to `all` will count all untracked files, including files
listed in .gitignore.
- `cd` to a git repository and test it!
#### Themes
The most settings are now stored in theme files. To select a theme, set the variable `GIT_PROMPT_THEME` to the name
of the theme located in `<INSTALLDIR>/themes` without the extension `.bgptheme` like this:
```sh
GIT_PROMPT_THEME=Solarized
```
If you set `GIT_PROMPT_THEME` to `Custom`, then the `.git-prompt-colors.sh` in the home directory will be used.
This file can now be generated with the command `git_prompt_make_custom_theme [<Name of base theme>]`. If the name of
the base theme is ommitted or the theme file is not found, then the Default theme is used. If you have already a custom
`.git-prompt-colors.sh` in your home directory, a error message will be shown.
You can display a list of available themes with `git_prompt_list_themes` (the current theme is highlighted)
**If you omit the `GIT_PROMPT_THEME` variable, the Default theme is used or, if you have a custom `.git-prompt-colors.sh`
in your home directory, then the Custom theme is used.**
##### Ubuntu Themes
Ubuntu requires a bit more spacing for some characters so it has its own themes.
These can be listed with `git_prompt_list_themes`:
```sh
git_prompt_list_themes | grep Ubuntu
```
##### Theme structure
Please see the ``Custom.bgptemplate`` in the ``themes`` subdirectory of the installation directory!
A theme consists of a function `override_git_prompt_colors()` which defines at least the variable `GIT_PROMPT_THEME_NAME`
with a unique theme identifier and a call to the function `reload_git_prompt_colors <ThemeName>` like follows:
```sh
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Custom" # needed for reload optimization, should be unique
# Place your overrides here
...
}
# load the theme
reload_git_prompt_colors "Custom"
```
The advantage of this approach is, that you only need to specify the parts, that are different to the Default theme.
If you use a custom theme in `.git-prompt-colors.sh`, please set `GIT_PROMPT_THEME_NAME="Custom"`.
#### Further customizations
- You can define `GIT_PROMPT_START` and `GIT_PROMPT_END` to tweak your prompt.
- The default colors are defined within `prompt-colors.sh`, which is sourced by
`gitprompt.sh`. The colors used for various git status are defined in
`themes/Default.bgptheme`. Both of these files may be overridden by copying
them to $HOME with a `.` prefix. They can also be placed in `$HOME/lib`
without the leading `.`. The defaults are the original files in the
`~/.bash-git-prompt` directory.
- You can use `GIT_PROMPT_START_USER`, `GIT_PROMPT_START_ROOT`,
`GIT_PROMPT_END_USER` and `GIT_PROMPT_END_ROOT` in your
`.git-prompt-colors.sh` to tweak your prompt. You can also override the start
and end of the prompt by setting `GIT_PROMPT_START` and `GIT_PROMPT_END`
before you source the `gitprompt.sh`.
- The current git repo information is obtained by the script `gitstatus.sh`.
- You can define `prompt_callback` function to tweak your prompt dynamically.
```sh
function prompt_callback {
if [ `jobs | wc -l` -ne 0 ]; then
echo -n " jobs:\j"
fi
}
```
- There are two helper functions that can be used within `prompt_callback`:
- `gp_set_window_title <String>` - sets the window title to the given string (should work for XTerm type terminals like in OS X or Ubuntu)
- `gp_truncate_pwd` - a function that returns the current PWD truncated to fit the current terminal width. Specify the length to truncate to as a parameter. Otherwise it defaults to 1/3 of the terminal width.
- If you want to show the git prompt only if you are in a git repository you
can set `GIT_PROMPT_ONLY_IN_REPO=1` before sourcing the gitprompt script
- You can show an abbreviated `username/repo` in the prompt by setting `GIT_PROMPT_WITH_USERNAME_AND_REPO=1` and setting the placeholder `_USERNAME_REPO_` in your `GIT_PROMPT_PREFIX`. You can also add a `GIT_PROMPT_USERNAME_REPO_SEPARATOR=" | "` so the `username/repo` is nicely separated if there is a remote and if there is no remote, neither the username/repo part nor the separator will be shown. See the theme `Single_line_username_repo.bgptheme` for an example.
- There is an indicator at the start of the prompt, which shows
the result of the last executed command by if you put the placeholder
`_LAST_COMMAND_INDICATOR_` in any of the prompt templates.
It is now by default activated in the default theme:
```sh
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${Yellow}${PathShort}${ResetColor}"
GIT_PROMPT_START_ROOT="_LAST_COMMAND_INDICATOR_ ${GIT_PROMPT_START_USER}"
```
If you want to display the exit code too, you can use the placeholder
``_LAST_COMMAND_STATE_`` in ``GIT_PROMPT_COMMAND_OK`` or ``GIT_PROMPT_COMMAND_FAIL``
in your ``.git-prompt-colors.sh``:
```sh
GIT_PROMPT_COMMAND_OK="${Green}✔ " # displays as ✔
GIT_PROMPT_COMMAND_FAIL="${Red}✘-_LAST_COMMAND_STATE_ " # displays as ✘-1 for exit code 1
```
- It is now possible to disable the fetching of the remote repository either
globally by setting ``GIT_PROMPT_FETCH_REMOTE_STATUS=0`` in your .bashrc or
on a per repository basis by creating a file named ``.bash-git-rc`` with the
content ``FETCH_REMOTE_STATUS=0`` in the root of your git repository.
- You can also ignore a repository completely by creating a file named ``.bash-git-rc`` with the
content ``GIT_PROMPT_IGNORE=1`` in the root of your git repository.
- If you have a repository with many untracked files, the git prompt can become very slow.
You can disable the display of untracked files on a per repository basis by setting
``GIT_PROMPT_SHOW_UNTRACKED_FILES=no`` in your ``.bash-git-rc`` in the repository or
by disabling it globally in your ``.bashrc``
- If you have a repository with a deep submodule hierarchy, this can also affect performance.
You can disable searching for changes in submodules on a per repository basis by setting
``GIT_PROMPT_IGNORE_SUBMODULES=1`` in your ``.bash-git-rc``
- You can get help on the git prompt with the function ``git_prompt_help``.
Examples are available with ``git_prompt_examples``.
A list of all available named colors is available with `git_prompt_color_samples`
- If you make any changes to any file that is sourced by `gitprompt.sh`, you
should run this command, so that the next prompt update will find all the
files and source them anew.
```sh
git_prompt_reset
```
- You can disable/enable gitprompt by running:
```sh
git_prompt_toggle
```
**Enjoy!**
## Alternative RPM Install
This project ships an RPM spec to simplify installation on RHEL and
clones. If you wish to install from RPM, you may first build the RPM
from scratch by following this procedure:
* Clone this repository and tag the release with a version number
````sh
git tag -a -m "Tag release 1.1" 1.1
````
* Run the following command to create a tarball:
````sh
VER=$(git describe)
# replace dash with underscore to work around
# rpmbuild does not allow dash in version string
VER=${VER//\-/_}
git archive \
--format tar \
--prefix=bash-git-prompt-${VER}/ \
HEAD \
-- *.sh \
*.fish \
README.md \
themes \
> bash-git-prompt-${VER}.tar
mkdir -p /tmp/bash-git-prompt-${VER}
sed "s/Version:.*/Version: ${VER}/" \
bash-git-prompt.spec \
> /tmp/bash-git-prompt-${VER}/bash-git-prompt.spec
OLDDIR=$(pwd)
cd /tmp
tar -uf ${OLDDIR}/bash-git-prompt-${VER}.tar \
bash-git-prompt-${VER}/bash-git-prompt.spec
cd ${OLDDIR}
gzip bash-git-prompt-${VER}.tar
mv bash-git-prompt-${VER}.tar.gz bash-git-prompt-${VER}.tgz
````
* Log into an RHEL or clones host and run:
````sh
rpmbuild -ta bash-git-prompt-xxx.tar.gz
````
Then you may publish or install the rpm from "~/rpmbuild/RPMS/noarch".
## License
This code is under the [BSD 2 Clause (NetBSD) license][license].
## Who Are You?
The current maintainer of the original bash-git-prompt is [Martin Gondermann][magicmonty].
## Contributing
If you want to contribute you can look for issues with the label [up-for-grabs][upforgrabs].
Please leave a comment on the issue, that you want to fix it, so others know, the labels are "taken".
Pull requests are welcome. I will check them and merge them, if I think they help the project.
## Donations
I accept tips through [Flattr][flattr].
[![Flattr](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=magicmonty&url=https%3A%2F%2Fgithub.com%2Fmagicmonty%2Fbash-git-prompt)
[blog post]: http://sebastiancelis.com/2009/nov/16/zsh-prompt-git-users/
[tip]:https://www.gittip.com/magicmonty/
[magicmonty]: http://blog.pagansoft.de/pages/about.html
[license]:https://github.com/magicmonty/bash-git-prompt/tree/master/LICENSE.txt
[flattr]: https://flattr.com/submit/auto?user_id=magicmonty&url=https%3A%2F%2Fgithub.com%2Fmagicmonty%2Fbash-git-prompt
[homebrew]: http://brew.sh/
[upforgrabs]: https://github.com/magicmonty/bash-git-prompt/labels/up-for-grabs

View File

@@ -0,0 +1,31 @@
class BashGitPrompt < Formula
desc "Informative, fancy bash prompt for Git users"
homepage "https://github.com/magicmonty/bash-git-prompt"
url "https://github.com/magicmonty/bash-git-prompt/archive/2.7.1.tar.gz"
sha256 "5e5fc6f5133b65760fede8050d4c3bc8edb8e78bc7ce26c16db442aa94b8a709"
head "https://github.com/magicmonty/bash-git-prompt.git"
bottle :unneeded
def install
share.install "gitprompt.sh", "gitprompt.fish", "git-prompt-help.sh",
"gitstatus.py", "gitstatus.sh", "gitstatus_pre-1.7.10.sh",
"prompt-colors.sh"
(share/"themes").install Dir["themes/*.bgptheme"], "themes/Custom.bgptemplate"
doc.install "README.md"
end
def caveats; <<~EOS
You should add the following to your .bashrc (or .bash_profile if bash is your login shell):
if [ -f "#{HOMEBREW_PREFIX}/opt/bash-git-prompt/share/gitprompt.sh" ]; then
__GIT_PROMPT_DIR="#{HOMEBREW_PREFIX}/opt/bash-git-prompt/share"
source "#{HOMEBREW_PREFIX}/opt/bash-git-prompt/share/gitprompt.sh"
fi
EOS
end
test do
system "true"
end
end

View File

@@ -0,0 +1,70 @@
%global START_TOKEN ### Generated by %{name} rpm package
%global END_TOKEN ### Generated by %{name} rpm package
Name: bash-git-prompt
Version: 2.7.1
Release: 1%{?dist}
Summary: Informative git prompt for bash and fish
Group: Development/Tools
License: FreeBSD
URL: https://github.com/magicmonty/bash-git-prompt
Source0: https://github.com/magicmonty/%{name}/archive/%{name}-%{version}.tar.gz
Requires: git
BuildArch: noarch
%description
A bash prompt that displays information about the current git repository. In particular the branch name, difference with remote branch, number of files staged, changed, etc.
This package will automatically enable the git prompt for bash after
install. It will disable the prompt accordingly after uninstall.
%prep
%setup -q
%build
# No command are required here
# These comments are here to avoid rpm lint issue
%install
install -dm 755 %{buildroot}%{_datadir}/%{name}
install -pm 755 *.sh %{buildroot}%{_datadir}/%{name}
#install -pm 755 *.py %{buildroot}%{_datadir}/%{name}
install -pm 755 *.fish %{buildroot}%{_datadir}/%{name}
install -pm 644 README.md %{buildroot}%{_datadir}/%{name}
install -dm 755 %{buildroot}%{_datadir}/%{name}/themes
install -pm 644 themes/*.bgptheme %{buildroot}%{_datadir}/%{name}/themes
install -pm 644 themes/*.bgptemplate %{buildroot}%{_datadir}/%{name}/themes
%post
# enable bash-git-prompt
cat << EOF >> /etc/bashrc
%{START_TOKEN}
if [ -f %{_datadir}/%{name}/gitprompt.sh ]; then
# Set config variables first
GIT_PROMPT_ONLY_IN_REPO=1
GIT_PROMPT_THEME=Default
source %{_datadir}/%{name}/gitprompt.sh
fi
%{END_TOKEN}
EOF
%postun
# remove bash-git-prompt setup
sed -i -e '/^%{START_TOKEN}/, /^%{END_TOKEN}/{d}' /etc/bashrc
%files
%defattr(-,root,root,-)
%{_datadir}/%{name}
%doc README.md
%license LICENSE.txt
%changelog
* Tue Jun 28 2016 Koustubh Sinkar <ksinkar@gmail.com>
- Updating the spec file to reflect more recent changes
* Fri Aug 08 2014 Justin Zhang <schnell18@gmail.com - 1.0.1-1
- Initial version of package

View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# git-prompt-help -- show useful info to help new users with the information
# being displayed.
git_prompt_help() {
source "${__GIT_PROMPT_DIR}/prompt-colors.sh"
source "${__GIT_PROMPT_DIR}/themes/Default.bgptheme"
cat <<EOF | sed 's/\\\[\\033//g' | sed 's/\\\]//g'
The git prompt format is ${GIT_PROMPT_PREFIX}<BRANCH><TRACKING>${GIT_PROMPT_SEPARATOR}<LOCALSTATUS>${GIT_PROMPT_SUFFIX}
BRANCH is a branch name, such as "master" or "stage", a tag name, or commit
hash prefixed with ':'.
TRACKING indicates how the local branch differs from the
remote branch. It can be empty, or one of:
${GIT_PROMPT_BRANCH}${ResetColor}${GIT_PROMPT_REMOTE}${GIT_PROMPT_SYMBOLS_AHEAD}N${ResetColor} - ahead of remote by N commits
${GIT_PROMPT_BRANCH}${ResetColor}${GIT_PROMPT_REMOTE}${GIT_PROMPT_SYMBOLS_BEHIND}M${ResetColor} - behind remote by M commits
${GIT_PROMPT_BRANCH}${ResetColor}${GIT_PROMPT_REMOTE}${GIT_PROMPT_SYMBOLS_AHEAD}N${GIT_PROMPT_SYMBOLS_BEHIND}M${ResetColor} - branches diverged, other by M commits, yours by N commits
LOCALSTATUS is one of the following:
${GIT_PROMPT_CLEAN}${ResetColor} - repository clean
${GIT_PROMPT_STAGED}N${ResetColor} - N staged files
${GIT_PROMPT_CONFLICTS}N${ResetColor} - N files with merge conflicts
${GIT_PROMPT_CHANGED}N${ResetColor} - N changed but *unstaged* files
${GIT_PROMPT_UNTRACKED}N${ResetColor} - N untracked files
${GIT_PROMPT_STASHED}N${ResetColor} - N stash entries
See "git_prompt_examples" for examples.
EOF
}
help_git_prompt() { git_prompt_help ; }
git_prompt_examples() {
cat <<EOF | sed 's/\\\[\\033//g' | sed 's/\\\]//g'
These are examples of the git prompt:
[${GIT_PROMPT_BRANCH}master${ResetColor}${GIT_PROMPT_REMOTE}↑·3${ResetColor}|${GIT_PROMPT_CHANGED}1${ResetColor}] - on branch "master", ahead of remote by 3 commits, 1
file changed but not staged
[${GIT_PROMPT_BRANCH}status${ResetColor}|${GIT_PROMPT_STAGED}2${ResetColor}] - on branch "status", 2 files staged
[${GIT_PROMPT_BRANCH}master${ResetColor}|${GIT_PROMPT_CHANGED}7${GIT_PROMPT_UNTRACKED}${ResetColor}] - on branch "master", 7 files changed, some files untracked
[${GIT_PROMPT_BRANCH}master${ResetColor}|${GIT_PROMPT_CONFLICTS}2${GIT_PROMPT_CHANGED}3${ResetColor}] - on branch "master", 2 conflicts, 3 files changed
[${GIT_PROMPT_BRANCH}master${ResetColor}|${GIT_PROMPT_STASHED}2${ResetColor}] - on branch "master", 2 stash entries
[${GIT_PROMPT_BRANCH}experimental${ResetColor}${GIT_PROMPT_REMOTE}↓·2↑·3${ResetColor}|${GIT_PROMPT_CLEAN}${ResetColor}]
- on branch "experimental"; your branch has diverged
by 3 commits, remote by 2 commits; the repository is
otherwise clean
[${GIT_PROMPT_BRANCH}:70c2952${ResetColor}|${GIT_PROMPT_CLEAN}${ResetColor}] - not on any branch; parent commit has hash "70c2952"; the
repository is otherwise clean
EOF
}
git_prompt_color_samples() {
showColor() {
local color=$(eval echo "\${${1}}")
echo -e "${color}${1}${ResetColor}" | sed 's/\\\]//g' | sed 's/\\\[//g'
}
local x=0
while (( x < 8 )) ; do
showColor "${ColorNames[x]}"
showColor "Dim${ColorNames[x]}"
showColor "Bold${ColorNames[x]}"
showColor "Bright${ColorNames[x]}"
(( x++ ))
done
}

View File

@@ -0,0 +1,115 @@
# name: bash-git-prompt
# author: Mariusz Smykuła <mariuszs@gmail.com>
function fish_prompt
if not set -q __GIT_PROMPT_DIR
set __GIT_PROMPT_DIR ~/.bash-git-prompt
end
# Colors
# Reset
set ResetColor (set_color normal) # Text Reset
# Regular Colors
set Red (set_color red) # Red
set Yellow (set_color yellow); # Yellow
set Blue (set_color blue) # Blue
set WHITE (set_color white)
# Bold
set BGreen (set_color -o green) # Green
# High Intensty
set IBlack (set_color -o black) # Black
# Bold High Intensty
set Magenta (set_color -o purple) # Purple
# Default values for the appearance of the prompt. Configure at will.
set GIT_PROMPT_PREFIX "["
set GIT_PROMPT_SUFFIX "]"
set GIT_PROMPT_SEPARATOR "|"
set GIT_PROMPT_BRANCH "$Magenta"
set GIT_PROMPT_STAGED "$Red"
set GIT_PROMPT_CONFLICTS "$Red"
set GIT_PROMPT_CHANGED "$Blue"
set GIT_PROMPT_REMOTE " "
set GIT_PROMPT_UNTRACKED "…"
set GIT_PROMPT_STASHED "⚑ "
set GIT_PROMPT_CLEAN "$BGreen"
# Various variables you might want for your PS1 prompt instead
set Time (date +%R)
set PathShort (pwd|sed "s=$HOME=~=")
set PROMPT_START "$Yellow$PathShort$ResetColor"
set PROMPT_END " \n$WHITE$Time$ResetColor \$ "
set -e __CURRENT_GIT_STATUS
set gitstatus "$__GIT_PROMPT_DIR/gitstatus.py"
set _GIT_STATUS (python $gitstatus)
set __CURRENT_GIT_STATUS $_GIT_STATUS
set __CURRENT_GIT_STATUS_PARAM_COUNT (count $__CURRENT_GIT_STATUS)
if not test "0" -eq $__CURRENT_GIT_STATUS_PARAM_COUNT
set GIT_BRANCH $__CURRENT_GIT_STATUS[1]
set GIT_REMOTE "$__CURRENT_GIT_STATUS[2]"
if contains "." "$GIT_REMOTE"
set -e GIT_REMOTE
end
set GIT_STAGED $__CURRENT_GIT_STATUS[3]
set GIT_CONFLICTS $__CURRENT_GIT_STATUS[4]
set GIT_CHANGED $__CURRENT_GIT_STATUS[5]
set GIT_UNTRACKED $__CURRENT_GIT_STATUS[6]
set GIT_STASHED $__CURRENT_GIT_STATUS[7]
set GIT_CLEAN $__CURRENT_GIT_STATUS[8]
end
if test -n "$__CURRENT_GIT_STATUS"
set STATUS " $GIT_PROMPT_PREFIX$GIT_PROMPT_BRANCH$GIT_BRANCH$ResetColor"
if set -q GIT_REMOTE
set STATUS "$STATUS$GIT_PROMPT_REMOTE$GIT_REMOTE$ResetColor"
end
set STATUS "$STATUS$GIT_PROMPT_SEPARATOR"
if [ $GIT_STAGED != "0" ]
set STATUS "$STATUS$GIT_PROMPT_STAGED$GIT_STAGED$ResetColor"
end
if [ $GIT_CONFLICTS != "0" ]
set STATUS "$STATUS$GIT_PROMPT_CONFLICTS$GIT_CONFLICTS$ResetColor"
end
if [ $GIT_CHANGED != "0" ]
set STATUS "$STATUS$GIT_PROMPT_CHANGED$GIT_CHANGED$ResetColor"
end
if [ "$GIT_UNTRACKED" != "0" ]
set STATUS "$STATUS$GIT_PROMPT_UNTRACKED$GIT_UNTRACKED$ResetColor"
end
if [ "$GIT_STASHED" != "0" ]
set STATUS "$STATUS$GIT_PROMPT_STASHED$GIT_STASHED$ResetColor"
end
if [ "$GIT_CLEAN" = "1" ]
set STATUS "$STATUS$GIT_PROMPT_CLEAN"
end
set STATUS "$STATUS$ResetColor$GIT_PROMPT_SUFFIX"
set PS1 "$PROMPT_START$STATUS$PROMPT_END"
else
set PS1 "$PROMPT_START$PROMPT_END"
end
echo -e $PS1
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,702 @@
#!/usr/bin/env bash
function async_run() {
{
eval "$@" &> /dev/null
}&
}
function git_prompt_dir() {
# assume the gitstatus.sh is in the same directory as this script
# code thanks to http://stackoverflow.com/questions/59895
if [[ -z "${__GIT_PROMPT_DIR:+x}" ]]; then
local SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]]; do
local DIR="$( command cd -P "$( dirname "${SOURCE}" )" && pwd )"
SOURCE="$(readlink "${SOURCE}")"
[[ ${SOURCE} != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
__GIT_PROMPT_DIR="$( command cd -P "$( dirname "${SOURCE}" )" && pwd )"
fi
}
function echoc() {
echo -e "${1}${2}${ResetColor}" | sed 's/\\\]//g' | sed 's/\\\[//g'
}
function get_theme() {
local CUSTOM_THEME_FILE="${HOME}/.git-prompt-colors.sh"
if [[ ! (-z "${GIT_PROMPT_THEME_FILE:+x}" ) ]]; then
CUSTOM_THEME_FILE="${GIT_PROMPT_THEME_FILE}"
fi
local DEFAULT_THEME_FILE="${__GIT_PROMPT_DIR}/themes/Default.bgptheme"
if [[ -z "${GIT_PROMPT_THEME+x}" ]]; then
if [[ -r "${CUSTOM_THEME_FILE}" ]]; then
GIT_PROMPT_THEME="Custom"
__GIT_PROMPT_THEME_FILE="${CUSTOM_THEME_FILE}"
else
GIT_PROMPT_THEME="Default"
__GIT_PROMPT_THEME_FILE="${DEFAULT_THEME_FILE}"
fi
else
if [[ "${GIT_PROMPT_THEME}" = "Custom" ]]; then
GIT_PROMPT_THEME="Custom"
__GIT_PROMPT_THEME_FILE="${CUSTOM_THEME_FILE}"
if [[ ! (-r "${__GIT_PROMPT_THEME_FILE}") ]]; then
GIT_PROMPT_THEME="Default"
__GIT_PROMPT_THEME_FILE="${DEFAULT_THEME_FILE}"
fi
else
local theme=""
# use default theme, if theme was not found
for themefile in "${__GIT_PROMPT_DIR}/themes/"*.bgptheme; do
local basename=${themefile##*/}
if [[ "${basename%.bgptheme}" = "${GIT_PROMPT_THEME}" ]]; then
theme="${GIT_PROMPT_THEME}"
break
fi
done
if [[ "${theme}" = "" ]]; then
GIT_PROMPT_THEME="Default"
fi
__GIT_PROMPT_THEME_FILE="${__GIT_PROMPT_DIR}/themes/${GIT_PROMPT_THEME}.bgptheme"
fi
fi
}
function git_prompt_load_colors() {
if gp_set_file_var __PROMPT_COLORS_FILE prompt-colors.sh ; then
# outsource the color defs
source "${__PROMPT_COLORS_FILE}"
else
echo 1>&2 "Cannot find prompt-colors.sh!"
fi
}
function git_prompt_load_theme() {
get_theme
local DEFAULT_THEME_FILE="${__GIT_PROMPT_DIR}/themes/Default.bgptheme"
source "${DEFAULT_THEME_FILE}"
source "${__GIT_PROMPT_THEME_FILE}"
}
function git_prompt_list_themes() {
git_prompt_load_colors
git_prompt_dir
get_theme
for themefile in "${__GIT_PROMPT_DIR}/themes/"*.bgptheme; do
local basename="${themefile##*/}"
local theme="${basename%.bgptheme}"
if [[ "${GIT_PROMPT_THEME}" = "${theme}" ]]; then
echoc "${Red}" "*${theme}"
else
echo "${theme}"
fi
done
if [[ "${GIT_PROMPT_THEME}" = "Custom" ]]; then
echoc "${Magenta}" "*Custom"
else
echoc "${Blue}" "Custom"
fi
}
function git_prompt_make_custom_theme() {
if [[ -r "${HOME}/.git-prompt-colors.sh" ]]; then
echoc "${Red}" "You have already created a custom theme!"
else
git_prompt_dir
local base="Default"
if [[ -n "${1}" && -r "${__GIT_PROMPT_DIR}/themes/${1}.bgptheme" ]]; then
base="${1}"
echoc "${Green}" "Using theme ${Magenta}\"${base}\"${Green} as base theme!"
else
echoc "${Green}" "Using theme ${Magenta}\"Default\"${Green} as base theme!"
fi
if [[ "${base}" = "Custom" ]]; then
echoc "${Red}" "You cannot use the custom theme as base"
else
echoc "${Green}" "Creating new custom theme in \"${HOME}/.git-prompt-colors.sh\""
echoc "${DimYellow}" "Please add ${Magenta}\"GIT_PROMPT_THEME=Custom\"${DimYellow} to your .bashrc to use this theme"
if [[ "${base}" == "Default" ]]; then
cp "${__GIT_PROMPT_DIR}/themes/Custom.bgptemplate" "${HOME}/.git-prompt-colors.sh"
else
cp "${__GIT_PROMPT_DIR}/themes/${base}.bgptheme" "${HOME}/.git-prompt-colors.sh"
fi
fi
fi
}
# gp_set_file_var ENVAR SOMEFILE
#
# If ENVAR is set, check that it's value exists as a readable file. Otherwise,
# Set ENVAR to the path to SOMEFILE, based on $HOME, $__GIT_PROMPT_DIR, and the
# directory of the current script. The SOMEFILE can be prefixed with '.', or
# not.
#
# Return 0 (success) if ENVAR not already defined, 1 (failure) otherwise.
function gp_set_file_var() {
local envar="${1}"
local file="${2}"
if eval "[[ -n \"\${${envar}+x}\" && -r \"\${${envar}+x}\" ]]" ; then # is envar set to a readable file?
local basefile
eval "basefile=\"\`basename \\\"\${${envar}}\\\"\`\"" # assign basefile
if [[ "${basefile}" = "${file}" || "${basefile}" = ".${file}" ]]; then
return 0
fi
else # envar is not set, or it's set to a different file than requested
eval "${envar}=" # set empty envar
gp_maybe_set_envar_to_path "${envar}" "${HOME}/.${file}" "${HOME}/${file}" "${HOME}/lib/${file}" && return 0
git_prompt_dir
gp_maybe_set_envar_to_path "${envar}" "${__GIT_PROMPT_DIR}/${file}" "${0##*/}/${file}" && return 0
fi
return 1
}
# gp_maybe_set_envar_to_path ENVAR FILEPATH ...
#
# return 0 (true) if any FILEPATH is readable, set ENVAR to it
# return 1 (false) if not
function gp_maybe_set_envar_to_path() {
local envar="${1}"
shift
local file
for file in "${@}" ; do
if [[ -r "${file}" ]]; then
eval "${envar}=\"${file}\""
return 0
fi
done
return 1
}
# git_prompt_reset
#
# unsets selected GIT_PROMPT variables, causing the next prompt callback to
# recalculate them from scratch.
git_prompt_reset() {
local var
for var in GIT_PROMPT_DIR __GIT_PROMPT_COLORS_FILE __PROMPT_COLORS_FILE __GIT_STATUS_CMD GIT_PROMPT_THEME_NAME; do
unset ${var}
done
}
# gp_format_exit_status RETVAL
#
# echos the symbolic signal name represented by RETVAL if the process was
# signalled, otherwise echos the original value of RETVAL
gp_format_exit_status() {
local RETVAL="${1}"
local SIGNAL
# Suppress STDERR in case RETVAL is not an integer (in such cases, RETVAL
# is echoed verbatim)
if [[ "${RETVAL}" -gt 128 ]] 2>/dev/null; then
SIGNAL=$(( RETVAL - 128 ))
kill -l "${SIGNAL}" 2>/dev/null || echo "${RETVAL}"
else
echo "${RETVAL}"
fi
}
gp_format_username_repo() {
git config --get remote.origin.url | sed 's|^.*//||; s/.*@//; s/[^:/]\+[:/]//; s/.git$//'
}
function git_prompt_config() {
#Checking if root to change output
_isroot=false
[[ "${UID}" -eq 0 ]] && _isroot=true
# There are two files related to colors:
#
# prompt-colors.sh -- sets generic color names suitable for bash 'PS1' prompt
# git-prompt-colors.sh -- sets the GIT_PROMPT color scheme, using names from prompt-colors.sh
git_prompt_load_colors
# source the user's ~/.git-prompt-colors.sh file, or the one that should be
# sitting in the same directory as this script
git_prompt_load_theme
if is_function prompt_callback; then
prompt_callback="prompt_callback"
else
prompt_callback="prompt_callback_default"
fi
if [[ "${GIT_PROMPT_LAST_COMMAND_STATE:-0}" = 0 ]]; then
LAST_COMMAND_INDICATOR="${GIT_PROMPT_COMMAND_OK}";
else
LAST_COMMAND_INDICATOR="${GIT_PROMPT_COMMAND_FAIL}";
fi
# replace _LAST_COMMAND_STATE_ token with the actual state
GIT_PROMPT_LAST_COMMAND_STATE=$(gp_format_exit_status "${GIT_PROMPT_LAST_COMMAND_STATE}")
LAST_COMMAND_INDICATOR="${LAST_COMMAND_INDICATOR//_LAST_COMMAND_STATE_/${GIT_PROMPT_LAST_COMMAND_STATE}}"
# Do this only once to define PROMPT_START and PROMPT_END
if [[ -z "${PROMPT_START:+x}" || -z "${PROMPT_END:+x}" ]]; then
if [[ -z "${GIT_PROMPT_START:+x}" ]] ; then
if ${_isroot}; then
PROMPT_START="${GIT_PROMPT_START_ROOT-}"
else
PROMPT_START="${GIT_PROMPT_START_USER-}"
fi
else
PROMPT_START="${GIT_PROMPT_START-}"
fi
if [[ -z "${GIT_PROMPT_END:+x}" ]] ; then
if $_isroot; then
PROMPT_END="${GIT_PROMPT_END_ROOT-}"
else
PROMPT_END="${GIT_PROMPT_END_USER-}"
fi
else
PROMPT_END="${GIT_PROMPT_END-}"
fi
fi
# set GIT_PROMPT_LEADING_SPACE to 0 if you want to have no leading space in front of the GIT prompt
if [[ "${GIT_PROMPT_LEADING_SPACE:-1}" = "0" ]]; then
PROMPT_LEADING_SPACE=""
else
PROMPT_LEADING_SPACE=" "
fi
if [[ "${GIT_PROMPT_ONLY_IN_REPO:-0}" == 1 ]]; then
EMPTY_PROMPT="${OLD_GITPROMPT}"
elif [[ "${GIT_PROMPT_WITH_VIRTUAL_ENV:-1}" == 1 ]]; then
local ps="$(gp_add_virtualenv_to_prompt)${PROMPT_START}$(${prompt_callback})${PROMPT_END}"
EMPTY_PROMPT="${ps//_LAST_COMMAND_INDICATOR_/${LAST_COMMAND_INDICATOR}}"
else
local ps="${PROMPT_START}$(${prompt_callback})${PROMPT_END}"
EMPTY_PROMPT="${ps//_LAST_COMMAND_INDICATOR_/${LAST_COMMAND_INDICATOR}}"
fi
# fetch remote revisions every other $GIT_PROMPT_FETCH_TIMEOUT (default 5) minutes
if [[ -z "${GIT_PROMPT_FETCH_TIMEOUT:+x}" ]]; then
GIT_PROMPT_FETCH_TIMEOUT="5"
fi
if [[ -z "${__GIT_STATUS_CMD:+x}" ]] ; then # if GIT_STATUS_CMD not defined..
git_prompt_dir
if ! gp_maybe_set_envar_to_path __GIT_STATUS_CMD "${__GIT_PROMPT_DIR}/${GIT_PROMPT_STATUS_COMMAND}" ; then
echo 1>&2 "Cannot find ${GIT_PROMPT_STATUS_COMMAND}!"
fi
# __GIT_STATUS_CMD defined
fi
unset GIT_BRANCH
}
function setLastCommandState() {
GIT_PROMPT_LAST_COMMAND_STATE="${?}"
}
function we_are_on_repo() {
if [[ -e "$(git rev-parse --git-dir 2> /dev/null)" ]]; then
echo 1
else
echo 0
fi
}
function update_old_git_prompt() {
local in_repo=$(we_are_on_repo)
if [[ "${GIT_PROMPT_OLD_DIR_WAS_GIT}" = 0 ]]; then
OLD_GITPROMPT="${PS1}"
fi
GIT_PROMPT_OLD_DIR_WAS_GIT="${in_repo}"
}
function setGitPrompt() {
update_old_git_prompt
local repo=$(git rev-parse --show-toplevel 2> /dev/null)
if [[ ! -e "${repo}" ]] && [[ "${GIT_PROMPT_ONLY_IN_REPO-}" = 1 ]]; then
# we do not permit bash-git-prompt outside git repos, so nothing to do
PS1="${OLD_GITPROMPT}"
return
fi
local EMPTY_PROMPT
local __GIT_STATUS_CMD
git_prompt_config
if [[ ! -e "${repo}" ]] || [[ "${GIT_PROMPT_DISABLE-}" = 1 ]]; then
PS1="${EMPTY_PROMPT}"
return
fi
local FETCH_REMOTE_STATUS=1
if [[ "${GIT_PROMPT_FETCH_REMOTE_STATUS}" = 0 ]]; then
FETCH_REMOTE_STATUS=0
fi
unset GIT_PROMPT_IGNORE
OLD_GIT_PROMPT_SHOW_UNTRACKED_FILES="${GIT_PROMPT_SHOW_UNTRACKED_FILES}"
unset GIT_PROMPT_SHOW_UNTRACKED_FILES
OLD_GIT_PROMPT_IGNORE_SUBMODULES="${GIT_PROMPT_IGNORE_SUBMODULES}"
unset GIT_PROMPT_IGNORE_SUBMODULES
if [[ -e "${repo}/.bash-git-rc" ]]; then
# The config file can only contain variable declarations on the form A_B=0 or G_P=all
local CONFIG_SYNTAX="^(FETCH_REMOTE_STATUS|GIT_PROMPT_SHOW_UNTRACKED_FILES|GIT_PROMPT_IGNORE_SUBMODULES|GIT_PROMPT_IGNORE)=[0-9a-z]+$"
if grep -q -v -E "${CONFIG_SYNTAX}" "${repo}/.bash-git-rc"; then
echo ".bash-git-rc can only contain variable values on the form NAME=value. Ignoring file." >&2
else
source "${repo}/.bash-git-rc"
fi
fi
if [[ -z "${GIT_PROMPT_SHOW_UNTRACKED_FILES+x}" ]]; then
GIT_PROMPT_SHOW_UNTRACKED_FILES="${OLD_GIT_PROMPT_SHOW_UNTRACKED_FILES}"
fi
unset OLD_GIT_PROMPT_SHOW_UNTRACKED_FILES
if [[ -z "${GIT_PROMPT_IGNORE_SUBMODULES+x}" ]]; then
GIT_PROMPT_IGNORE_SUBMODULES="${OLD_GIT_PROMPT_IGNORE_SUBMODULES}"
fi
unset OLD_GIT_PROMPT_IGNORE_SUBMODULES
if [[ "${GIT_PROMPT_IGNORE-}" = 1 ]]; then
PS1="${EMPTY_PROMPT}"
return
fi
if [[ "${FETCH_REMOTE_STATUS}" = 1 ]]; then
checkUpstream
fi
updatePrompt
}
# some versions of find do not have -mmin
_have_find_mmin=1
function olderThanMinutes() {
local matches
local find_exit_code
if [[ -z "${_find_command+x}" ]]; then
if command -v gfind > /dev/null; then
_find_command="gfind"
else
_find_command="find"
fi
fi
if [[ "${_have_find_mmin}" = 1 ]]; then
matches=$("${_find_command}" "${1}" -mmin +"${2}" 2> /dev/null)
find_exit_code="${?}"
if [[ -n "${matches}" ]]; then
return 0
else
if [[ "${find_exit_code}" != 0 ]]; then
_have_find_mmin=0
else
return 1
fi
fi
fi
# try perl, solaris ships with perl
if command -v perl > /dev/null; then
perl -e '((time - (stat("'"${1}"'"))[9]) / 60) > '"${2}"' && exit(0) || exit(1)'
return "${?}"
else
echo >&2
echo "WARNING: neither a find that supports -mmin (such as GNU find) or perl is available, disabling remote status checking. Install GNU find as gfind or perl to enable this feature, or set GIT_PROMPT_FETCH_REMOTE_STATUS=0 to disable this warning." >&2
echo >&2
GIT_PROMPT_FETCH_REMOTE_STATUS=0
return 1
fi
}
function checkUpstream() {
local GIT_PROMPT_FETCH_TIMEOUT
git_prompt_config
local FETCH_HEAD="${repo}/.git/FETCH_HEAD"
# Fech repo if local is stale for more than $GIT_FETCH_TIMEOUT minutes
if [[ ! -e "${FETCH_HEAD}" ]] || olderThanMinutes "${FETCH_HEAD}" "${GIT_PROMPT_FETCH_TIMEOUT}"
then
if [[ -n $(git remote show) ]]; then
(
async_run "GIT_TERMINAL_PROMPT=0 git fetch --quiet"
disown -h
)
fi
fi
}
function replaceSymbols() {
# Disable globbing, so a * could be used as symbol here
set -f
if [[ -z ${GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING+x} ]]; then
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING=L
fi
local VALUE="${1//_AHEAD_/${GIT_PROMPT_SYMBOLS_AHEAD}}"
local VALUE1="${VALUE//_BEHIND_/${GIT_PROMPT_SYMBOLS_BEHIND}}"
local VALUE2="${VALUE1//_NO_REMOTE_TRACKING_/${GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING}}"
echo "${VALUE2//_PREHASH_/${GIT_PROMPT_SYMBOLS_PREHASH}}"
# reenable globbing symbols
set +f
}
function createPrivateIndex {
# Create a copy of the index to avoid conflicts with parallel git commands, e.g. git rebase.
local __GIT_INDEX_FILE
local __GIT_INDEX_PRIVATE
if [[ -z "${GIT_INDEX_FILE+x}" ]]; then
__GIT_INDEX_FILE="$(git rev-parse --git-dir)/index"
else
__GIT_INDEX_FILE="${GIT_INDEX_FILE}"
fi
__GIT_INDEX_PRIVATE="/tmp/git-index-private$$"
command cp "${__GIT_INDEX_FILE}" "${__GIT_INDEX_PRIVATE}" 2>/dev/null
echo "${__GIT_INDEX_PRIVATE}"
}
function updatePrompt() {
local LAST_COMMAND_INDICATOR
local PROMPT_LEADING_SPACE
local PROMPT_START
local PROMPT_END
local EMPTY_PROMPT
local Blue="\[\033[0;34m\]"
git_prompt_config
__GIT_PROMPT_IGNORE_STASH="${GIT_PROMPT_IGNORE_STASH:-0}"
__GIT_PROMPT_SHOW_UPSTREAM="${GIT_PROMPT_SHOW_UPSTREAM:-0}"
__GIT_PROMPT_IGNORE_SUBMODULES="${GIT_PROMPT_IGNORE_SUBMODULES:-0}"
__GIT_PROMPT_WITH_USERNAME_AND_REPO="${GIT_PROMPT_WITH_USERNAME_AND_REPO:-0}"
export __GIT_PROMPT_SHOW_UNTRACKED_FILES="${GIT_PROMPT_SHOW_UNTRACKED_FILES-normal}"
local __GIT_PROMPT_SHOW_CHANGED_FILES_COUNT="${GIT_PROMPT_SHOW_CHANGED_FILES_COUNT:-1}"
local GIT_INDEX_PRIVATE="$(createPrivateIndex)"
#important to define GIT_INDEX_FILE as local: This way it only affects this function (and below) - even with the export afterwards
local GIT_INDEX_FILE
export GIT_INDEX_FILE="${GIT_INDEX_PRIVATE}"
local -a git_status_fields
while IFS=$'\n' read -r line; do git_status_fields+=("${line}"); done < <("${__GIT_STATUS_CMD}" 2>/dev/null)
export GIT_BRANCH=$(replaceSymbols "${git_status_fields[0]}")
local GIT_REMOTE="$(replaceSymbols "${git_status_fields[1]}")"
if [[ "." == "${GIT_REMOTE}" ]]; then
unset GIT_REMOTE
fi
local GIT_REMOTE_USERNAME_REPO="$(replaceSymbols "${git_status_fields[2]}")"
if [[ "." == "${GIT_REMOTE_USERNAME_REPO}" ]]; then
unset GIT_REMOTE_USERNAME_REPO
fi
local GIT_FORMATTED_UPSTREAM
local GIT_UPSTREAM_PRIVATE="${git_status_fields[3]}"
if [[ "${__GIT_PROMPT_SHOW_UPSTREAM:-0}" != "1" || "^" == "${GIT_UPSTREAM_PRIVATE}" ]]; then
unset GIT_FORMATTED_UPSTREAM
else
GIT_FORMATTED_UPSTREAM="${GIT_PROMPT_UPSTREAM//_UPSTREAM_/${GIT_UPSTREAM_PRIVATE}}"
fi
local GIT_STAGED="${git_status_fields[4]}"
local GIT_CONFLICTS="${git_status_fields[5]}"
local GIT_CHANGED="${git_status_fields[6]}"
local GIT_UNTRACKED="${git_status_fields[7]}"
local GIT_STASHED="${git_status_fields[8]}"
local GIT_CLEAN="${git_status_fields[9]}"
local NEW_PROMPT="${EMPTY_PROMPT}"
if [[ "${#git_status_fields[@]}" -gt 0 ]]; then
if [[ -z "${GIT_REMOTE_USERNAME_REPO+x}" ]]; then
local GIT_PROMPT_PREFIX_FINAL="${GIT_PROMPT_PREFIX//_USERNAME_REPO_/${ResetColor}}"
else
if [[ -z "${GIT_PROMPT_USERNAME_REPO_SEPARATOR+x}" ]]; then
local GIT_PROMPT_PREFIX_FINAL="${GIT_PROMPT_PREFIX//_USERNAME_REPO_/${GIT_REMOTE_USERNAME_REPO}${ResetColor}}"
else
local GIT_PROMPT_PREFIX_FINAL="${GIT_PROMPT_PREFIX//_USERNAME_REPO_/${GIT_REMOTE_USERNAME_REPO}${ResetColor}${GIT_PROMPT_USERNAME_REPO_SEPARATOR}}"
fi
fi
case "${GIT_BRANCH-}" in
${GIT_PROMPT_MASTER_BRANCHES})
local STATUS_PREFIX="${PROMPT_LEADING_SPACE}${GIT_PROMPT_PREFIX_FINAL}${GIT_PROMPT_MASTER_BRANCH}${URL_SHORT-}\${GIT_BRANCH}${ResetColor}${GIT_FORMATTED_UPSTREAM-}"
;;
*)
local STATUS_PREFIX="${PROMPT_LEADING_SPACE}${GIT_PROMPT_PREFIX_FINAL}${GIT_PROMPT_BRANCH}${URL_SHORT-}\${GIT_BRANCH}${ResetColor}${GIT_FORMATTED_UPSTREAM-}"
;;
esac
local STATUS=""
# __add_status KIND VALEXPR INSERT
# eg: __add_status 'STAGED' '-ne 0'
__chk_gitvar_status() {
local v
if [[ "${2-}" = "-n" ]] ; then
v="${2} \"\${GIT_${1}-}\""
else
v="\${GIT_${1}-} ${2}"
fi
if eval "[[ ${v} ]]" ; then
if [[ "${3-}" != '-' ]] && [[ "${__GIT_PROMPT_SHOW_CHANGED_FILES_COUNT}" == "1" || "${1-}" == "REMOTE" ]]; then
__add_status "\${GIT_PROMPT_${1}}\${GIT_${1}}\${ResetColor}"
else
__add_status "\${GIT_PROMPT_${1}}\${ResetColor}"
fi
fi
}
__add_gitvar_status() {
__add_status "\${GIT_PROMPT_${1}}\${GIT_${1}}\${ResetColor}"
}
# __add_status SOMETEXT
__add_status() {
eval "STATUS=\"${STATUS}${1}\""
}
__chk_gitvar_status 'REMOTE' '-n'
if [[ "${GIT_CLEAN}" -eq 0 ]] || [[ "${GIT_PROMPT_CLEAN}" != "" ]]; then
__add_status "${GIT_PROMPT_SEPARATOR}"
__chk_gitvar_status 'STAGED' '!= "0" && ${GIT_STAGED-} != "^"'
__chk_gitvar_status 'CONFLICTS' '!= "0"'
__chk_gitvar_status 'CHANGED' '!= "0"'
__chk_gitvar_status 'UNTRACKED' '!= "0"'
__chk_gitvar_status 'STASHED' '!= "0"'
__chk_gitvar_status 'CLEAN' '= "1"' -
fi
__add_status "${ResetColor}${GIT_PROMPT_SUFFIX}"
NEW_PROMPT="$(gp_add_virtualenv_to_prompt)${PROMPT_START}$(${prompt_callback})${STATUS_PREFIX}${STATUS}${PROMPT_END}"
else
NEW_PROMPT="${EMPTY_PROMPT}"
fi
PS1="${NEW_PROMPT//_LAST_COMMAND_INDICATOR_/${LAST_COMMAND_INDICATOR}${ResetColor}}"
command rm "${GIT_INDEX_PRIVATE}" 2>/dev/null
}
# Helper function that returns virtual env information to be set in prompt
# Honors virtualenvs own setting VIRTUAL_ENV_DISABLE_PROMPT
function gp_add_virtualenv_to_prompt {
local ACCUMULATED_VENV_PROMPT=""
local VENV=""
if [[ -n "${VIRTUAL_ENV-}" && -z "${VIRTUAL_ENV_DISABLE_PROMPT+x}" ]]; then
VENV=$(basename "${VIRTUAL_ENV}")
ACCUMULATED_VENV_PROMPT="${ACCUMULATED_VENV_PROMPT}${GIT_PROMPT_VIRTUALENV//_VIRTUALENV_/${VENV}}"
fi
if [[ -n "${NODE_VIRTUAL_ENV-}" && -z "${NODE_VIRTUAL_ENV_DISABLE_PROMPT+x}" ]]; then
VENV=$(basename "${NODE_VIRTUAL_ENV}")
ACCUMULATED_VENV_PROMPT="${ACCUMULATED_VENV_PROMPT}${GIT_PROMPT_VIRTUALENV//_VIRTUALENV_/${VENV}}"
fi
if [[ -n "${CONDA_DEFAULT_ENV-}" ]]; then
VENV=$(basename "${CONDA_DEFAULT_ENV}")
ACCUMULATED_VENV_PROMPT="${ACCUMULATED_VENV_PROMPT}${GIT_PROMPT_VIRTUALENV//_VIRTUALENV_/${VENV}}"
fi
echo "${ACCUMULATED_VENV_PROMPT}"
}
# Use exit status from declare command to determine whether input argument is a
# bash function
function is_function {
declare -Ff "${1}" >/dev/null;
}
# Helper function that truncates $PWD depending on window width
# Optionally specify maximum length as parameter (defaults to 1/3 of terminal)
function gp_truncate_pwd {
local tilde="~"
local newPWD="${PWD/#${HOME}/${tilde}}"
local pwdmaxlen="${1:-$((${COLUMNS:-80}/3))}"
[[ "${#newPWD}" -gt "${pwdmaxlen}" ]] && newPWD="...${newPWD:3-$pwdmaxlen}"
echo -n "${newPWD}"
}
# Sets the window title to the given argument string
function gp_set_window_title {
echo -ne "\[\033]0;"${@}"\007\]"
}
function prompt_callback_default {
return
}
# toggle gitprompt
function git_prompt_toggle() {
if [[ "${GIT_PROMPT_DISABLE:-0}" = 1 ]]; then
GIT_PROMPT_DISABLE=0
else
GIT_PROMPT_DISABLE=1
fi
return
}
function gp_install_prompt {
if [[ -z "${OLD_GITPROMPT+x}" ]]; then
OLD_GITPROMPT=${PS1}
fi
if [[ -z "${GIT_PROMPT_OLD_DIR_WAS_GIT+x}" ]]; then
GIT_PROMPT_OLD_DIR_WAS_GIT=$(we_are_on_repo)
fi
if [[ -z "${PROMPT_COMMAND:+x}" ]]; then
PROMPT_COMMAND=setGitPrompt
else
PROMPT_COMMAND="${PROMPT_COMMAND//$'\n'/;}" # convert all new lines to semi-colons
PROMPT_COMMAND="${PROMPT_COMMAND#\;}" # remove leading semi-colon
PROMPT_COMMAND="${PROMPT_COMMAND%% }" # remove trailing spaces
PROMPT_COMMAND="${PROMPT_COMMAND%\;}" # remove trailing semi-colon
local new_entry="setGitPrompt"
case ";${PROMPT_COMMAND};" in
*";${new_entry};"*)
# echo "PROMPT_COMMAND already contains: $new_entry"
:;;
*)
PROMPT_COMMAND="${PROMPT_COMMAND};${new_entry}"
# echo "PROMPT_COMMAND does not contain: $new_entry"
;;
esac
fi
local setLastCommandStateEntry="setLastCommandState"
case ";${PROMPT_COMMAND};" in
*";${setLastCommandStateEntry};"*)
# echo "PROMPT_COMMAND already contains: $setLastCommandStateEntry"
:;;
*)
PROMPT_COMMAND="${setLastCommandStateEntry};${PROMPT_COMMAND}"
# echo "PROMPT_COMMAND does not contain: $setLastCommandStateEntry"
;;
esac
git_prompt_dir
source "${__GIT_PROMPT_DIR}/git-prompt-help.sh"
}
gp_install_prompt

View File

@@ -0,0 +1,154 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""This module defines a Print function to use with python 2.x or 3.x., so we can use the prompt with older versions of
Python too
It's interface is that of python 3.0's print. See
http://docs.python.org/3.0/library/functions.html?highlight=print#print
Shamelessly ripped from
http://www.daniweb.com/software-development/python/code/217214/a-print-function-for-different-versions-of-python
"""
# change those symbols to whatever you prefer
symbols = {'ahead of': '↑·', 'behind': '↓·', 'prehash': ':'}
import sys
import re
from subprocess import Popen, PIPE
__all__ = ["Print"]
try:
Print = eval("print") # python 3.0 case
python_version = 3
to_str = str
except SyntaxError as e:
python_version = 2
to_str = unicode
D = dict()
try:
exec ("from __future__ import print_function\np=print", D)
Print = D["p"] # 2.6 case
except SyntaxError:
def Print(*args, **kwd): # 2.4, 2.5, define our own Print function
fout = kwd.get("file", sys.stdout)
w = fout.write
if args:
w(str(args[0]))
sep = kwd.get("sep", " ")
for a in args[1:]:
w(sep)
w(str(a))
w(kwd.get("end", "\n"))
finally:
del D
def get_tag_or_hash():
cmd = Popen(['git', 'describe', '--exact-match'], stdout=PIPE, stderr=PIPE)
so, se = cmd.communicate()
tag = '%s' % so.decode('utf-8').strip()
if tag:
return tag
else:
cmd = Popen(['git', 'rev-parse', '--short', 'HEAD'], stdout=PIPE, stderr=PIPE)
so, se = cmd.communicate()
hash_name = '%s' % so.decode('utf-8').strip()
return ''.join([symbols['prehash'], hash_name])
def get_stash():
cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE)
so, se = cmd.communicate()
stash_file = '%s%s' % (so.decode('utf-8').rstrip(), '/logs/refs/stash')
try:
with open(stash_file) as f:
return sum(1 for _ in f)
except IOError:
return 0
# `git status --porcelain --branch` can collect all information
# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
po = Popen(['git', 'status', '--porcelain', '--branch'], env={'LC_ALL': 'C'}, stdout=PIPE, stderr=PIPE)
stdout, stderr = po.communicate()
if po.returncode != 0:
sys.exit(0) # Not a git repository
# collect git status information
untracked, staged, changed, conflicts = [], [], [], []
num_ahead, num_behind = 0, 0
ahead, behind = '', ''
branch = ''
remote = ''
status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()]
for st in status:
if st[0] == '#' and st[1] == '#':
if re.search('Initial commit on', st[2]):
branch = st[2].split(' ')[-1]
elif re.search('No commits yet on', st[2]):
branch = st[2].split(' ')[-1]
elif re.search('no branch', st[2]): # detached status
branch = get_tag_or_hash()
elif len(st[2].strip().split('...')) == 1:
branch = st[2].strip()
else:
# current and remote branch info
branch, rest = st[2].strip().split('...')
if len(rest.split(' ')) == 1:
# remote_branch = rest.split(' ')[0]
pass
else:
# ahead or behind
divergence = ' '.join(rest.split(' ')[1:])
divergence = divergence.lstrip('[').rstrip(']')
for div in divergence.split(', '):
if 'ahead' in div:
num_ahead = int(div[len('ahead '):].strip())
ahead = '%s%s' % (symbols['ahead of'], num_ahead)
elif 'behind' in div:
num_behind = int(div[len('behind '):].strip())
behind = '%s%s' % (symbols['behind'], num_behind)
remote = ''.join([behind, ahead])
elif st[0] == '?' and st[1] == '?':
untracked.append(st)
else:
if st[1] == 'M':
changed.append(st)
if st[0] == 'U':
conflicts.append(st)
elif st[0] != ' ':
staged.append(st)
stashed = get_stash()
if not changed and not staged and not conflicts and not untracked and not stashed:
clean = 1
else:
clean = 0
if remote == "":
remote = '.'
if python_version == 2:
remote = remote.decode('utf-8')
out = '\n'.join([
branch,
remote,
to_str(len(staged)),
to_str(len(conflicts)),
to_str(len(changed)),
to_str(len(untracked)),
to_str(stashed),
to_str(clean),
to_str(python_version),
])
if python_version == 2:
Print(out.encode('utf-8'))
else:
Print(out)

View File

@@ -0,0 +1,199 @@
#!/usr/bin/env bash
# -*- coding: utf-8 -*-
# gitstatus.sh -- produce the current git repo status on STDOUT
# Functionally equivalent to 'gitstatus.py', but written in bash (not python).
#
# Alan K. Stebbens <aks@stebbens.org> [http://github.com/aks]
set -u
if [[ -z "${__GIT_PROMPT_DIR:+x}" ]]; then
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]]; do
DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
__GIT_PROMPT_DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )"
fi
if [[ "${__GIT_PROMPT_IGNORE_SUBMODULES:-0}" == "1" ]]; then
_ignore_submodules="--ignore-submodules"
else
_ignore_submodules=""
fi
if [[ "${__GIT_PROMPT_WITH_USERNAME_AND_REPO:-0}" == "1" ]]; then
# returns "user/repo" from remote.origin.url git variable
#
# supports urls:
# https://user@bitbucket.org/user/repo.git
# https://github.com/user/repo.git
# git@github.com:user/repo.git
#
remote_url=$(git config --get remote.origin.url | sed 's|^.*//||; s/.*@//; s/[^:/]\+[:/]//; s/.git$//')
else
remote_url='.'
fi
gitstatus=$( LC_ALL=C git status ${_ignore_submodules} --untracked-files="${__GIT_PROMPT_SHOW_UNTRACKED_FILES:-normal}" --porcelain --branch )
# if the status is fatal, exit now
[[ ! "${?}" ]] && exit 0
git_dir="$(git rev-parse --git-dir 2>/dev/null)"
[[ -z "${git_dir:+x}" ]] && exit 0
__git_prompt_read ()
{
local f="${1}"
shift
[[ -r "${f}" ]] && read -r "${@}" <"${f}"
}
state=""
step=""
total=""
if [[ -d "${git_dir}/rebase-merge" ]]; then
__git_prompt_read "${git_dir}/rebase-merge/msgnum" step
__git_prompt_read "${git_dir}/rebase-merge/end" total
if [[ -f "${git_dir}/rebase-merge/interactive" ]]; then
state="|REBASE-i"
else
state="|REBASE-m"
fi
else
if [[ -d "${git_dir}/rebase-apply" ]]; then
__git_prompt_read "${git_dir}/rebase-apply/next" step
__git_prompt_read "${git_dir}/rebase-apply/last" total
if [[ -f "${git_dir}/rebase-apply/rebasing" ]]; then
state="|REBASE"
elif [[ -f "${git_dir}/rebase-apply/applying" ]]; then
state="|AM"
else
state="|AM/REBASE"
fi
elif [[ -f "${git_dir}/MERGE_HEAD" ]]; then
state="|MERGING"
elif [[ -f "${git_dir}/CHERRY_PICK_HEAD" ]]; then
state="|CHERRY-PICKING"
elif [[ -f "${git_dir}/REVERT_HEAD" ]]; then
state="|REVERTING"
elif [[ -f "${git_dir}/BISECT_LOG" ]]; then
state="|BISECTING"
fi
fi
if [[ -n "${step}" ]] && [[ -n "${total}" ]]; then
state="${state} ${step}/${total}"
fi
num_staged=0
num_changed=0
num_conflicts=0
num_untracked=0
while IFS='' read -r line || [[ -n "${line}" ]]; do
status="${line:0:2}"
while [[ -n ${status} ]]; do
case "${status}" in
#two fixed character matches, loop finished
\#\#) branch_line="${line/\.\.\./^}"; break ;;
\?\?) ((num_untracked++)); break ;;
U?) ((num_conflicts++)); break;;
?U) ((num_conflicts++)); break;;
DD) ((num_conflicts++)); break;;
AA) ((num_conflicts++)); break;;
#two character matches, first loop
?M) ((num_changed++)) ;;
?D) ((num_changed++)) ;;
?\ ) ;;
#single character matches, second loop
U) ((num_conflicts++)) ;;
\ ) ;;
*) ((num_staged++)) ;;
esac
status="${status:0:(${#status}-1)}"
done
done <<< "${gitstatus}"
num_stashed=0
if [[ "${__GIT_PROMPT_IGNORE_STASH:-0}" != "1" ]]; then
stash_file="${git_dir}/logs/refs/stash"
if [[ -e "${stash_file}" ]]; then
while IFS='' read -r wcline || [[ -n "${wcline}" ]]; do
((num_stashed++))
done < "${stash_file}"
fi
fi
clean=0
if (( num_changed == 0 && num_staged == 0 && num_untracked == 0 && num_stashed == 0 && num_conflicts == 0)) ; then
clean=1
fi
IFS="^" read -ra branch_fields <<< "${branch_line/\#\# }"
branch="${branch_fields[0]}"
remote=""
upstream=""
if [[ "${branch}" == *"Initial commit on"* ]]; then
IFS=" " read -ra fields <<< "${branch}"
branch="${fields[3]}"
remote="_NO_REMOTE_TRACKING_"
remote_url='.'
elif [[ "${branch}" == *"No commits yet on"* ]]; then
IFS=" " read -ra fields <<< "${branch}"
branch="${fields[4]}"
remote="_NO_REMOTE_TRACKING_"
remote_url='.'
elif [[ "${branch}" == *"no branch"* ]]; then
tag=$( git describe --tags --exact-match )
if [[ -n "${tag}" ]]; then
branch="${tag}"
else
branch="_PREHASH_$( git rev-parse --short HEAD )"
fi
else
if [[ "${#branch_fields[@]}" -eq 1 ]]; then
remote="_NO_REMOTE_TRACKING_"
remote_url='.'
else
IFS="[,]" read -ra remote_fields <<< "${branch_fields[1]}"
upstream="${remote_fields[0]}"
for remote_field in "${remote_fields[@]}"; do
if [[ "${remote_field}" == "ahead "* ]]; then
num_ahead="${remote_field:6}"
ahead="_AHEAD_${num_ahead}"
fi
if [[ "${remote_field}" == "behind "* ]] || [[ "${remote_field}" == " behind "* ]]; then
num_behind="${remote_field:7}"
behind="_BEHIND_${num_behind# }"
fi
done
remote="${behind-}${ahead-}"
fi
fi
if [[ -z "${remote:+x}" ]] ; then
remote='.'
fi
if [[ -z "${upstream:+x}" ]] ; then
upstream='^'
fi
UPSTREAM_TRIMMED=`echo $upstream |xargs`
printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" \
"${branch}${state}" \
"${remote}" \
"${remote_url}" \
"${UPSTREAM_TRIMMED}" \
"${num_staged}" \
"${num_conflicts}" \
"${num_changed}" \
"${num_untracked}" \
"${num_stashed}" \
"${clean}"
exit

View File

@@ -0,0 +1,140 @@
#!/usr/bin/env bash
# -*- coding: UTF-8 -*-
# gitstatus.sh -- produce the current git repo status on STDOUT
# Functionally equivalent to 'gitstatus.py', but written in bash (not python).
#
# Alan K. Stebbens <aks@stebbens.org> [http://github.com/aks]
# helper functions
count_lines() { echo "${1}" | egrep -c "^${2}" ; }
all_lines() { echo "${1}" | grep -v "^$" | wc -l ; }
if [[ -z "${__GIT_PROMPT_DIR-}" ]]; then
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]]; do
DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
__GIT_PROMPT_DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )"
fi
if [[ "${__GIT_PROMPT_WITH_USERNAME_AND_REPO}" == "1" ]]; then
# returns "user/repo" from remote.origin.url git variable
#
# supports urls:
# https://user@bitbucket.org/user/repo.git
# https://github.com/user/repo.git
# git@github.com:user/repo.git
#
remote_url=$(git config --get remote.origin.url | sed 's|^.*//||; s/.*@//; s/[^:/]\+[:/]//; s/.git$//')
else
remote_url='.'
fi
gitsym=$( git symbolic-ref HEAD 2>/dev/null )
#If exit status OK, we have a branch
if [[ "${?}" == 0 ]]; then
# the current branch is the tail end of the symbolic reference
branch="${gitsym##refs/heads/}" # get the basename after "refs/heads/"
fi
gitstatus=$( git diff --name-status 2>&1 )
# if the diff is fatal, exit now
if [[ "${?}" != 0 ]]; then exit 0; fi
staged_files=$( git diff --staged --name-status )
num_changed=$(( $( all_lines "${gitstatus}" ) - $( count_lines "${gitstatus}" U ) ))
num_conflicts=$( count_lines "${staged_files}" U )
num_staged=$(( $( all_lines "${staged_files}" ) - num_conflicts ))
num_untracked=$( git ls-files --others --exclude-standard $(git rev-parse --show-cdup) | wc -l )
num_stashed=0
if [[ "${__GIT_PROMPT_IGNORE_STASH}" != "1" ]]; then
stash_file="$( git rev-parse --git-dir )/logs/refs/stash"
if [[ -e "${stash_file}" ]]; then
while IFS='' read -r wcline || [[ -n "${wcline}" ]]; do
((num_stashed++))
done < "${stash_file}"
fi
fi
clean=0
if (( num_changed == 0 && num_staged == 0 && num_untracked == 0 && num_stashed == 0 && num_conflicts == 0 )) ; then
clean=1
fi
remote=""
upstream=""
if [[ -z "${branch-}" ]]; then
tag=$( git describe --tags --exact-match 2>/dev/null )
if [[ -n "${tag}" ]]; then
branch="${tag}"
else
branch="_PREHASH_$( git rev-parse --short HEAD )"
fi
else
remote_name=$( git config "branch.${branch}.remote" )
if [[ -n "$remote_name" ]]; then
merge_name=$( git config "branch.${branch}.merge" )
else
remote_name='origin'
merge_name="refs/heads/${branch}"
fi
if [[ "${remote_name}" == '.' ]]; then
remote_ref="${merge_name}"
else
remote_ref="refs/remotes/${remote_name}/${merge_name##refs/heads/}"
fi
# detect if the local branch have a remote tracking branch
upstream=$( git rev-parse --abbrev-ref "${branch}"@{upstream} 2>&1 )
if [[ "${?}" == 0 ]]; then
# get the revision list, and count the leading "<" and ">"
revgit=$( git rev-list --left-right "${remote_ref}...HEAD" 2>/dev/null )
if [[ "${?}" == 0 ]]; then
num_revs=$( all_lines "${revgit}" )
num_ahead=$( count_lines "${revgit}" "^>" )
num_behind=$(( num_revs - num_ahead ))
if (( num_behind > 0 )) ; then
remote="${remote}_BEHIND_${num_behind}"
fi
if (( num_ahead > 0 )) ; then
remote="${remote}_AHEAD_${num_ahead}"
fi
fi
else
remote='_NO_REMOTE_TRACKING_'
remote_url='.'
unset upstream
fi
fi
if [[ -z "${remote:+x}" ]] ; then
remote='.'
fi
if [[ -z "${upstream:+x}" ]] ; then
upstream='^'
fi
printf "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" \
"${branch}" \
"${remote}" \
"${remote_url}" \
"${upstream}" \
"${num_staged}" \
"${num_conflicts}" \
"${num_changed}" \
"${num_untracked// /}" \
"${num_stashed}" \
"${clean}"
exit

View File

@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# prompt-colors.sh
#
# source this file to get color definitions
# are also printed to STDERR.
define_color_names() {
ColorNames=( Black Red Green Yellow Blue Magenta Cyan White )
FgColors=( 30 31 32 33 34 35 36 37 )
BgColors=( 40 41 42 43 44 45 46 47 )
local AttrNorm=0
local AttrBright=1
local AttrDim=2
local AttrUnder=4
local AttrBlink=5
local AttrRev=7
local AttrHide=8
# define "BoldCOLOR", "BrightCOLOR", and "DimCOLOR" names
# _map_colors ATTRNAME ATTRVALUE
#
# Defines three names for every color, attribute combintaion:
# {ATTRNAME}{COLORNAME}
# {ATTRNAME}{COLORNAME}Fg
# {ATTRNAME}{COLORNAME}Bg
#
# Example: BoldRed, BoldRedFg, BoldRedBg
_map_colors() {
local x=0
local attrname="${1}"
local attrcode="${2}"
while (( x < 8 )) ; do
local colorname="${ColorNames[x]}"
local fgcolorcode="${FgColors[x]}"
local bgcolorcode="${BgColors[x]}"
longcolorname="${attrname}${colorname}"
_def_color "${longcolorname}" "${attrcode}" "${fgcolorcode}"
_def_color "${longcolorname}Fg" "${attrcode}" "${fgcolorcode}"
_def_color "${longcolorname}Bg" "${attrcode}" "${bgcolorcode}"
(( x++ ))
done
}
# _term_color [ N | N M ]
_term_color() {
local cv
if [[ "${#}" -gt 1 ]]; then
cv="${1};${2}"
else
cv="${1}"
fi
echo "\[\033[${cv}m\]"
}
# def_color NAME ATTRCODE COLORCODE
_def_color() {
local def="${1}=\"\`_term_color ${2} ${3}\`\""
eval "${def}"
}
_map_colors Bold ${AttrBright}
_map_colors Bright ${AttrBright}
_map_colors Dim ${AttrDim}
_map_colors '' ${AttrNorm}
_def_color IntenseBlack 0 90
_def_color ResetColor 0 0
}
# do the color definitions only once
if [[ -z "${ColorNames+x}" || "${#ColorNames[*]}" = 0 || -z "${IntenseBlack:+x}" || -z "${ResetColor:+x}" ]]; then
define_color_names
fi

View File

@@ -0,0 +1,32 @@
# This theme for gitprompt.sh is designed for dark color schemes
# it is clone of oh-my-zsh crunch theme style with exit status
override_git_prompt_colors() {
if [ -e ~/.rvm/bin/rvm-prompt ]; then
RUBY_PROMPT='{$(~/.rvm/bin/rvm-prompt i v)}'
else
if command -v rbenv > /dev/null; then
RUBY_PROMPT='{$(rbenv version | sed -e "s/ (set.*$//")}'
fi
fi
Time12a="\$(date +%H:%M)"
GIT_PROMPT_THEME_NAME="Chmike"
GIT_PROMPT_BRANCH="${Green}"
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}"
GIT_PROMPT_REMOTE=" "
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="⭐"
GIT_PROMPT_SEPARATOR="|"
GIT_PROMPT_CHANGED="${Cyan}❗"
GIT_PROMPT_STAGED="${Yellow}▸"
GIT_PROMPT_UNTRACKED="${Blue}…"
GIT_PROMPT_CONFLICTS="${BoldRed}❓"
GIT_PROMPT_STASHED="${Magenta}>"
GIT_PROMPT_CLEAN="${Green}✔ "
GIT_PROMPT_COMMAND_OK="${Green}✔"
GIT_PROMPT_COMMAND_FAIL="${Red}✘"
}
reload_git_prompt_colors "Chmike"

View File

@@ -0,0 +1,34 @@
# This theme for gitprompt.sh is designed for dark color schemes
# it is clone of oh-my-zsh crunch theme style with exit status
override_git_prompt_colors() {
if [ -e ~/.rvm/bin/rvm-prompt ]; then
RUBY_PROMPT='{$(~/.rvm/bin/rvm-prompt i v)}'
else
if command -v rbenv > /dev/null; then
RUBY_PROMPT='{$(rbenv version | sed -e "s/ (set.*$//")}'
fi
fi
Time12a="\$(date +%H:%M)"
GIT_PROMPT_THEME_NAME="Crunch"
GIT_PROMPT_STAGED="${Yellow}● "
GIT_PROMPT_UNTRACKED="${Cyan}… "
GIT_PROMPT_STASHED="${BoldMagenta}⚑ "
GIT_PROMPT_CLEAN="${Green}✔ "
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_COMMAND_FAIL="${Red}✘ "
KERNEL_PROMPT='$(uname -r)'
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_${White}{${Yellow}${Time12a}${White}}[${Magenta}${RUBY_PROMPT}${White}]${Cyan}${PathShort}${White}:"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
GIT_PROMPT_END_USER="${BoldBlue} ➭ ${ResetColor}"
GIT_PROMPT_END_ROOT="${BoldRed} # ${ResetColor}"
GIT_PROMPT_LEADING_SPACE=0
GIT_PROMPT_PREFIX="${Green}["
GIT_PROMPT_SUFFIX="${Green}]"
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="✭"
}
reload_git_prompt_colors "Crunch"

View File

@@ -0,0 +1,65 @@
# This is the custom theme template for gitprompt.sh
# These are the defaults from the "Default" theme
# You just need to override what you want to have changed
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Custom"
# Time12a="\$(date +%H:%M)"
# PathShort="\w";
## These are the color definitions used by gitprompt.sh
# GIT_PROMPT_PREFIX="[" # start of the git info string
# GIT_PROMPT_SUFFIX="]" # the end of the git info string
# GIT_PROMPT_SEPARATOR="|" # separates each item
# GIT_PROMPT_BRANCH="${Magenta}" # the git branch that is active in the current directory
# GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}" # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
# GIT_PROMPT_STAGED="${Red}●" # the number of staged files/directories
# GIT_PROMPT_CONFLICTS="${Red}✖ " # the number of files in conflict
# GIT_PROMPT_CHANGED="${Blue}✚ " # the number of changed files
# GIT_PROMPT_REMOTE=" " # the remote branch name (if any) and the symbols for ahead and behind
# GIT_PROMPT_UNTRACKED="${Cyan}…" # the number of untracked files/dirs
# GIT_PROMPT_STASHED="${BoldBlue}⚑ " # the number of stashed files/dir
# GIT_PROMPT_CLEAN="${BoldGreen}✔" # a colored flag indicating a "clean" repo
## For the command indicator, the placeholder _LAST_COMMAND_STATE_
## will be replaced with the exit code of the last command
## e.g.
## GIT_PROMPT_COMMAND_OK="${Green}✔-_LAST_COMMAND_STATE_ " # indicator if the last command returned with an exit code of 0
## GIT_PROMPT_COMMAND_FAIL="${Red}✘-_LAST_COMMAND_STATE_ " # indicator if the last command returned with an exit code of other than 0
# GIT_PROMPT_COMMAND_OK="${Green}✔" # indicator if the last command returned with an exit code of 0
# GIT_PROMPT_COMMAND_FAIL="${Red}✘-_LAST_COMMAND_STATE_" # indicator if the last command returned with an exit code of other than 0
## template for displaying the current virtual environment
## use the placeholder _VIRTUALENV_ will be replaced with
## the name of the current virtual environment (currently CONDA and VIRTUAL_ENV)
# GIT_PROMPT_VIRTUALENV="(${Blue}_VIRTUALENV_${ResetColor}) "
# template for displaying the current remote tracking branch
# use the placeholder _UPSTREAM_ will be replaced with
# the name of the current remote tracking branch
# GIT_PROMPT_UPSTREAM=" {${Blue}_UPSTREAM_${ResetColor}}"
## _LAST_COMMAND_INDICATOR_ will be replaced by the appropriate GIT_PROMPT_COMMAND_OK OR GIT_PROMPT_COMMAND_FAIL
# GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${Yellow}${PathShort}${ResetColor}"
# GIT_PROMPT_START_ROOT="_LAST_COMMAND_INDICATOR_ ${GIT_PROMPT_START_USER}"
# GIT_PROMPT_END_USER=" \n${White}${Time12a}${ResetColor} $ "
# GIT_PROMPT_END_ROOT=" \n${White}${Time12a}${ResetColor} # "
## Please do not add colors to these symbols
# GIT_PROMPT_SYMBOLS_AHEAD="↑·" # The symbol for "n versions ahead of origin"
# GIT_PROMPT_SYMBOLS_BEHIND="↓·" # The symbol for "n versions behind of origin"
# GIT_PROMPT_SYMBOLS_PREHASH=":" # Written before hash of commit, if no name could be found
# GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="L" # This symbol is written after the branch, if the branch is not tracked
# branch name(s) that will use $GIT_PROMPT_MASTER_BRANCH color
# To specify multiple branches, use
# shopt -s extglob
# GIT_PROMPT_MASTER_BRANCHES='@(master|production)'
# GIT_PROMPT_MASTER_BRANCHES="master"
}
reload_git_prompt_colors "Custom"

View File

@@ -0,0 +1,113 @@
# This is the default theme for gitprompt.sh
unset_git_prompt_colors() {
unset Time12a
unset PathShort
unset GIT_PROMPT_PREFIX
unset GIT_PROMPT_SUFFIX
unset GIT_PROMPT_SEPARATOR
unset GIT_PROMPT_BRANCH
unset GIT_PROMPT_STAGED
unset GIT_PROMPT_CONFLICTS
unset GIT_PROMPT_CHANGED
unset GIT_PROMPT_REMOTE
unset GIT_PROMPT_UNTRACKED
unset GIT_PROMPT_STASHED
unset GIT_PROMPT_CLEAN
unset GIT_PROMPT_COMMAND_OK
unset GIT_PROMPT_COMMAND_FAIL
unset GIT_PROMPT_VIRTUALENV
unset GIT_PROMPT_UPSTREAM
unset GIT_PROMPT_START_USER
unset GIT_PROMPT_START_ROOT
unset GIT_PROMPT_END_USER
unset GIT_PROMPT_END_ROOT
unset GIT_PROMPT_SYMBOLS_AHEAD
unset GIT_PROMPT_SYMBOLS_BEHIND
unset GIT_PROMPT_SYMBOLS_PREHASH
unset GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING
}
define_helpers() {
Time12a="\$(date +%H:%M)"
PathShort="\w";
}
define_undefined_git_prompt_colors() {
if [ -z ${GIT_PROMPT_THEME_NAME:+x} ]; then GIT_PROMPT_THEME_NAME="Default"; fi
# These are the color definitions used by gitprompt.sh
if [ -z "${GIT_PROMPT_PREFIX+x}" ]; then GIT_PROMPT_PREFIX="["; fi # start of the git info string
if [ -z "${GIT_PROMPT_SUFFIX+x}" ]; then GIT_PROMPT_SUFFIX="]"; fi # the end of the git info string
if [ -z "${GIT_PROMPT_SEPARATOR+x}" ]; then GIT_PROMPT_SEPARATOR="|"; fi # separates each item
if [ -z "${GIT_PROMPT_BRANCH+x}" ]; then GIT_PROMPT_BRANCH="${Magenta}"; fi # the git branch that is active in the current directory
if [ -z "${GIT_PROMPT_MASTER_BRANCH+x}" ]; then GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}"; fi # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
if [ -z "${GIT_PROMPT_STAGED+x}" ]; then GIT_PROMPT_STAGED="${Red}●"; fi # the number of staged files/directories
if [ -z "${GIT_PROMPT_CONFLICTS+x}" ]; then GIT_PROMPT_CONFLICTS="${Red}✖ "; fi # the number of files in conflict
if [ -z "${GIT_PROMPT_CHANGED+x}" ]; then GIT_PROMPT_CHANGED="${Blue}✚ "; fi # the number of changed files
if [ -z "${GIT_PROMPT_REMOTE+x}" ]; then GIT_PROMPT_REMOTE=" "; fi # the remote branch name (if any) and the symbols for ahead and behind
if [ -z "${GIT_PROMPT_UNTRACKED+x}" ]; then GIT_PROMPT_UNTRACKED="${Cyan}…"; fi # the number of untracked files/dirs
if [ -z "${GIT_PROMPT_STASHED+x}" ]; then GIT_PROMPT_STASHED="${BoldBlue}⚑ "; fi # the number of stashed files/dir
if [ -z "${GIT_PROMPT_CLEAN+x}" ]; then GIT_PROMPT_CLEAN="${BoldGreen}✔"; fi # a colored flag indicating a "clean" repo
# For the command indicator, the placeholder _LAST_COMMAND_STATE_
# will be replaced with the exit code of the last command
# e.g.
# GIT_PROMPT_COMMAND_OK="${Green}✔-_LAST_COMMAND_STATE_ " # indicator if the last command returned with an exit code of 0
# GIT_PROMPT_COMMAND_FAIL="${Red}✘-_LAST_COMMAND_STATE_ " # indicator if the last command returned with an exit code of other than 0
if [ -z "${GIT_PROMPT_COMMAND_OK+x}" ]; then GIT_PROMPT_COMMAND_OK="${Green}✔"; fi # indicator if the last command returned with an exit code of 0
if [ -z "${GIT_PROMPT_COMMAND_FAIL+x}" ]; then GIT_PROMPT_COMMAND_FAIL="${Red}✘-_LAST_COMMAND_STATE_"; fi # indicator if the last command returned with an exit code of other than 0
# Possible to change which command is used to create git status information
# There are three options:
# 1) gitstatus.sh (uses git status --branch --porcelain - fast, requires git > 1.7.10)
# 2) gitstatus_pre-1.7.10.sh (Uses a variety of git commands and pipes - slower, works with older git clients)
# 3) gitstatus.py (Unsupported, lack features found in the bash versions)
if [ -z "${GIT_PROMPT_STATUS_COMMAND+x}" ]; then GIT_PROMPT_STATUS_COMMAND="gitstatus.sh"; fi # Point out the command to get the git status from
# template for displaying the current virtual environment
# use the placeholder _VIRTUALENV_ will be replaced with
# the name of the current virtual environment (currently CONDA and VIRTUAL_ENV)
if [ -z "${GIT_PROMPT_VIRTUALENV+x}" ]; then GIT_PROMPT_VIRTUALENV="(${Blue}_VIRTUALENV_${ResetColor}) "; fi
# template for displaying the current remote tracking branch
# use the placeholder _UPSTREAM_ will be replaced with
# the name of the current remote tracking branch
if [ -z "${GIT_PROMPT_UPSTREAM+x}" ]; then GIT_PROMPT_UPSTREAM=" {${Blue}_UPSTREAM_${ResetColor}}"; fi
# _LAST_COMMAND_INDICATOR_ will be replaced by the appropriate GIT_PROMPT_COMMAND_OK OR GIT_PROMPT_COMMAND_FAIL
if [ -z "${GIT_PROMPT_START_USER+x}" ]; then GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${Yellow}${PathShort}${ResetColor}"; fi
if [ -z "${GIT_PROMPT_START_ROOT+x}" ]; then GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"; fi
if [ -z "${GIT_PROMPT_END_USER+x}" ]; then GIT_PROMPT_END_USER=" \n${White}${Time12a}${ResetColor} $ "; fi
if [ -z "${GIT_PROMPT_END_ROOT+x}" ]; then GIT_PROMPT_END_ROOT=" \n${White}${Time12a}${ResetColor} # "; fi
# Please do not add colors to these symbols
if [ -z ${GIT_PROMPT_SYMBOLS_AHEAD+x} ]; then GIT_PROMPT_SYMBOLS_AHEAD="↑·"; fi # The symbol for "n versions ahead of origin"
if [ -z ${GIT_PROMPT_SYMBOLS_BEHIND+x} ]; then GIT_PROMPT_SYMBOLS_BEHIND="↓·"; fi # The symbol for "n versions behind of origin"
if [ -z ${GIT_PROMPT_SYMBOLS_PREHASH+x} ]; then GIT_PROMPT_SYMBOLS_PREHASH=":"; fi # Written before hash of commit, if no name could be found
if [ -z ${GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING+x} ]; then GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="L"; fi # This symbol is written after the branch, if the branch is not tracked
# branch name(s) that will use $GIT_PROMPT_MASTER_BRANCH color
# To specify multiple branches, use
# shopt -s extglob
# GIT_PROMPT_MASTER_BRANCHES='@(master|production)'
if [ -z ${GIT_PROMPT_MASTER_BRANCHES+x} ]; then GIT_PROMPT_MASTER_BRANCHES="master"; fi
}
# call only from theme file
reload_git_prompt_colors() {
if [[ "${GIT_PROMPT_THEME_NAME-}" != "${1}" ]]; then
unset_git_prompt_colors
define_helpers
override_git_prompt_colors
define_undefined_git_prompt_colors
fi
}
if [[ "${GIT_PROMPT_THEME-}" == "Default" && "${GIT_PROMPT_THEME_NAME-}" != "Default" ]]; then
define_helpers
define_undefined_git_prompt_colors
fi

View File

@@ -0,0 +1,11 @@
# This is the default theme for gitprompt.sh
# without the indicator of the last command state
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Default NoExitState"
GIT_PROMPT_COMMAND_FAIL="${Red}✘" # indicator if the last command returned with an exit code of other than 0
GIT_PROMPT_START_USER="${Yellow}${PathShort}${ResetColor}"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
}
reload_git_prompt_colors "Default NoExitState"

View File

@@ -0,0 +1,15 @@
# This is the default theme for gitprompt.sh
# without the indicator of the last command state
# tweaked for Ubuntu terminal fonts
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Default NoExitState Ubuntu"
GIT_PROMPT_STAGED="${Red}● " # the number of staged files/directories
GIT_PROMPT_CLEAN="${BoldGreen}✔ " # a colored flag indicating a "clean" repo
GIT_PROMPT_COMMAND_OK="${Green}✔ " # indicator if the last command returned with an exit code of 0
GIT_PROMPT_COMMAND_FAIL="${Red}✘ " # indicator if the last command returned with an exit code of other than 0
GIT_PROMPT_START_USER="${Yellow}${PathShort}${ResetColor}"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
}
reload_git_prompt_colors "Default NoExitState Ubuntu"

View File

@@ -0,0 +1,11 @@
# This is the default theme for gitprompt.sh
# tweaked for Ubuntu terminal fonts
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Default Ubuntu"
GIT_PROMPT_STAGED="${Red}● " # the number of staged files/directories
GIT_PROMPT_CLEAN="${BoldGreen}✔ " # a colored flag indicating a "clean" repo
GIT_PROMPT_COMMAND_OK="${Green}✔ " # indicator if the last command returned with an exit code of 0
}
reload_git_prompt_colors "Default Ubuntu"

View File

@@ -0,0 +1,31 @@
# This theme for gitprompt.sh is designed for dark color schemes
# It is most suitable for Retina or high resolution displays
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Evermeet"
GIT_PROMPT_PREFIX="" # start of the git info string
GIT_PROMPT_SUFFIX="" # the end of the git info string
GIT_PROMPT_SEPARATOR="|" # separates each item
GIT_PROMPT_BRANCH="${Magenta}" # the git branch that is active in the current directory
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}" # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
GIT_PROMPT_STAGED="${Cyan}●" # the number of staged files/directories
GIT_PROMPT_CONFLICTS="${BoldRed}✖" # the number of files in conflict
GIT_PROMPT_CHANGED="${Cyan}✚" # the number of changed files
GIT_PROMPT_UNTRACKED="${Cyan}…" # the number of untracked files/dirs
GIT_PROMPT_STASHED="${Magenta}⚑" # the number of stashed files/dir
GIT_PROMPT_CLEAN="${BoldGreen}✔" # a colored flag indicating a "clean" repo
GIT_PROMPT_UPSTREAM=" {${Magenta}_UPSTREAM_${ResetColor}}"
GIT_PROMPT_START_USER="[${BoldGreen}\u@\h${ResetColor} ${BoldYellow}\${?}${ResetColor} ${BoldBlue}\w${ResetColor}"
GIT_PROMPT_START_ROOT="[${BoldRed}\u@\h${ResetColor} ${BoldYellow}\${?}${ResetColor} ${BoldBlue}\w${ResetColor}"
GIT_PROMPT_END_USER="]$ "
GIT_PROMPT_END_ROOT="]# "
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="⭑" # This symbol is written after the branch, if the branch is not tracked
}
reload_git_prompt_colors "Evermeet"

View File

@@ -0,0 +1,33 @@
# This theme for gitprompt.sh is designed for dark color schemes
# On lowres screens unicode characters like ✖ require a space after them
# otherwise the following character may overlap with the unicode character
# tweaked for low resolution and non-retina screens
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Evermeet_Lowres"
GIT_PROMPT_PREFIX="" # start of the git info string
GIT_PROMPT_SUFFIX="" # the end of the git info string
GIT_PROMPT_SEPARATOR="|" # separates each item
GIT_PROMPT_BRANCH="${Magenta}" # the git branch that is active in the current directory
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}" # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
GIT_PROMPT_STAGED="${Cyan}●" # the number of staged files/directories
GIT_PROMPT_CONFLICTS="${BoldRed}✖ " # the number of files in conflict
GIT_PROMPT_CHANGED="${Cyan}✚ " # the number of changed files
GIT_PROMPT_UNTRACKED="${Cyan}…" # the number of untracked files/dirs
GIT_PROMPT_STASHED="${Magenta}⚑" # the number of stashed files/dir
GIT_PROMPT_CLEAN="${BoldGreen}✔" # a colored flag indicating a "clean" repo
GIT_PROMPT_UPSTREAM=" {${Magenta}_UPSTREAM_${ResetColor}}"
GIT_PROMPT_START_USER="[${BoldGreen}\u@\h${ResetColor} ${BoldYellow}\${?}${ResetColor} ${BoldBlue}\w${ResetColor}"
GIT_PROMPT_START_ROOT="[${BoldRed}\u@\h${ResetColor} ${BoldYellow}\${?}${ResetColor} ${BoldBlue}\w${ResetColor}"
GIT_PROMPT_END_USER="]$ "
GIT_PROMPT_END_ROOT="]# "
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="⭑ " # This symbol is written after the branch, if the branch is not tracked
}
reload_git_prompt_colors "Evermeet_Lowres"

View File

@@ -0,0 +1,33 @@
# This theme for gitprompt.sh is designed for dark color schemes
# On lowres screens unicode characters like ✖ require a space after them
# otherwise the following character may overlap with the unicode character
# tweaked for Ubuntu terminal fonts
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Evermeet_Ubuntu"
GIT_PROMPT_PREFIX="" # start of the git info string
GIT_PROMPT_SUFFIX="" # the end of the git info string
GIT_PROMPT_SEPARATOR="|" # separates each item
GIT_PROMPT_BRANCH="${Magenta}" # the git branch that is active in the current directory
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}" # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
GIT_PROMPT_STAGED="${Cyan}● " # the number of staged files/directories
GIT_PROMPT_CONFLICTS="${BoldRed}✖ " # the number of files in conflict
GIT_PROMPT_CHANGED="${Cyan}✚ " # the number of changed files
GIT_PROMPT_UNTRACKED="${Cyan}…" # the number of untracked files/dirs
GIT_PROMPT_STASHED="${Magenta}⚑ " # the number of stashed files/dir
GIT_PROMPT_CLEAN="${BoldGreen}✔ " # a colored flag indicating a "clean" repo
GIT_PROMPT_UPSTREAM=" {${Magenta}_UPSTREAM_${ResetColor}}"
GIT_PROMPT_START_USER="[${BoldGreen}\u@\h${ResetColor} ${BoldYellow}\${?}${ResetColor} ${BoldBlue}\w${ResetColor}"
GIT_PROMPT_START_ROOT="[${BoldRed}\u@\h${ResetColor} ${BoldYellow}\${?}${ResetColor} ${BoldBlue}\w${ResetColor}"
GIT_PROMPT_END_USER="]$ "
GIT_PROMPT_END_ROOT="]# "
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="⭑ " # This symbol is written after the branch, if the branch is not tracked
}
reload_git_prompt_colors "Evermeet_Ubuntu"

View File

@@ -0,0 +1,62 @@
##############################################################################
# Changes the prompt to a Debian-style one that truncates pwd to a max length
# depending on the terminal column width. Also uses the prompt_callback
# function of bash-git-prompt to set the window title to almost the same
# Debian-style. This version has been tweaked for Ubuntu standard terminal
# fonts.
#
# The prompt will use a Debian-style on the form
#
# relative-path-from-git-toplevel-dir bash-git-prompt-info <exit status>
# HH:MM:SS ▶
#
# The window title will have the form
# relative-path-from-git-toplevel-dir
#
# Example usage:
# if [ -f ~/.bash-git-prompt/gitprompt.sh ]; then
# GIT_PROMPT_THEME=Minimal
# source ~/.bash-git-prompt/gitprompt.sh
# fi
#
# Imbibinebe <imbibinebe@gmail.com> [https://github.com/imbibinebe]
##############################################################################
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Minimal"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
GIT_CONTAINER_FOLDER_FULLPATH=$(git rev-parse --show-toplevel 2> /dev/null)
GIT_CONTAINER_FOLDER=$(basename $GIT_CONTAINER_FOLDER_FULLPATH 2> /dev/null)
CURRENT_FULLPATH=$(pwd)
local PS1=$GIT_CONTAINER_FOLDER${CURRENT_FULLPATH#$GIT_CONTAINER_FOLDER_FULLPATH}
gp_set_window_title "$PS1"
echo -n "${BoldYellow}${PS1}${ResetColor}"
}
Time12a="\$(date +%H:%M:%S)"
GIT_PROMPT_BRANCH="${BoldMagenta}" # the git branch that is active in the current directory
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_MASTER_BRANCH}" # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
GIT_PROMPT_PREFIX="" # start of the git info string
GIT_PROMPT_SUFFIX="" # the end of the git info string
GIT_PROMPT_SEPARATOR="" # separates each item
GIT_PROMPT_STAGED=" ${Green}●" # the number of staged files/directories
GIT_PROMPT_CONFLICTS=" ${BoldRed}✖" # the number of files in conflict
GIT_PROMPT_CHANGED=" ${BoldBlue}✚" # the number of changed files
# GIT_PROMPT_REMOTE=" " # the remote branch name (if any) and the symbols for ahead and behind
GIT_PROMPT_UNTRACKED=" ${Cyan}…" # the number of untracked files/dirs
GIT_PROMPT_STASHED=" ${BoldCyan}⚑" # the number of stashed files/dir
GIT_PROMPT_CLEAN=" ${BoldGreen}✔" # a colored flag indicating a "clean" repo
local gp_end="_LAST_COMMAND_INDICATOR_\n${White}${Time12a}${ResetColor}"
GIT_PROMPT_START_USER=""
GIT_PROMPT_END_USER="${gp_end} ▶ "
GIT_PROMPT_END_ROOT="${gp_end} /!!!\ "
GIT_PROMPT_COMMAND_OK="${Green} ✔ " # indicator if the last command returned with an exit code of 0
GIT_PROMPT_COMMAND_FAIL="${BoldRed} ✘-_LAST_COMMAND_STATE_" # indicator if the last command returned with an exit code of other than 0
}
reload_git_prompt_colors "Minimal"

View File

@@ -0,0 +1,72 @@
##############################################################################
# Changes the prompt to a Debian-style one that truncates pwd to a max length
# depending on the terminal column width. Also uses the prompt_callback
# function of bash-git-prompt to set the window title to almost the same
# Debian-style. This version has been tweaked for Ubuntu standard terminal
# fonts.
#
# The prompt will use a Debian-style on the form
#
# relative-path-from-git-toplevel-dir bash-git-prompt-info <exit status>
# HH:MM ▶
#
# ● ✖ ◆ ➤ ▶ ❚❖ ⬅ ◀ ✔ ✘ ⬆ ⬇ ✚ ✦ ✛ ✲
#
# The window title will have the form
# relative-path-from-git-toplevel-dir
#
# Example usage:
# if [ -f ~/.bash-git-prompt/gitprompt.sh ]; then
# GIT_PROMPT_THEME=Minimal_Time
# source ~/.bash-git-prompt/gitprompt.sh
# fi
#
# [https://github.com/modib]
##############################################################################
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Minimal_Time"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
GIT_CONTAINER_FOLDER_FULLPATH=$(git rev-parse --show-toplevel 2> /dev/null)
GIT_CONTAINER_FOLDER=$(basename $GIT_CONTAINER_FOLDER_FULLPATH 2> /dev/null)
CURRENT_FULLPATH=$(pwd)
local PS1=$GIT_CONTAINER_FOLDER${CURRENT_FULLPATH#$GIT_CONTAINER_FOLDER_FULLPATH}
gp_set_window_title "$PS1"
echo "${Cyan}${PS1}${ResetColor}"
}
Time12a="\$(date +%H:%M)"
GIT_PROMPT_BRANCH="${Magenta}" # the git branch that is active in the current directory
GIT_PROMPT_MASTER_BRANCH="${White}" # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
GIT_PROMPT_PREFIX="["
GIT_PROMPT_SUFFIX="]"
GIT_PROMPT_SEPARATOR="" # separates each item
GIT_PROMPT_STAGED=" ${Green}●" # the number of staged files/directories
GIT_PROMPT_CONFLICTS=" ${Red}" # the number of files in conflict
GIT_PROMPT_CHANGED=" ${Yellow}✚." # the number of changed files
GIT_PROMPT_REMOTE=" " # the remote branch name (if any) and the symbols for ahead and behind
GIT_PROMPT_UNTRACKED=" ${Cyan}…" # the number of untracked files/dirs
GIT_PROMPT_STASHED=" ${Cyan}⚑" # the number of stashed files/dir
GIT_PROMPT_CLEAN=" ${Green}" # a colored flag indicating a "clean" repo
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="${Red}✭"
GIT_PROMPT_COMMAND_OK="${Green}" # indicator if the last command returned with an exit code of 0
GIT_PROMPT_COMMAND_FAIL="${Red} _LAST_COMMAND_STATE_" # indicator if the last command returned with an exit code of other than 0
local gp_start="_LAST_COMMAND_INDICATOR_"
local gp_end="\n${White}${Time12a}${ResetColor} "
GIT_PROMPT_START_USER="\n${gp_start} "
GIT_PROMPT_END_USER="${gp_end} "
#GIT_PROMPT_SYMBOLS_AHEAD="↑·"
GIT_PROMPT_SYMBOLS_AHEAD="⬆."
#GIT_PROMPT_SYMBOLS_BEHIND="↓·"
GIT_PROMPT_SYMBOLS_BEHIND="⬇."
}
reload_git_prompt_colors "Minimal_Time"

View File

@@ -0,0 +1,70 @@
##############################################################################
# Changes the prompt to a Debian-style one that truncates pwd to a max length
# depending on the terminal column width. Also uses the prompt_callback
# function of bash-git-prompt to set the window title to almost the same
# Debian-style. This version has been tweaked for Ubuntu standard terminal
# fonts.
#
# The prompt will use a Debian-style on the form
#
# relative-path-from-git-toplevel-dir bash-git-prompt-info <exit status>
# HH:MM:SS User@Host ▶
#
# The window title will have the form
# relative-path-from-git-toplevel-dir
#
# Example usage:
# if [ -f ~/.bash-git-prompt/gitprompt.sh ]; then
# GIT_PROMPT_THEME=Minimal_UserHost
# source ~/.bash-git-prompt/gitprompt.sh
# fi
#
# Gert Pellin <gert@pellin.be> [https://github.com/switch87]
#
# Based on Minimal by Imbibinebe <imbibinebe@gmail.com> [https://github.com/imbibinebe]
##############################################################################
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Minimal_UserHost"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
GIT_CONTAINER_FOLDER_FULLPATH=$(git rev-parse --show-toplevel 2> /dev/null)
GIT_CONTAINER_FOLDER=$(basename $GIT_CONTAINER_FOLDER_FULLPATH 2> /dev/null)
CURRENT_FULLPATH=$(pwd)
local PS1=$GIT_CONTAINER_FOLDER${CURRENT_FULLPATH#$GIT_CONTAINER_FOLDER_FULLPATH}
gp_set_window_title "$PS1"
echo -n "${BoldYellow}${PS1}${ResetColor}"
}
Time12a="\$(date +%H:%M:%S)"
if [ "$(id -u)" != "0" ]; then
UserHost_Color="${BoldGreen}"
else
UserHost_Color="${BoldRed}"
fi
GIT_PROMPT_BRANCH="${BoldMagenta}" # the git branch that is active in the current directory
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_MASTER_BRANCH}" # used if the git branch that is active in the current directory is $GIT_PROMPT_MASTER_BRANCHES
GIT_PROMPT_PREFIX="" # start of the git info string
GIT_PROMPT_SUFFIX="" # the end of the git info string
GIT_PROMPT_SEPARATOR="" # separates each item
GIT_PROMPT_STAGED=" ${Green}●" # the number of staged files/directories
GIT_PROMPT_CONFLICTS=" ${BoldRed}✖" # the number of files in conflict
GIT_PROMPT_CHANGED=" ${BoldBlue}✚" # the number of changed files
# GIT_PROMPT_REMOTE=" " # the remote branch name (if any) and the symbols for ahead and behind
GIT_PROMPT_UNTRACKED=" ${Cyan}…" # the number of untracked files/dirs
GIT_PROMPT_STASHED=" ${BoldCyan}⚑" # the number of stashed files/dir
GIT_PROMPT_CLEAN=" ${BoldGreen}✔" # a colored flag indicating a "clean" repo
local gp_end="_LAST_COMMAND_INDICATOR_\n${BoldBlack}${Time12a} ${UserHost_Color}$(whoami)@$(hostname)${ResetColor}"
GIT_PROMPT_START_USER=""
GIT_PROMPT_END_USER="${gp_end} ▶ "
GIT_PROMPT_END_ROOT="${gp_end} /!!!\ "
GIT_PROMPT_COMMAND_OK="${Green} ✔ " # indicator if the last command returned with an exit code of 0
GIT_PROMPT_COMMAND_FAIL="${BoldRed} ✘-_LAST_COMMAND_STATE_" # indicator if the last command returned with an exit code of other than 0
}
reload_git_prompt_colors "Minimal_UserHost"

View File

@@ -0,0 +1,41 @@
# Plague Doctor's bash-git-prompt theme.
#
# Note 1: The theme is designed to work only in GIT Repos.
# If one needs a coresponding prompt for non GIT locations, here is the code:
#
# if [ -f <path-to-prompt-colors.sh> ]; then
# source <path-to-prompt-colors.sh>
# MYPROMPT="${White}\A${ResetColor} ${BoldGreen}\\u${White}@${BoldYellow}\\h ${Cyan}\w${ResetColor}${BoldWhite} $ ${ResetColor}"
# else
# MYPROMPT="\[\033[37m\]\A \[\033[1m\]\[\033[32m\]\u\[\033[0m\]\[\033[37m\]@\[\033[1m\]\[\033[33m\]\h:\[\033[0m\]\[\033[36m\] \w\[\033[0m\]\[\033[1m\]\[\033[37m\] \$ \[\033[0m\]"
# fi
# export PS1=$MYPROMPT
#
# Note 2: The theme looks very nice with "FantasqueSansMono Nerd Font" https://github.com/ryanoasis/nerd-fonts
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Plague Doctor"
GIT_PROMPT_ONLY_IN_REPO=1
GIT_PROMPT_LEADING_SPACE=0
GIT_PROMPT_PREFIX="[ "
GIT_PROMPT_SUFFIX=" ]"
GIT_PROMPT_SEPARATOR=" |"
GIT_PROMPT_STAGED=" ${Red}● ${ResetColor}"
GIT_PROMPT_CONFLICTS=" ${Red}✖ ${ResetColor}"
GIT_PROMPT_CHANGED=" ${Blue}✚ ${ResetColor}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_STASHED=" ${BoldBlue}⚑ ${ResetColor}"
GIT_PROMPT_CLEAN=" ${BoldGreen}✔ ${ResetColor}"
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="✭"
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_COMMAND_FAIL="${Red}✘ "
GIT_PROMPT_START_USER="${BoldBlue} ${ResetColor}"
GIT_PROMPT_START_ROOT="${BoldRed}❖ ${ResetColor}"
GIT_PROMPT_END_USER="\n_LAST_COMMAND_INDICATOR_${White}${Time12a}${ResetColor} ${BoldGreen}\\u${White}@${BoldYellow}\\h ${Cyan}${PathShort}${ResetColor}${BoldWhite} $ ${ResetColor}"
GIT_PROMPT_END_ROOT="\n_LAST_COMMAND_INDICATOR_${White}${Time12a}${ResetColor} ${BoldRed}\\u${White}@${BoldYellow}\\h ${Cyan}${PathShort}${ResetColor}${BoldRed} # ${ResetColor}"
}
reload_git_prompt_colors "Plague Doctor"

View File

@@ -0,0 +1,11 @@
# This is an alternative approach. Single line in git repo.
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${White}${Time12a}${ResetColor} ${BoldYellow}${PathShort}${ResetColor}"
GIT_PROMPT_END_USER="${ResetColor} $ "
GIT_PROMPT_END_ROOT="${BoldRed} # "
}
reload_git_prompt_colors "Single_line"

View File

@@ -0,0 +1,20 @@
# This is a theme for gitprompt.sh,
# it uses the default openSUSE bash prompt style with exit status
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_nono031"
GIT_PROMPT_BRANCH="${Cyan}"
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_CHANGED="${Yellow}✚ "
GIT_PROMPT_STAGED="${Magenta}●"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${BoldGreen}\h:${BoldBlue}\w${ResetColor}"
GIT_PROMPT_START_ROOT="_LAST_COMMAND_INDICATOR_ ${BoldRed}\h:${BoldBlue}\w${ResetColor}"
GIT_PROMPT_END_USER="${ResetColor}> "
GIT_PROMPT_END_ROOT=" # ${ResetColor}"
}
reload_git_prompt_colors "Single_line_nono031"

View File

@@ -0,0 +1,33 @@
# This is an alternative approach. Single line minimalist in git repo.
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_Minimalist"
function prompt_callback {
local PS1="$(gp_truncate_pwd)"
gp_set_window_title "$PS1"
}
Time12a="\$(date +%H:%M:%S)"
PathShort="\W";
GIT_PROMPT_PREFIX="["
GIT_PROMPT_SUFFIX="]"
GIT_PROMPT_SEPARATOR=" "
GIT_PROMPT_STAGED="${Red}●${ResetColor}"
GIT_PROMPT_CONFLICTS="${Red}✖${ResetColor}"
GIT_PROMPT_CHANGED="${Blue}✚${ResetColor}"
GIT_PROMPT_UNTRACKED="${Cyan}…${ResetColor}"
GIT_PROMPT_STASHED="${BoldBlue}⚑${ResetColor}"
GIT_PROMPT_CLEAN="${BoldGreen}✔${ResetColor}"
GIT_PROMPT_COMMAND_OK="${Green}✔"
GIT_PROMPT_COMMAND_FAIL="${Red}✘"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${White}${Time12a}${ResetColor} ${Cyan}${PathShort}${ResetColor}"
GIT_PROMPT_END_USER="${ResetColor} $ "
GIT_PROMPT_END_ROOT="${BoldRed} # "
}
reload_git_prompt_colors "Single_line_Minimalist"

View File

@@ -0,0 +1,12 @@
# This is an alternative approach. Single line in git repo.
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_NoExitState"
GIT_PROMPT_COMMAND_FAIL="${Red}✘"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${White}${Time12a}${ResetColor} ${BoldYellow}${PathShort}${ResetColor}"
GIT_PROMPT_END_USER="${ResetColor} $ "
GIT_PROMPT_END_ROOT="${BoldRed} # "
}
reload_git_prompt_colors "Single_line_NoExitState"

View File

@@ -0,0 +1,20 @@
# This is a theme for gitprompt.sh,
# it uses the default Gentoo bash prompt style.
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_NoExitState_Gentoo"
GIT_PROMPT_BRANCH="${Cyan}"
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_CHANGED="${Yellow}✚ "
GIT_PROMPT_STAGED="${Magenta}●"
GIT_PROMPT_START_USER="${BoldGreen}\u@\h ${BrightBlue}\w${ResetColor}"
GIT_PROMPT_START_ROOT="${BoldRed}\h ${BrightBlue}\w${ResetColor}"
GIT_PROMPT_END_USER="${BrightBlue} \$ ${ResetColor}"
GIT_PROMPT_END_ROOT="${BrightBlue} \$ ${ResetColor}"
}
reload_git_prompt_colors "Single_line_NoExitState_Gentoo"

View File

@@ -0,0 +1,20 @@
# This is a theme for gitprompt.sh,
# it uses the default openSUSE bash prompt style
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_NoExitState_openSUSE"
GIT_PROMPT_BRANCH="${Cyan}"
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_CHANGED="${Yellow}✚ "
GIT_PROMPT_STAGED="${Magenta}●"
GIT_PROMPT_START_USER="\u@\h:\w"
GIT_PROMPT_START_ROOT="${BoldRed}\h:\w"
GIT_PROMPT_END_USER="> "
GIT_PROMPT_END_ROOT=" # ${ResetColor}"
}
reload_git_prompt_colors "Single_line_NoExitState_openSUSE"

View File

@@ -0,0 +1,34 @@
# This is an alternative approach. Single line in git repo.
# Theme optimised for Terminus and PowerLine compatible fonts.
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# without the indicator of the last command state
# tweaked for Ubuntu terminal fonts
define_helpers() {
PathShort="${BoldBlue}\u:${Cyan}\W"
}
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_Solarized"
GIT_PROMPT_PREFIX="[ "
GIT_PROMPT_SUFFIX=" ]"
GIT_PROMPT_SEPARATOR=" |"
GIT_PROMPT_STAGED=" ${Yellow}● ${ResetColor}"
GIT_PROMPT_CONFLICTS=" ${Red}✖ ${ResetColor}"
GIT_PROMPT_CHANGED=" ${Blue}✚ ${ResetColor}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_STASHED=" ${BoldMagenta}⚑ ${ResetColor}"
GIT_PROMPT_CLEAN=" ${Green}✔ ${ResetColor}"
GIT_PROMPT_COMMAND_FAIL="${Red}✘"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${Yellow}${PathShort}${ResetColor}"
GIT_PROMPT_END_USER="${BoldBlue} ➭ ${ResetColor}"
GIT_PROMPT_END_ROOT="${BoldRed} # ${ResetColor}"
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="✭"
}
reload_git_prompt_colors "Single_line_Solarized"

View File

@@ -0,0 +1,48 @@
# This is an alternative approach. Single line in git repo.
# Theme optimised for Terminus and PowerLine compatible fonts.
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# without the indicator of the last command state
# tweaked for Ubuntu terminal fonts
define_helpers() {
YELLOW=$(tput setaf 3)
PathShort="\[$YELLOW\][\A] ${Cyan}\w"
}
override_git_prompt_colors() {
YELLOW=$(tput setaf 3)
ORANGE=$(tput setaf 9)
RED=$(tput setaf 1)
MAGENTA=$(tput setaf 5)
VIOLET=$(tput setaf 13)
BLUE=$(tput setaf 4)
CYAN=$(tput setaf 6)
GREEN=$(tput setaf 2)
BOLD=$(tput bold)
RESET=$(tput sgr0)
GIT_PROMPT_THEME_NAME="Single_line_Solarized_Lamda"
GIT_PROMPT_PREFIX="[ "
GIT_PROMPT_SUFFIX=" ]"
GIT_PROMPT_SEPARATOR=" |"
GIT_PROMPT_STAGED=" ${Yellow}● ${ResetColor}"
GIT_PROMPT_CONFLICTS=" ${Red}✖ ${ResetColor}"
GIT_PROMPT_CHANGED=" ${Blue}✚ ${ResetColor}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_STASHED=" ${BoldMagenta}⚑ ${ResetColor}"
GIT_PROMPT_CLEAN=" ${Green}✔ ${ResetColor}"
GIT_PROMPT_COMMAND_FAIL="${Red}✘"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${Yellow}${PathShort}${ResetColor}"
GIT_PROMPT_END_USER="\[$ORANGE\] λ ${ResetColor}"
GIT_PROMPT_END_ROOT="${BoldRed} # ${ResetColor}"
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="✭"
}
reload_git_prompt_colors "Single_line_Solarized_Lamda"

View File

@@ -0,0 +1,25 @@
# This is an alternative approach. Single line in git repo.
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_Ubuntu"
GIT_PROMPT_PREFIX="[ "
GIT_PROMPT_SUFFIX=" ]"
GIT_PROMPT_SEPARATOR=" |"
GIT_PROMPT_STAGED=" ${Red}● ${ResetColor}"
GIT_PROMPT_CONFLICTS=" ${Red}✖ ${ResetColor}"
GIT_PROMPT_CHANGED=" ${Blue}✚ ${ResetColor}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_STASHED=" ${BoldBlue}⚑ ${ResetColor}"
GIT_PROMPT_CLEAN=" ${BoldGreen}✔ ${ResetColor}"
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_COMMAND_FAIL="${Red}✘ "
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${White}${Time12a}${ResetColor} ${Cyan}${PathShort}${ResetColor}"
GIT_PROMPT_END_USER="${ResetColor} $ "
GIT_PROMPT_END_ROOT="${BoldRed} # "
}
reload_git_prompt_colors "Single_line_Ubuntu"

View File

@@ -0,0 +1,20 @@
# This is a theme for gitprompt.sh,
# it uses the default openSUSE bash prompt style with exit status
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_openSUSE"
GIT_PROMPT_BRANCH="${Cyan}"
GIT_PROMPT_MASTER_BRANCH="${GIT_PROMPT_BRANCH}"
GIT_PROMPT_UNTRACKED=" ${Cyan}…${ResetColor}"
GIT_PROMPT_CHANGED="${Yellow}✚ "
GIT_PROMPT_STAGED="${Magenta}●"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${ResetColor}\u@\h:\w"
GIT_PROMPT_START_ROOT="_LAST_COMMAND_INDICATOR_ ${BoldRed}\h:\w"
GIT_PROMPT_END_USER="${ResetColor}> "
GIT_PROMPT_END_ROOT=" # ${ResetColor}"
}
reload_git_prompt_colors "Single_line_openSUSE"

View File

@@ -0,0 +1,13 @@
# This is an alternative approach. Single line in git repo.
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Single_line_username_repo"
GIT_PROMPT_WITH_USERNAME_AND_REPO=1
GIT_PROMPT_USERNAME_REPO_SEPARATOR=" | "
GIT_PROMPT_PREFIX="[ ${Blue}_USERNAME_REPO_"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${White}${Time12a}${ResetColor} ${BoldYellow}${PathShort}${ResetColor}"
GIT_PROMPT_END_USER="${ResetColor} $ "
GIT_PROMPT_END_ROOT="${BoldRed} # "
}
reload_git_prompt_colors "Single_line_username_repo"

View File

@@ -0,0 +1,13 @@
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# tweaked for Ubuntu terminal fonts
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Solarized"
GIT_PROMPT_STAGED="${Yellow}●"
GIT_PROMPT_STASHED="${BoldMagenta}⚑ "
GIT_PROMPT_CLEAN="${Green}✔"
GIT_PROMPT_END_USER=" \n${BoldBlue}${Time12a}${ResetColor} $ "
GIT_PROMPT_END_ROOT=" \n${BoldBlue}${Time12a}${ResetColor} # "
}
reload_git_prompt_colors "Solarized"

View File

@@ -0,0 +1,41 @@
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# tweaked for Ubuntu terminal fonts
# some modifications on colors
# added ruby prompt, and kernel version as well
override_git_prompt_colors() {
if [ -e ~/.rvm/bin/rvm-prompt ]; then
RUBY_PROMPT='{$(~/.rvm/bin/rvm-prompt i v)}'
else
if command -v rbenv > /dev/null; then
RUBY_PROMPT='{$(rbenv version | sed -e "s/ (set.*$//")}'
fi
fi
Time12a="\$(date +%H:%M:%S)"
GIT_PROMPT_THEME_NAME="Solarized Extravagant"
GIT_PROMPT_STAGED="${Yellow}● "
GIT_PROMPT_UNTRACKED="${Cyan}… "
GIT_PROMPT_STASHED="${BoldMagenta}⚑ "
GIT_PROMPT_CLEAN="${Green}✔ "
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_COMMAND_FAIL="${Red}✘ "
KERNEL_PROMPT='$(uname -r)'
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${BoldBlueFg}${Time12a} ${Green}${KERNEL_PROMPT} ${Cyan}${RUBY_PROMPT} ${Yellow}${PathShort}"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
if [ -n "$SSH_CLIENT" ]; then
GIT_PROMPT_END_USER="\n${BoldRed} ➤ ${ResetColor}"
GIT_PROMPT_END_ROOT="\n${BoldRed} » ${ResetColor}"
else
GIT_PROMPT_END_USER="\n${BoldBlue} ➭ ${ResetColor}"
GIT_PROMPT_END_ROOT="\n${BoldRed} # ${ResetColor}"
fi
GIT_PROMPT_LEADING_SPACE=1
GIT_PROMPT_PREFIX="${Cyan}["
GIT_PROMPT_SUFFIX="${Cyan}]"
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="✭"
}
reload_git_prompt_colors "Solarized Extravagant"

View File

@@ -0,0 +1,16 @@
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# without the indicator of the last command state
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Solarized NoExitState"
GIT_PROMPT_STAGED="${Yellow}●"
GIT_PROMPT_STASHED="${BoldMagenta}⚑ "
GIT_PROMPT_CLEAN="${Green}✔"
GIT_PROMPT_COMMAND_FAIL="${Red}✘"
GIT_PROMPT_START_USER="${Yellow}${PathShort}${ResetColor}"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
GIT_PROMPT_END_USER=" \n${BoldBlue}${Time12a}${ResetColor} $ "
GIT_PROMPT_END_ROOT=" \n${BoldBlue}${Time12a}${ResetColor} # "
}
reload_git_prompt_colors "Solarized NoExitState"

View File

@@ -0,0 +1,18 @@
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# without the indicator of the last command state
# tweaked for Ubuntu terminal fonts
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Solarized NoExitState Ubuntu"
GIT_PROMPT_STAGED="${Yellow}● "
GIT_PROMPT_STASHED="${BoldMagenta}⚑ "
GIT_PROMPT_CLEAN="${Green}✔ "
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_COMMAND_FAIL="${Red}✘ "
GIT_PROMPT_START_USER="${Yellow}${PathShort}${ResetColor}"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
GIT_PROMPT_END_USER=" \n${BoldBlue}${Time12a}${ResetColor} $ "
GIT_PROMPT_END_ROOT=" \n${BoldBlue}${Time12a}${ResetColor} # "
}
reload_git_prompt_colors "Solarized NoExitState Ubuntu"

View File

@@ -0,0 +1,14 @@
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# tweaked for Ubuntu terminal fonts
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Solarized Ubuntu"
GIT_PROMPT_STAGED="${Yellow}● "
GIT_PROMPT_STASHED="${BoldMagenta}⚑ "
GIT_PROMPT_CLEAN="${Green}✔ "
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_END_USER=" \n${BoldBlue}${Time12a}${ResetColor} $ "
GIT_PROMPT_END_ROOT=" \n${BoldBlue}${Time12a}${ResetColor} # "
}
reload_git_prompt_colors "Solarized Ubuntu"

View File

@@ -0,0 +1,23 @@
# This theme for gitprompt.sh is optimized for the "Solarized Dark" and "Solarized Light" color schemes
# based on "Solarized Extravagant", with user@host on the second line and some things removed.
function override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME='Solarized UserHost'
GIT_PROMPT_STAGED="${Yellow}● "
GIT_PROMPT_UNTRACKED="${Cyan}… "
GIT_PROMPT_STASHED="${BoldMagenta}⚑ "
GIT_PROMPT_CLEAN="${Green}✔ "
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_COMMAND_FAIL="${Red}✘ "
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${Yellow}${PathShort}"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
GIT_PROMPT_END_USER="\n${Blue}\\u${White}@${BoldBlue}\\h ${BoldRed} ➤ ${ResetColor} "
GIT_PROMPT_END_ROOT="\n${Blue}\\u${White}@${BoldBlue}\\h ${BoldRed} # ${ResetColor} "
GIT_PROMPT_LEADING_SPACE=1
GIT_PROMPT_PREFIX="${Cyan}["
GIT_PROMPT_SUFFIX="${Cyan}]"
GIT_PROMPT_SYMBOLS_NO_REMOTE_TRACKING="✭"
}
reload_git_prompt_colors 'Solarized UserHost'

View File

@@ -0,0 +1,40 @@
##############################################################################
# Changes the prompt to a Debian-style one that truncates pwd to a max length
# depending on the terminal column width. Also uses the prompt_callback
# function of bash-git-prompt to set the window title to almost the same
# Debian-style.
#
# The prompt will use a Debian-style on the form
#
# [user@host: <truncated PWD>] [bash-git-prompt-info] <exit status>
# HH:MM $
#
# The window title will have the form
# user@host: <truncated PWD>
#
# Example usage:
# if [ -f ~/.bash-git-prompt/gitprompt.sh ]; then
# GIT_PROMPT_THEME=TruncatedPwd_WindowTitle
# source ~/.bash-git-prompt/gitprompt.sh
# fi
#
# oGre <oGre@muppfarmen.se> [https://github.com/ogr3]
##############################################################################
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="TruncatedPwd_WindowTitle"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
local PS1="\u@\h: $(gp_truncate_pwd)"
gp_set_window_title "$PS1"
echo -n "${Yellow}[${PS1}]${ResetColor}"
}
local gp_end=" _LAST_COMMAND_INDICATOR_\n${White}${Time12a}${ResetColor}"
GIT_PROMPT_START_USER=""
GIT_PROMPT_END_USER="${gp_end} $ "
GIT_PROMPT_END_ROOT="${gp_end} # "
}
reload_git_prompt_colors "TruncatedPwd_WindowTitle"

View File

@@ -0,0 +1,40 @@
##############################################################################
# Changes the prompt to a Debian-style one that truncates pwd to a max length
# depending on the terminal column width. Also uses the prompt_callback
# function of bash-git-prompt to set the window title to almost the same
# Debian-style.
#
# The prompt will use a Debian-style on the form
#
# [user@host: <truncated PWD>] [bash-git-prompt-info]
# HH:MM $
#
# The window title will have the form
# user@host: <truncated PWD>
#
# Example usage:
# if [ -f ~/.bash-git-prompt/gitprompt.sh ]; then
# GIT_PROMPT_THEME=TruncatedPwd_WindowTitle_NoExitState
# source ~/.bash-git-prompt/gitprompt.sh
# fi
#
# oGre <oGre@muppfarmen.se> [https://github.com/ogr3]
##############################################################################
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="TruncatedPwd_WindowTitle_NoExitState"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
local PS1="\u@\h: $(gp_truncate_pwd)"
gp_set_window_title "${PS1}"
echo -n "${Yellow}[${PS1}]${ResetColor}"
}
local gp_end=" _LAST_COMMAND_INDICATOR_\n${White}${Time12a}${ResetColor}"
GIT_PROMPT_START_USER=""
GIT_PROMPT_END_USER="${gp_end} $ "
GIT_PROMPT_END_ROOT="${gp_end} # "
}
reload_git_prompt_colors "TruncatedPwd_WindowTitle_NoExitState"

View File

@@ -0,0 +1,46 @@
##############################################################################
# Changes the prompt to a Debian-style one that truncates pwd to a max length
# depending on the terminal column width. Also uses the prompt_callback
# function of bash-git-prompt to set the window title to almost the same
# Debian-style. This version has been tweaked for Ubuntu standard terminal
# fonts.
#
# The prompt will use a Debian-style on the form
#
# [user@host: <truncated PWD>] [bash-git-prompt-info]
# HH:MM $
#
# The window title will have the form
# user@host: <truncated PWD>
#
# Example usage:
# if [ -f ~/.bash-git-prompt/gitprompt.sh ]; then
# GIT_PROMPT_THEME=TruncatedPwd_WindowTitle_NoExitState_Ubuntu
# source ~/.bash-git-prompt/gitprompt.sh
# fi
#
# oGre <oGre@muppfarmen.se> [https://github.com/ogr3]
##############################################################################
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="TruncatedPwd_WindowTitle_NoExitState_Ubuntu"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
local PS1="\u@\h: $(gp_truncate_pwd)"
gp_set_window_title "${PS1}"
echo -n "${Yellow}[${PS1}]${ResetColor}"
}
local gp_end=" _LAST_COMMAND_INDICATOR_\n${White}${Time12a}${ResetColor}"
GIT_PROMPT_START_USER=""
GIT_PROMPT_END_USER="${gp_end} $ "
GIT_PROMPT_END_ROOT="${gp_end} # "
GIT_PROMPT_STAGED="${Red}● " # the number of staged files/directories
GIT_PROMPT_CLEAN="${BoldGreen}✔ " # a colored flag indicating a "clean" repo
GIT_PROMPT_COMMAND_OK="${Green}✔ " # indicator if the last command returned with an exit code of 0
GIT_PROMPT_COMMAND_FAIL="${Red}✘ " # indicator if the last command returned with an exit code of other than 0
}
reload_git_prompt_colors "TruncatedPwd_WindowTitle_NoExitState_Ubuntu"

View File

@@ -0,0 +1,45 @@
##############################################################################
# Changes the prompt to a Debian-style one that truncates pwd to a max length
# depending on the terminal column width. Also uses the prompt_callback
# function of bash-git-prompt to set the window title to almost the same
# Debian-style. This version has been tweaked for Ubuntu standard terminal
# fonts.
#
# The prompt will use a Debian-style on the form
#
# [user@host: <truncated PWD>] [bash-git-prompt-info] <exit status>
# HH:MM $
#
# The window title will have the form
# user@host: <truncated PWD>
#
# Example usage:
# if [ -f ~/.bash-git-prompt/gitprompt.sh ]; then
# GIT_PROMPT_THEME=TruncatedPwd_WindowTitle_Ubuntu
# source ~/.bash-git-prompt/gitprompt.sh
# fi
#
# oGre <oGre@muppfarmen.se> [https://github.com/ogr3]
##############################################################################
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="TruncatedPwd_WindowTitle_Ubuntu"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
local PS1="\u@\h: $(gp_truncate_pwd)"
gp_set_window_title "${PS1}"
echo -n "${Yellow}[${PS1}]${ResetColor}"
}
local gp_end=" _LAST_COMMAND_INDICATOR_\n${White}${Time12a}${ResetColor}"
GIT_PROMPT_START_USER=""
GIT_PROMPT_END_USER="${gp_end} $ "
GIT_PROMPT_END_ROOT="${gp_end} # "
GIT_PROMPT_STAGED="${Red}● " # the number of staged files/directories
GIT_PROMPT_CLEAN="${BoldGreen}✔ " # a colored flag indicating a "clean" repo
GIT_PROMPT_COMMAND_OK="${Green}✔ " # indicator if the last command returned with an exit code of 0
}
reload_git_prompt_colors "TruncatedPwd_WindowTitle_Ubuntu"

View File

@@ -0,0 +1,18 @@
# ~/.bash_profile: executed by bash(1) for login shells.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# the default umask is set in /etc/login.defs
#umask 022
# include .bashrc if it exists
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# set PATH so it includes user's private bin if it exists
if [ -d ~/bin ] ; then
PATH=~/bin:"${PATH}"
fi
export LANG=en_US.UTF-8

View File

@@ -0,0 +1,38 @@
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# ASCII COLORS
red='\[\033[0;31m\]'
RED='\[\033[1;31m\]'
green='\[\033[0;32m\]'
GREEN='\[\033[1;32m\]'
yellow='\[\033[0;33m\]'
YELLOW='\[\033[1;33m\]'
blue='\[\033[0;34m\]'
BLUE='\[\033[1;34m\]'
magenta='\[\033[0;35m\]'
MAGENTA='\[\033[1;35m\]'
cyan='\[\033[0;36m\]'
CYAN='\[\033[1;36m\]'
white='\[\033[0;37m\]'
WHITE='\[\033[1;37m\]'
NC='\[\033[0m\]'
export EDITOR="vim"
# if we use git prompt, override so we get the current PS1 set
# GET: git clone https://github.com/magicmonty/bash-git-prompt.git .bash-git-prompt --depth=1
export GIT_PROMPT_ONLY_IN_REPO=1
export GIT_PROMPT_LEADING_SPACE=0
export GIT_PROMPT_START="[$yellow\t$NC][$GREEN\u$NC@$RED\H$NC:$BLUE\w$NC][$cyan\j$NC]{_LAST_COMMAND_INDICATOR_$ResetColor}"
export GIT_PROMPT_END='\$ '
source ~/.bash-git-prompt/gitprompt.sh

View File

@@ -0,0 +1,41 @@
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
# ASCII COLORS
red='\[\033[0;31m\]'
RED='\[\033[1;31m\]'
green='\[\033[0;32m\]'
GREEN='\[\033[1;32m\]'
yellow='\[\033[0;33m\]'
YELLOW='\[\033[1;33m\]'
blue='\[\033[0;34m\]'
BLUE='\[\033[1;34m\]'
magenta='\[\033[0;35m\]'
MAGENTA='\[\033[1;35m\]'
cyan='\[\033[0;36m\]'
CYAN='\[\033[1;36m\]'
white='\[\033[0;37m\]'
WHITE='\[\033[1;37m\]'
NC='\[\033[0m\]'
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"'
;;
screen*)
PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\033\\"'
;;
*)
;;
esac
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

View File

@@ -0,0 +1,146 @@
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# ASCII COLORS
red='\[\033[0;31m\]'
RED='\[\033[1;31m\]'
green='\[\033[0;32m\]'
GREEN='\[\033[1;32m\]'
yellow='\[\033[0;33m\]'
YELLOW='\[\033[1;33m\]'
blue='\[\033[0;34m\]'
BLUE='\[\033[1;34m\]'
magenta='\[\033[0;35m\]'
MAGENTA='\[\033[1;35m\]'
cyan='\[\033[0;36m\]'
CYAN='\[\033[1;36m\]'
white='\[\033[0;37m\]'
WHITE='\[\033[1;37m\]'
NC='\[\033[0m\]'
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\H\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\H:\w\$ '
fi
unset color_prompt force_color_prompt
# Comment in the above and uncomment this below for a color prompt
#PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\H\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
PS1="[$yellow\t$NC][$GREEN\u$NC@$RED\H$NC:$BLUE\w$NC][$cyan\j$NC]\\$ "
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\H: \w\a\]$PS1"
;;
screen*)
PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\033\\"'
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
#alias ll='ls -l'
#alias la='ls -A'
#alias l='ls -CF'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
export EDITOR="vim"
# if we use git prompt, override so we get the current PS1 set
# GET: git clone https://github.com/magicmonty/bash-git-prompt.git .bash-git-prompt --depth=1
export GIT_PROMPT_ONLY_IN_REPO=1
export GIT_PROMPT_LEADING_SPACE=0
export GIT_PROMPT_START="[$yellow\t$NC][$GREEN\u$NC@$RED\H$NC:$BLUE\w$NC][$cyan\j$NC]{_LAST_COMMAND_INDICATOR_$ResetColor}"
export GIT_PROMPT_END='\$ '
source ~/.bash-git-prompt/gitprompt.sh

View File

@@ -0,0 +1,105 @@
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
# ASCII COLORS
red='\[\033[0;31m\]'
RED='\[\033[1;31m\]'
green='\[\033[0;32m\]'
GREEN='\[\033[1;32m\]'
yellow='\[\033[0;33m\]'
YELLOW='\[\033[1;33m\]'
blue='\[\033[0;34m\]'
BLUE='\[\033[1;34m\]'
magenta='\[\033[0;35m\]'
MAGENTA='\[\033[1;35m\]'
cyan='\[\033[0;36m\]'
CYAN='\[\033[1;36m\]'
white='\[\033[0;37m\]'
WHITE='\[\033[1;37m\]'
NC='\[\033[0m\]'
# don't put duplicate lines in the history. See bash(1) for more options
export HISTCONTROL=ignoredups
export HISTSIZE=10000
shopt -s histappend
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color)
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\H\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
;;
*)
PS1='${debian_chroot:+($debian_chroot)}\u@\H:\w [\j]\$ '
;;
esac
# Comment in the above and uncomment this below for a color prompt
#PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\H\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"'
;;
screen*)
PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\033\\"'
;;
*)
;;
esac
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
#if [ -f ~/.bash_aliases ]; then
# . ~/.bash_aliases
#fi
# enable color support of ls and also add handy aliases
if [ "$TERM" != "dumb" ]; then
eval "`dircolors -b`"
alias ls='ls --color=auto'
#alias dir='ls --color=auto --format=vertical'
#alias vdir='ls --color=auto --format=long'
fi
# some more ls aliases
#alias ll='ls -l'
#alias la='ls -A'
#alias l='ls -CF'
alias lsd="ls -d */"
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
export EDITOR="vim"
# if we use git prompt, override so we get the current PS1 set
# GET: git clone https://github.com/magicmonty/bash-git-prompt.git .bash-git-prompt --depth=1
export GIT_PROMPT_ONLY_IN_REPO=1
export GIT_PROMPT_LEADING_SPACE=0
export GIT_PROMPT_START="[$yellow\t$NC][$GREEN\u$NC@$RED\H$NC:$BLUE\w$NC][$cyan\j$NC]{_LAST_COMMAND_INDICATOR_$ResetColor}"
export GIT_PROMPT_END='\$ '
source ~/.bash-git-prompt/gitprompt.sh

View File

@@ -0,0 +1,149 @@
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# ASCII COLORS
red='\[\033[0;31m\]'
RED='\[\033[1;31m\]'
green='\[\033[0;32m\]'
GREEN='\[\033[1;32m\]'
yellow='\[\033[0;33m\]'
YELLOW='\[\033[1;33m\]'
blue='\[\033[0;34m\]'
BLUE='\[\033[1;34m\]'
magenta='\[\033[0;35m\]'
MAGENTA='\[\033[1;35m\]'
cyan='\[\033[0;36m\]'
CYAN='\[\033[1;36m\]'
white='\[\033[0;37m\]'
WHITE='\[\033[1;37m\]'
NC='\[\033[0m\]'
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\H\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\H:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\H: \w\a\]$PS1"
;;
screen*)
PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\033\\"'
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias lsd="ls -d */"
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
export EDITOR="vim"
# if we use git prompt, override so we get the current PS1 set
# GET: git clone https://github.com/magicmonty/bash-git-prompt.git .bash-git-prompt --depth=1
export GIT_PROMPT_ONLY_IN_REPO=1
export GIT_PROMPT_LEADING_SPACE=0
export GIT_PROMPT_START="[$yellow\t$NC][$GREEN\u$NC@$RED\H$NC:$BLUE\w$NC][$cyan\j$NC]{_LAST_COMMAND_INDICATOR_$ResetColor}"
export GIT_PROMPT_END='\$ '
source ~/.bash-git-prompt/gitprompt.sh

97
home-rc/dot-files/.psqlrc Normal file
View File

@@ -0,0 +1,97 @@
\set HISTFILE ~/.psql_history-:DBNAME
--\set HISTSIZE 5000
--\set FETCH_COUNT 1000
\set HISTCONTROL ignoredups
\set COMP_KEYWORD_CASE upper
\set ON_ERROR_STOP on
\set ON_ERROR_ROLLBACK interactive
\set VERBOSITY verbose
\set version 'SELECT version();'
\set extensions 'select * from pg_available_extensions;'
\timing
-- alt char ¤
--\set null NULL
--\pset null 'Ø'
\pset null '∅'
-- set line type ascii or unicde
--\pset linestyle unicode
\pset linestyle ascii
-- from 0-2--
\pset border 1
-- turn off pager (more like)
--\pset pager off
-- wrap long lines
\set format wrapped
\setenv PAGER 'pspg -bX --no-mouse'
-- PROMPT
-- [ USER (%n) @ DATABASE (%/) % HOST(full) (%M) : PORT (%>) ] { :ENCODING: } [transaction %x (4)] PROMPT %R SUPERUSER %#
-- * one line color
--\set PROMPT1 '[%[%033[1;32m%]%n%[%033[0m%]@%[%033[1;35m%]%/%[%033[0m%]%%%[%033[1;31m%]%M%[%033[0m%]:%[%033[1;33m%]%>%[%033[0m%]]{%[%033[0;36m%]%:ENCODING:%[%033[0m%]}%x%x%x%R%# '
--\set PROMPT2 '(%[%033[1;35m%]%/%[%033[0m%])%x%x%x%[%033[1;36m%]%R%[%033[0m%]%# '
-- * two line color
\set PROMPT1 '[%[%033[1;32m%]%n%[%033[0m%]@%[%033[1;35m%]%/%[%033[0m%]%%%[%033[1;31m%]%M%[%033[0m%]:%[%033[1;33m%]%>%[%033[0m%]]{%[%033[0;36m%]%:ENCODING:%[%033[0m%]}\n%x%x%x%[%033[1;34m%]%R%[%033[0m%]%# '
\set PROMPT2 '%x%x%x%[%033[1;36m%]%R%[%033[0m%]%# '
-- * one line no color
--\set PROMPT1 '[%n@%/%%%M:%>]{%:ENCODING:}%x%x%x%R%# '
-- switch linestyle
\set la '\\pset linestyle ascii'
\set lu '\\pset linestyle unicode'
-- switch pagers
\set x '\\setenv PAGER less'
\set xx '\\setenv PAGER \'pspg -bX --no-mouse\''
-- like tsize below, but without converting data into bytes
\set rtsize '(select table_schema, table_name, pg_relation_size( quote_ident( table_schema ) || \'.\' || quote_ident( table_name ) ) as size, pg_indexes_size( quote_ident( table_schema ) || \'.\' || quote_ident( table_name ) ) as index_size, pg_total_relation_size( quote_ident( table_schema ) || \'.\' || quote_ident( table_name ) ) as total_size from information_schema.tables where table_type = \'BASE TABLE\' and table_schema not in (\'information_schema\', \'pg_catalog\') order by pg_relation_size( quote_ident( table_schema ) || \'.\' || quote_ident( table_name ) ) desc, table_schema, table_name)'
-- compact size output for tables + indexes
\set tsize '(select table_schema, table_name, pg_size_pretty(size) as size, pg_size_pretty(index_size) as index_size, pg_size_pretty(total_size) as total_size from (:rtsize) x order by x.size desc, x.total_size desc, table_schema, table_name)'
-- extended size output for tables and indexes
\set etsize 'SELECT pgn.nspname, relname, pg_size_pretty(relpages::bigint * 8 * 1024) AS size, CASE WHEN relkind = \'t\' THEN (SELECT pgd.relname FROM pg_class pgd WHERE pgd.reltoastrelid = pg.oid) WHEN nspname = \'pg_toast\' AND relkind = \'i\' THEN (SELECT pgt.relname FROM pg_class pgt WHERE SUBSTRING(pgt.relname FROM 10) = REPLACE(SUBSTRING(pg.relname FROM 10), \'_index\', \'\')) ELSE (SELECT pgc.relname FROM pg_class pgc WHERE pg.reltoastrelid = pgc.oid) END::varchar AS refrelname, CASE WHEN nspname = \'pg_toast\' AND relkind = \'i\' THEN (SELECT pgts.relname FROM pg_class pgts WHERE pgts.reltoastrelid = (SELECT pgt.oid FROM pg_class pgt WHERE SUBSTRING(pgt.relname FROM 10) = REPLACE(SUBSTRING(pg.relname FROM 10), \'_index\', \'\'))) END AS relidxrefrelname, relfilenode, relkind, reltuples::bigint, relpages FROM pg_class pg, pg_namespace pgn WHERE pg.relnamespace = pgn.oid AND pgn.nspname NOT IN (\'information_schema\', \'pg_catalog\') ORDER BY relpages DESC'
-- get useless indexes
\set trashindexes '( select s.schemaname as sch, s.relname as rel, s.indexrelname as idx, s.idx_scan as scans, pg_size_pretty(pg_relation_size(s.relid)) as ts, pg_size_pretty(pg_relation_size(s.indexrelid)) as "is" from pg_stat_user_indexes s join pg_index i on i.indexrelid=s.indexrelid left join pg_constraint c on i.indrelid=c.conrelid and array_to_string(i.indkey, '' '') = array_to_string(c.conkey, '' '') where i.indisunique is false and pg_relation_size(s.relid) > 1000000 and s.idx_scan < 100000 and c.confrelid is null order by s.idx_scan asc, pg_relation_size(s.indexrelid) desc, pg_relation_size(s.relid) desc )'
-- get useless indexes (full read)
\set trashindexesall '( select s.schemaname as sch, s.relname as rel, s.indexrelname as idx, s.idx_scan as scans, pg_size_pretty(pg_relation_size(s.relid)) as ts, pg_size_pretty(pg_relation_size(s.indexrelid)) as "is", c.confrelid, c.conkey from pg_stat_user_indexes s join pg_index i on i.indexrelid=s.indexrelid left join pg_constraint c on i.indrelid=c.conrelid and array_to_string(i.indkey, '' '') = array_to_string(c.conkey, '' '') where i.indisunique is false and pg_relation_size(s.relid) > 1000000 and s.idx_scan < 100000 order by s.idx_scan asc, pg_relation_size(s.indexrelid) desc, pg_relation_size(s.relid) desc )'
-- get all indexes for a relation ('table')
\set getindexes 'select s.schemaname as sch, s.relname as rel, s.indexrelname as idx, s.idx_scan as scans, pg_size_pretty(pg_relation_size(s.relid)) as ts, pg_size_pretty(pg_relation_size(s.indexrelid)) as "is", c.confrelid, c.conkey from pg_stat_user_indexes s join pg_index i on i.indexrelid=s.indexrelid left join pg_constraint c on i.indrelid=c.conrelid and array_to_string(i.indkey, '' '') = array_to_string(c.conkey, '' '') where s.relname = '
-- possible missing indexes
\set missingindexes '( select src_table, dst_table, fk_name, pg_size_pretty(s_size) as s_size, pg_size_pretty(d_size) as d_size, d from ( select distinct on (1,2,3,4,5) textin(regclassout(c.conrelid)) as src_table, textin(regclassout(c.confrelid)) as dst_table, c.conname as fk_name, pg_relation_size(c.conrelid) as s_size, pg_relation_size(c.confrelid) as d_size, array_upper(di.indkey::int[], 1) + 1 - array_upper(c.conkey::int[], 1) as d from pg_constraint c left join pg_index di on di.indrelid = c.conrelid and array_to_string(di.indkey, '' '') ~ (''^'' || array_to_string(c.conkey, '' '') || ''( |$)'') join pg_stat_user_tables st on st.relid = c.conrelid where c.contype = ''f'' order by 1,2,3,4,5,6 asc) mfk where mfk.d is distinct from 0 and mfk.s_size > 1000000 order by mfk.s_size desc, mfk.d desc )'
-- overal percentage of index hits for a table
\set percentindexes 'SELECT relname, 100 * idx_scan / (seq_scan + idx_scan) percent_of_times_index_used, n_live_tup rows_in_table FROM pg_stat_user_tables ORDER BY n_live_tup DESC'
-- current running queries
\set running 'SELECT datname, client_addr, pid, now() - query_start AS runtime, state, wait_event_type, wait_event, query FROM pg_stat_activity WHERE query <> ''<IDLE>'' AND state <> ''idle'' ORDER BY 1, 5, 4 DESC;'
\set runningidle 'SELECT datname, client_addr, pid, now() - query_start AS runtime, state, wait_event_type, wait_event, query FROM pg_stat_activity WHERE query <> ''<IDLE>'' ORDER BY 1, 5, 4 DESC;'
\set runningold 'SELECT datname, client_addr, pid, now() - query_start AS runtime, state, case when waiting then ''WAIT'' else '''' end AS wait, query FROM pg_stat_activity WHERE query <> ''<IDLE>'' AND state <> ''idle'' ORDER BY 1, 5, 4 DESC;'
\set runningidleold 'SELECT datname, client_addr, pid, now() - query_start AS runtime, state, case when waiting then ''WAIT'' else '''' end AS wait, query FROM pg_stat_activity WHERE query <> ''<IDLE>'' ORDER BY 1, 5, 4 DESC;'
-- misses primary key
\set missingpk 'SELECT table_catalog, table_schema, table_name FROM information_schema.tables WHERE (table_catalog, table_schema, table_name) NOT IN (SELECT table_catalog, table_schema, table_name FROM information_schema.table_constraints WHERE constraint_type = ''PRIMARY KEY'') AND table_schema NOT IN (''information_schema'', ''pg_catalog'')'
-- chance of hitting the cache
\set cachehit 'SELECT sum(heap_blks_read) as heap_read, sum(heap_blks_hit) as heap_hit, (sum(heap_blks_hit) - sum(heap_blks_read)) / sum(heap_blks_hit) as ratio;'
-- chance of hitting the index during a read
\set indexhit 'SELECT sum(idx_blks_read) as idx_read, sum(idx_blks_hit) as idx_hit, (sum(idx_blks_hit) - sum(idx_blks_read)) / sum(idx_blks_hit) as ratio FROM pg_statio_user_indexes;'
-- show slow queries
\set show_slow_queries 'SELECT (total_time / 1000 / 60) as total_minutes, (total_time/calls) as average_time, query FROM pg_stat_statements ORDER BY 1 DESC LIMIT 100;'
-- show current search path
\set shsp 'SHOW search_path;'
-- set new search path
\set setsp 'SET search_path TO'
-- INDEX BLOAT read
\set indexbloat 'WITH btree_index_atts AS ( SELECT nspname, relname, reltuples, relpages, indrelid, relam, regexp_split_to_table(indkey::text, '' '')::smallint AS attnum, indexrelid as index_oid FROM pg_index JOIN pg_class ON pg_class.oid=pg_index.indexrelid JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace JOIN pg_am ON pg_class.relam = pg_am.oid WHERE pg_am.amname = ''btree''), index_item_sizes AS ( SELECT i.nspname, i.relname, i.reltuples, i.relpages, i.relam, (quote_ident(s.schemaname) || ''.'' || quote_ident(s.tablename))::regclass AS starelid, a.attrelid AS table_oid, index_oid, current_setting(''block_size'')::numeric AS bs, CASE WHEN version() ~ ''mingw32'' OR version() ~ ''64-bit'' THEN 8 ELSE 4 END AS maxalign, 24 AS pagehdr, CASE WHEN max(coalesce(s.null_frac,0)) = 0 THEN 2 ELSE 6 END AS index_tuple_hdr, sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 2048) ) AS nulldatawidth FROM pg_attribute AS a JOIN pg_stats AS s ON (quote_ident(s.schemaname) || ''.'' || quote_ident(s.tablename))::regclass=a.attrelid AND s.attname = a.attname JOIN btree_index_atts AS i ON i.indrelid = a.attrelid AND a.attnum = i.attnum WHERE a.attnum > 0 GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9), index_aligned AS ( SELECT maxalign, bs, nspname, relname AS index_name, reltuples, relpages, relam, table_oid, index_oid, ( 2 + maxalign - CASE WHEN 2%maxalign = 0 THEN maxalign ELSE 2%maxalign END + nulldatawidth + maxalign - CASE WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign ELSE nulldatawidth::integer%maxalign END)::numeric AS nulldatahdrwidth, pagehdr FROM index_item_sizes AS s1), otta_calc AS ( SELECT bs, nspname, table_oid, index_oid, index_name, relpages, coalesce( ceil((reltuples*(4+nulldatahdrwidth))/(bs-pagehdr::float)) + CASE WHEN am.amname IN (''hash'',''btree'') THEN 1 ELSE 0 END , 0 ) AS otta FROM index_aligned AS s2 LEFT JOIN pg_am am ON s2.relam = am.oid), raw_bloat AS ( SELECT current_database() as dbname, nspname, c.relname AS table_name, index_name, bs*(sub.relpages)::bigint AS totalbytes, CASE WHEN sub.relpages <= otta THEN 0 ELSE bs*(sub.relpages-otta)::bigint END AS wastedbytes, CASE WHEN sub.relpages <= otta THEN 0 ELSE bs*(sub.relpages-otta)::bigint * 100 / (bs*(sub.relpages)::bigint) END AS realbloat, pg_relation_size(sub.table_oid) as table_bytes, stat.idx_scan as index_scans FROM otta_calc AS sub JOIN pg_class AS c ON c.oid=sub.table_oid JOIN pg_stat_user_indexes AS stat ON sub.index_oid = stat.indexrelid) SELECT dbname as database_name, nspname as schema_name, table_name, index_name, round(realbloat, 1) as bloat_pct, wastedbytes as bloat_bytes, pg_size_pretty(wastedbytes) as bloat_size, totalbytes as index_bytes, pg_size_pretty(totalbytes) as index_size, table_bytes, pg_size_pretty(table_bytes) as table_size, index_scans FROM raw_bloat WHERE ( ( realbloat > 50 and wastedbytes > 50000000 ) or wastedbytes > 50000000 ) ORDER BY wastedbytes DESC;'
-- never used index check
\set indexusage 'WITH table_scans as (SELECT relid, tables.idx_scan + tables.seq_scan as all_scans, ( tables.n_tup_ins + tables.n_tup_upd + tables.n_tup_del ) as writes, pg_relation_size(relid) as table_size FROM pg_stat_user_tables as tables), all_writes as (SELECT sum(writes) as total_writes FROM table_scans), indexes as (SELECT idx_stat.relid, idx_stat.indexrelid, idx_stat.schemaname, idx_stat.relname as tablename, idx_stat.indexrelname as indexname, idx_stat.idx_scan, pg_relation_size(idx_stat.indexrelid) as index_bytes, indexdef ~* ''USING btree'' AS idx_is_btree FROM pg_stat_user_indexes as idx_stat JOIN pg_index USING (indexrelid) JOIN pg_indexes as indexes ON idx_stat.schemaname = indexes.schemaname AND idx_stat.relname = indexes.tablename AND idx_stat.indexrelname = indexes.indexname WHERE pg_index.indisunique = FALSE), index_ratios AS (SELECT schemaname, tablename, indexname, idx_scan, all_scans, round(( CASE WHEN all_scans = 0 THEN 0.0::NUMERIC ELSE idx_scan::NUMERIC/all_scans * 100 END),2) as index_scan_pct, writes, round((CASE WHEN writes = 0 THEN idx_scan::NUMERIC ELSE idx_scan::NUMERIC/writes END),2) as scans_per_write, pg_size_pretty(index_bytes) as index_size, pg_size_pretty(table_size) as table_size, idx_is_btree, index_bytes FROM indexes JOIN table_scans USING (relid)), index_groups AS (SELECT ''Never Used Indexes'' as reason, *, 1 as grp FROM index_ratios WHERE idx_scan = 0 and idx_is_btree UNION ALL SELECT ''Low Scans, High Writes'' as reason, *, 2 as grp FROM index_ratios WHERE scans_per_write <= 1 and index_scan_pct < 10 and idx_scan > 0 and writes > 100 and idx_is_btree UNION ALL SELECT ''Seldom Used Large Indexes'' as reason, *, 3 as grp FROM index_ratios WHERE index_scan_pct < 5 and scans_per_write > 1 and idx_scan > 0 and idx_is_btree and index_bytes > 100000000 UNION ALL SELECT ''High-Write Large Non-Btree'' as reason, index_ratios.*, 4 as grp FROM index_ratios, all_writes WHERE ( writes::NUMERIC / ( total_writes + 1 ) ) > 0.02 AND NOT idx_is_btree AND index_bytes > 100000000 ORDER BY grp, index_bytes DESC ) SELECT reason, schemaname, tablename, indexname, index_scan_pct, scans_per_write, index_size, table_size FROM index_groups;'
-- foreign key count for all tables in database
\set foreignkeycount 'SELECT t.oid::regclass::text AS table_name, count(1) AS total FROM pg_constraint c JOIN pg_class t ON (t.oid = c.confrelid) GROUP BY table_name ORDER BY total DESC;'
-- ALSO from view 'bloat': SELECT * from bloat
-- bloat for tables and indexes
\set tablebloat 'SELECT sml.schemaname, sml.tablename, sml.reltuples::bigint AS reltuples, sml.relpages::bigint AS relpages, sml.otta, round( CASE WHEN sml.otta = 0::double precision THEN 0.0 ELSE sml.relpages::numeric / sml.otta::numeric END, 1) AS tbloat, sml.relpages::bigint::double precision - sml.otta AS wastedpages, sml.bs * (sml.relpages::double precision - sml.otta)::bigint::numeric AS wastedbytes, pg_size_pretty((sml.bs::double precision * (sml.relpages::double precision - sml.otta))::bigint) AS wastedsize, sml.iname, sml.ituples::bigint AS ituples, sml.ipages::bigint AS ipages, sml.iotta, round( CASE WHEN sml.iotta = 0::double precision OR sml.ipages = 0 THEN 0.0 ELSE sml.ipages::numeric / sml.iotta::numeric END, 1) AS ibloat, CASE WHEN sml.ipages::double precision < sml.iotta THEN 0::double precision ELSE sml.ipages::bigint::double precision - sml.iotta END AS wastedipages, CASE WHEN sml.ipages::double precision < sml.iotta THEN 0::double precision ELSE sml.bs::double precision * (sml.ipages::double precision - sml.iotta) END AS wastedibytes, CASE WHEN sml.ipages::double precision < sml.iotta THEN pg_size_pretty(0::bigint) ELSE pg_size_pretty((sml.bs::double precision * (sml.ipages::double precision - sml.iotta))::bigint) END AS wastedisize FROM ( SELECT rs.schemaname, rs.tablename, cc.reltuples, cc.relpages, rs.bs, ceil(cc.reltuples * ((rs.datahdr + rs.ma::numeric - CASE WHEN (rs.datahdr % rs.ma::numeric) = 0::numeric THEN rs.ma::numeric ELSE rs.datahdr % rs.ma::numeric END)::double precision + rs.nullhdr2 + 4::double precision) / (rs.bs::double precision - 20::double precision)) AS otta, COALESCE(c2.relname, ''?''::name) AS iname, COALESCE(c2.reltuples, 0::real) AS ituples, COALESCE(c2.relpages, 0) AS ipages, COALESCE(ceil(c2.reltuples * (rs.datahdr - 12::numeric)::double precision / (rs.bs::double precision - 20::double precision)), 0::double precision) AS iotta FROM ( SELECT foo.ma, foo.bs, foo.schemaname, foo.tablename, (foo.datawidth + (foo.hdr + foo.ma - CASE WHEN (foo.hdr % foo.ma) = 0 THEN foo.ma ELSE foo.hdr % foo.ma END)::double precision)::numeric AS datahdr, foo.maxfracsum * (foo.nullhdr + foo.ma - CASE WHEN (foo.nullhdr % foo.ma::bigint) = 0 THEN foo.ma::bigint ELSE foo.nullhdr % foo.ma::bigint END)::double precision AS nullhdr2 FROM ( SELECT s.schemaname, s.tablename, constants.hdr, constants.ma, constants.bs, sum((1::double precision - s.null_frac) * s.avg_width::double precision) AS datawidth, max(s.null_frac) AS maxfracsum, constants.hdr + (( SELECT 1 + count(*) / 8 FROM pg_stats s2 WHERE s2.null_frac <> 0::double precision AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename)) AS nullhdr FROM pg_stats s, ( SELECT ( SELECT current_setting(''block_size''::text)::numeric AS current_setting) AS bs, CASE WHEN "substring"(foo_1.v, 12, 3) = ANY (ARRAY[''8.0''::text, ''8.1''::text, ''8.2''::text]) THEN 27 ELSE 23 END AS hdr, CASE WHEN foo_1.v ~ ''mingw32''::text THEN 8 ELSE 4 END AS ma FROM ( SELECT version() AS v) foo_1) constants GROUP BY s.schemaname, s.tablename, constants.hdr, constants.ma, constants.bs) foo) rs JOIN pg_class cc ON cc.relname = rs.tablename JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = rs.schemaname LEFT JOIN pg_index i ON i.indrelid = cc.oid LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid) sml WHERE (sml.relpages::double precision - sml.otta) > 0::double precision OR (sml.ipages::double precision - sml.iotta) > 10::double precision ORDER BY sml.bs * (sml.relpages::double precision - sml.otta)::bigint::numeric DESC, CASE WHEN sml.ipages::double precision < sml.iotta THEN 0::double precision ELSE sml.bs::double precision * (sml.ipages::double precision - sml.iotta) END DESC;'
-- view locks
\set viewlockedquery 'SELECT COALESCE(blockingl.relation::regclass::text,blockingl.locktype) as locked_item, now() - blockeda.query_start AS waiting_duration, blockeda.pid AS blocked_pid, blockeda.query as blocked_query, blockedl.mode as blocked_mode, blockinga.pid AS blocking_pid, blockinga.query as blocking_query, blockingl.mode as blocking_mode FROM pg_catalog.pg_locks blockedl JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid JOIN pg_catalog.pg_locks blockingl ON( ( (blockingl.transactionid=blockedl.transactionid) OR (blockingl.relation=blockedl.relation AND blockingl.locktype=blockedl.locktype)) AND blockedl.pid != blockingl.pid) JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid AND blockinga.datid = blockeda.datid WHERE NOT blockedl.granted AND blockinga.datname = current_database();'
\set viewlocks 'select (SELECT datname FROM pg_stat_database WHERE datid = database) AS database, pid, locktype, relation::regclass AS relation, mode, virtualxid AS vtid, transactionid AS tid, classid, objid, objsubid, virtualtransaction AS vtrans, granted, fastpath FROM pg_locks ORDER BY pid;'
-- tables that need vacuum
\set vacuumneed 'WITH table_opts AS ( SELECT c.oid, c.relname, c.relfrozenxid, c.relminmxid, n.nspname, array_to_string(c.reloptions, '''') AS relopts FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind IN (''r'', ''t'') AND n.nspname NOT IN (''pg_catalog'', ''information_schema'') AND n.nspname !~ ''^pg_temp''), vacuum_settings AS ( SELECT oid, relname, nspname, relfrozenxid, relminmxid, CASE WHEN relopts LIKE ''%autovacuum_vacuum_threshold%'' THEN regexp_replace(relopts, ''.*autovacuum_vacuum_threshold=([0-9.]+).*'', E''\\1'')::integer ELSE current_setting(''autovacuum_vacuum_threshold'')::integer END AS autovacuum_vacuum_threshold, CASE WHEN relopts LIKE ''%autovacuum_vacuum_scale_factor%'' THEN regexp_replace(relopts, ''.*autovacuum_vacuum_scale_factor=([0-9.]+).*'', E''\\1'')::real ELSE current_setting(''autovacuum_vacuum_scale_factor'')::real END AS autovacuum_vacuum_scale_factor, CASE WHEN relopts LIKE ''%autovacuum_analyze_threshold%'' THEN regexp_replace(relopts, ''.*autovacuum_analyze_threshold=([0-9.]+).*'', E''\\1'')::integer ELSE current_setting(''autovacuum_analyze_threshold'')::integer END AS autovacuum_analyze_threshold, CASE WHEN relopts LIKE ''%autovacuum_analyze_scale_factor%'' THEN regexp_replace(relopts, ''.*autovacuum_analyze_scale_factor=([0-9.]+).*'', E''\\1'')::real ELSE current_setting(''autovacuum_analyze_scale_factor'')::real END AS autovacuum_analyze_scale_factor, CASE WHEN relopts LIKE ''%autovacuum_freeze_max_age%'' THEN least(regexp_replace(relopts, ''.*autovacuum_freeze_max_age=([0-9.]+).*'', E''\\1'')::bigint,current_setting(''autovacuum_freeze_max_age'')::bigint) ELSE current_setting(''autovacuum_freeze_max_age'')::bigint END AS autovacuum_freeze_max_age, CASE WHEN relopts LIKE ''%autovacuum_multixact_freeze_max_age%'' THEN least(regexp_replace(relopts, ''.*autovacuum_multixact_freeze_max_age=([0-9.]+).*'', E''\\1'')::bigint,current_setting(''autovacuum_multixact_freeze_max_age'')::bigint) ELSE current_setting(''autovacuum_multixact_freeze_max_age'')::bigint END AS autovacuum_multixact_freeze_max_age FROM table_opts) SELECT s.schemaname ||''.''|| s.relname, CASE WHEN v.autovacuum_vacuum_threshold + (v.autovacuum_vacuum_scale_factor::numeric * c.reltuples) < s.n_dead_tup THEN true ELSE false END AS need_vacuum, CASE WHEN v.autovacuum_analyze_threshold + (v.autovacuum_analyze_scale_factor::numeric * c.reltuples) < s.n_mod_since_analyze THEN true ELSE false END AS need_analyze, CASE WHEN (age(v.relfrozenxid)::bigint > v.autovacuum_freeze_max_age) OR (mxid_age(v.relminmxid)::bigint > v.autovacuum_multixact_freeze_max_age) THEN true ELSE false END AS need_wraparound FROM pg_stat_user_tables s INNER JOIN pg_class c ON s.relid = c.oid INNER JOIN vacuum_settings v ON c.oid = v.oid WHERE (v.autovacuum_vacuum_threshold + (v.autovacuum_vacuum_scale_factor::numeric * c.reltuples) < s.n_dead_tup) OR (v.autovacuum_analyze_threshold + (v.autovacuum_analyze_scale_factor::numeric * c.reltuples) < s.n_mod_since_analyze) OR (age(v.relfrozenxid)::bigint > v.autovacuum_freeze_max_age) OR (mxid_age(v.relminmxid)::bigint > v.autovacuum_multixact_freeze_max_age)'
\set tablebloatscan 'WITH constants AS (SELECT current_setting(''block_size'')::numeric AS bs, 23 AS hdr, 8 AS ma), no_stats AS (SELECT table_schema, table_name, n_live_tup::numeric as est_rows, pg_table_size(relid)::numeric as table_size FROM information_schema.columns JOIN pg_stat_user_tables as psut ON table_schema = psut.schemaname AND table_name = psut.relname LEFT OUTER JOIN pg_stats ON table_schema = pg_stats.schemaname AND table_name = pg_stats.tablename AND column_name = attname WHERE attname IS NULL AND table_schema NOT IN (''pg_catalog'', ''information_schema'') GROUP BY table_schema, table_name, relid, n_live_tup), null_headers AS (SELECT hdr+1+(sum(case when null_frac <> 0 THEN 1 else 0 END)/8) as nullhdr, SUM((1-null_frac)*avg_width) as datawidth, MAX(null_frac) as maxfracsum, schemaname, tablename, hdr, ma, bs FROM pg_stats CROSS JOIN constants LEFT OUTER JOIN no_stats ON schemaname = no_stats.table_schema AND tablename = no_stats.table_name WHERE schemaname NOT IN (''pg_catalog'', ''information_schema'') AND no_stats.table_name IS NULL AND EXISTS ( SELECT 1 FROM information_schema.columns WHERE schemaname = columns.table_schema AND tablename = columns.table_name ) GROUP BY schemaname, tablename, hdr, ma, bs), data_headers AS (SELECT ma, bs, hdr, schemaname, tablename, (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr, (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2 FROM null_headers), table_estimates AS (SELECT schemaname, tablename, bs, reltuples::numeric as est_rows, relpages * bs as table_bytes, CEIL((reltuples*(datahdr + nullhdr2 + 4 + ma - (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))/(bs-20))) * bs AS expected_bytes, reltoastrelid FROM data_headers JOIN pg_class ON tablename = relname JOIN pg_namespace ON relnamespace = pg_namespace.oid AND schemaname = nspname WHERE pg_class.relkind = ''r''), estimates_with_toast AS (SELECT schemaname, tablename, TRUE as can_estimate, est_rows, table_bytes + ( coalesce(toast.relpages, 0) * bs ) as table_bytes, expected_bytes + ( ceil( coalesce(toast.reltuples, 0) / 4 ) * bs ) as expected_bytes FROM table_estimates LEFT OUTER JOIN pg_class as toast ON table_estimates.reltoastrelid = toast.oid AND toast.relkind = ''t''), table_estimates_plus AS (SELECT current_database() as databasename, schemaname, tablename, can_estimate, est_rows, CASE WHEN table_bytes > 0 THEN table_bytes::NUMERIC ELSE NULL::NUMERIC END AS table_bytes, CASE WHEN expected_bytes > 0 THEN expected_bytes::NUMERIC ELSE NULL::NUMERIC END AS expected_bytes, CASE WHEN expected_bytes > 0 AND table_bytes > 0 AND expected_bytes <= table_bytes THEN (table_bytes - expected_bytes)::NUMERIC ELSE 0::NUMERIC END AS bloat_bytes FROM estimates_with_toast UNION ALL SELECT current_database() as databasename, table_schema, table_name, FALSE, est_rows, table_size, NULL::NUMERIC, NULL::NUMERIC FROM no_stats), bloat_data AS (select current_database() as databasename, schemaname, tablename, can_estimate, table_bytes, round(table_bytes/(1024^2)::NUMERIC,3) as table_mb, expected_bytes, round(expected_bytes/(1024^2)::NUMERIC,3) as expected_mb, round(bloat_bytes*100/table_bytes) as pct_bloat, round(bloat_bytes/(1024::NUMERIC^2),2) as mb_bloat, table_bytes, expected_bytes, est_rows FROM table_estimates_plus) SELECT databasename, schemaname, tablename, can_estimate, est_rows, pct_bloat, mb_bloat, table_mb FROM bloat_data WHERE ( pct_bloat >= 50 AND mb_bloat >= 20 ) OR ( pct_bloat >= 25 AND mb_bloat >= 1000 ) ORDER BY pct_bloat DESC;'
-- current vacuum status
\set vacuumstatus 'SELECT p.pid, now() - a.xact_start AS duration, coalesce(wait_event_type ||''.''|| wait_event, ''f'') AS waiting, CASE WHEN a.query ~ ''^autovacuum.*to prevent wraparound'' THEN ''wraparound'' WHEN a.query ~ ''^vacuum'' THEN ''user'' ELSE ''regular'' END AS mode, p.datname AS database, p.relid::regclass AS table, p.phase, pg_size_pretty(p.heap_blks_total * current_setting(''block_size'')::int) AS table_size, pg_size_pretty(pg_total_relation_size(relid)) AS total_size, pg_size_pretty(p.heap_blks_scanned * current_setting(''block_size'')::int) AS scanned, pg_size_pretty(p.heap_blks_vacuumed * current_setting(''block_size'')::int) AS vacuumed, round(100.0 * p.heap_blks_scanned / p.heap_blks_total, 1) AS scanned_pct, round(100.0 * p.heap_blks_vacuumed / p.heap_blks_total, 1) AS vacuumed_pct, p.index_vacuum_count, round(100.0 * p.num_dead_tuples / p.max_dead_tuples,1) AS dead_pct FROM pg_stat_progress_vacuum p JOIN pg_stat_activity a using (pid) ORDER BY now() - a.xact_start DESC;'

View File

@@ -0,0 +1,42 @@
# enable scrollback, does not work in konsole
defscrollback 50000
# hardstatus line at the bottom
hardstatus alwayslastline "%{.kw}[%{..g}%H%{..w}] [%{..M}%S%{..w}:%{..m}%n %{..M}%t%{..w}] [%{..W}%h%{..w}]%= %{..w}[%{..r}%l%{..w}][%{..y}%D, %y/%m/%d %{..Y}%c:%s%{..w}]"
# hardstatus if we have a split layout
caption splitonly "%{rw}%n%f %t %{wk} | %>%{wk}%?%-Lw%?[%{..M}%n*%f %t%{.kw}]%?(%u)%?%{wk}%?%+Lw%?%<"
# "~" stands for the "bell" character
# use %n to display the window number and %t for its title:
activity "activity in %f%n (%t) [%c:%s]~"
# pass on the "beep" (CTRL-G) by adding a '~':
bell "bell in %f%n (%t) [%c:%s]~"
# vbell_msg: Message shown when the
# "virtual bell" rings.
vbell_msg " *beep* "
# to be able to select screens n > 9 ->
# press "C-a - #" instead of just "C-a #"
bind - command -c select_1n
bind -c select_1n 0 select 10
bind -c select_1n 1 select 11
bind -c select_1n 2 select 12
bind -c select_1n 3 select 13
bind -c select_1n 4 select 14
bind -c select_1n 5 select 15
bind -c select_1n 6 select 16
bind -c select_1n 7 select 17
bind -c select_1n 8 select 18
bind -c select_1n 9 select 19
bind -c select_1n - command -c select_2n
bind -c select_2n 0 select 20
bind -c select_2n 1 select 21
bind -c select_2n 2 select 22
bind -c select_2n 3 select 23
bind -c select_2n 4 select 24
bind -c select_2n 5 select 25
bind -c select_2n 6 select 26
bind -c select_2n 7 select 27
bind -c select_2n 8 select 28
bind -c select_2n 9 select 29
bind -c select_2n - select -

View File

@@ -0,0 +1,4 @@
let g:netrw_dirhistmax =10
let g:netrw_dirhist_cnt =2
let g:netrw_dirhist_1='/storage/var/www/html/developers/clemens/php/php-diff-master/lib/Diff'
let g:netrw_dirhist_2='/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/www/configs'

View File

@@ -0,0 +1,264 @@
" pathogen.vim - path option manipulation
" Maintainer: Tim Pope <http://tpo.pe/>
" Version: 2.4
" Install in ~/.vim/autoload (or ~\vimfiles\autoload).
"
" For management of individually installed plugins in ~/.vim/bundle (or
" ~\vimfiles\bundle), adding `execute pathogen#infect()` to the top of your
" .vimrc is the only other setup necessary.
"
" The API is documented inline below.
if exists("g:loaded_pathogen") || &cp
finish
endif
let g:loaded_pathogen = 1
" Point of entry for basic default usage. Give a relative path to invoke
" pathogen#interpose() or an absolute path to invoke pathogen#surround().
" Curly braces are expanded with pathogen#expand(): "bundle/{}" finds all
" subdirectories inside "bundle" inside all directories in the runtime path.
" If no arguments are given, defaults "bundle/{}", and also "pack/{}/start/{}"
" on versions of Vim without native package support.
function! pathogen#infect(...) abort
if a:0
let paths = filter(reverse(copy(a:000)), 'type(v:val) == type("")')
else
let paths = ['bundle/{}', 'pack/{}/start/{}']
endif
if has('packages')
call filter(paths, 'v:val !~# "^pack/[^/]*/start/[^/]*$"')
endif
let static = '^\%([$~\\/]\|\w:[\\/]\)[^{}*]*$'
for path in filter(copy(paths), 'v:val =~# static')
call pathogen#surround(path)
endfor
for path in filter(copy(paths), 'v:val !~# static')
if path =~# '^\%([$~\\/]\|\w:[\\/]\)'
call pathogen#surround(path)
else
call pathogen#interpose(path)
endif
endfor
call pathogen#cycle_filetype()
if pathogen#is_disabled($MYVIMRC)
return 'finish'
endif
return ''
endfunction
" Split a path into a list.
function! pathogen#split(path) abort
if type(a:path) == type([]) | return a:path | endif
if empty(a:path) | return [] | endif
let split = split(a:path,'\\\@<!\%(\\\\\)*\zs,')
return map(split,'substitute(v:val,''\\\([\\,]\)'',''\1'',"g")')
endfunction
" Convert a list to a path.
function! pathogen#join(...) abort
if type(a:1) == type(1) && a:1
let i = 1
let space = ' '
else
let i = 0
let space = ''
endif
let path = ""
while i < a:0
if type(a:000[i]) == type([])
let list = a:000[i]
let j = 0
while j < len(list)
let escaped = substitute(list[j],'[,'.space.']\|\\[\,'.space.']\@=','\\&','g')
let path .= ',' . escaped
let j += 1
endwhile
else
let path .= "," . a:000[i]
endif
let i += 1
endwhile
return substitute(path,'^,','','')
endfunction
" Convert a list to a path with escaped spaces for 'path', 'tag', etc.
function! pathogen#legacyjoin(...) abort
return call('pathogen#join',[1] + a:000)
endfunction
" Turn filetype detection off and back on again if it was already enabled.
function! pathogen#cycle_filetype() abort
if exists('g:did_load_filetypes')
filetype off
filetype on
endif
endfunction
" Check if a bundle is disabled. A bundle is considered disabled if its
" basename or full name is included in the list g:pathogen_blacklist or the
" comma delimited environment variable $VIMBLACKLIST.
function! pathogen#is_disabled(path) abort
if a:path =~# '\~$'
return 1
endif
let sep = pathogen#slash()
let blacklist = get(g:, 'pathogen_blacklist', get(g:, 'pathogen_disabled', [])) + pathogen#split($VIMBLACKLIST)
if !empty(blacklist)
call map(blacklist, 'substitute(v:val, "[\\/]$", "", "")')
endif
return index(blacklist, fnamemodify(a:path, ':t')) != -1 || index(blacklist, a:path) != -1
endfunction
" Prepend the given directory to the runtime path and append its corresponding
" after directory. Curly braces are expanded with pathogen#expand().
function! pathogen#surround(path) abort
let sep = pathogen#slash()
let rtp = pathogen#split(&rtp)
let path = fnamemodify(a:path, ':s?[\\/]\=$??')
let before = filter(pathogen#expand(path), '!pathogen#is_disabled(v:val)')
let after = filter(reverse(pathogen#expand(path, sep.'after')), '!pathogen#is_disabled(v:val[0:-7])')
call filter(rtp, 'index(before + after, v:val) == -1')
let &rtp = pathogen#join(before, rtp, after)
return &rtp
endfunction
" For each directory in the runtime path, add a second entry with the given
" argument appended. Curly braces are expanded with pathogen#expand().
function! pathogen#interpose(name) abort
let sep = pathogen#slash()
let name = a:name
if has_key(s:done_bundles, name)
return ""
endif
let s:done_bundles[name] = 1
let list = []
for dir in pathogen#split(&rtp)
if dir =~# '\<after$'
let list += reverse(filter(pathogen#expand(dir[0:-6].name, sep.'after'), '!pathogen#is_disabled(v:val[0:-7])')) + [dir]
else
let list += [dir] + filter(pathogen#expand(dir.sep.name), '!pathogen#is_disabled(v:val)')
endif
endfor
let &rtp = pathogen#join(pathogen#uniq(list))
return 1
endfunction
let s:done_bundles = {}
" Invoke :helptags on all non-$VIM doc directories in runtimepath.
function! pathogen#helptags() abort
let sep = pathogen#slash()
for glob in pathogen#split(&rtp)
for dir in map(split(glob(glob), "\n"), 'v:val.sep."/doc/".sep')
if (dir)[0 : strlen($VIMRUNTIME)] !=# $VIMRUNTIME.sep && filewritable(dir) == 2 && !empty(split(glob(dir.'*.txt'))) && (!filereadable(dir.'tags') || filewritable(dir.'tags'))
silent! execute 'helptags' pathogen#fnameescape(dir)
endif
endfor
endfor
endfunction
command! -bar Helptags :call pathogen#helptags()
" Execute the given command. This is basically a backdoor for --remote-expr.
function! pathogen#execute(...) abort
for command in a:000
execute command
endfor
return ''
endfunction
" Section: Unofficial
function! pathogen#is_absolute(path) abort
return a:path =~# (has('win32') ? '^\%([\\/]\|\w:\)[\\/]\|^[~$]' : '^[/~$]')
endfunction
" Given a string, returns all possible permutations of comma delimited braced
" alternatives of that string. pathogen#expand('/{a,b}/{c,d}') yields
" ['/a/c', '/a/d', '/b/c', '/b/d']. Empty braces are treated as a wildcard
" and globbed. Actual globs are preserved.
function! pathogen#expand(pattern, ...) abort
let after = a:0 ? a:1 : ''
let pattern = substitute(a:pattern, '^[~$][^\/]*', '\=expand(submatch(0))', '')
if pattern =~# '{[^{}]\+}'
let [pre, pat, post] = split(substitute(pattern, '\(.\{-\}\){\([^{}]\+\)}\(.*\)', "\\1\001\\2\001\\3", ''), "\001", 1)
let found = map(split(pat, ',', 1), 'pre.v:val.post')
let results = []
for pattern in found
call extend(results, pathogen#expand(pattern))
endfor
elseif pattern =~# '{}'
let pat = matchstr(pattern, '^.*{}[^*]*\%($\|[\\/]\)')
let post = pattern[strlen(pat) : -1]
let results = map(split(glob(substitute(pat, '{}', '*', 'g')), "\n"), 'v:val.post')
else
let results = [pattern]
endif
let vf = pathogen#slash() . 'vimfiles'
call map(results, 'v:val =~# "\\*" ? v:val.after : isdirectory(v:val.vf.after) ? v:val.vf.after : isdirectory(v:val.after) ? v:val.after : ""')
return filter(results, '!empty(v:val)')
endfunction
" \ on Windows unless shellslash is set, / everywhere else.
function! pathogen#slash() abort
return !exists("+shellslash") || &shellslash ? '/' : '\'
endfunction
function! pathogen#separator() abort
return pathogen#slash()
endfunction
" Convenience wrapper around glob() which returns a list.
function! pathogen#glob(pattern) abort
let files = split(glob(a:pattern),"\n")
return map(files,'substitute(v:val,"[".pathogen#slash()."/]$","","")')
endfunction
" Like pathogen#glob(), only limit the results to directories.
function! pathogen#glob_directories(pattern) abort
return filter(pathogen#glob(a:pattern),'isdirectory(v:val)')
endfunction
" Remove duplicates from a list.
function! pathogen#uniq(list) abort
let i = 0
let seen = {}
while i < len(a:list)
if (a:list[i] ==# '' && exists('empty')) || has_key(seen,a:list[i])
call remove(a:list,i)
elseif a:list[i] ==# ''
let i += 1
let empty = 1
else
let seen[a:list[i]] = 1
let i += 1
endif
endwhile
return a:list
endfunction
" Backport of fnameescape().
function! pathogen#fnameescape(string) abort
if exists('*fnameescape')
return fnameescape(a:string)
elseif a:string ==# '-'
return '\-'
else
return substitute(escape(a:string," \t\n*?[{`$\\%#'\"|!<"),'^[+>]','\\&','')
endif
endfunction
" Like findfile(), but hardcoded to use the runtimepath.
function! pathogen#runtime_findfile(file,count) abort
let rtp = pathogen#join(1,pathogen#split(&rtp))
let file = findfile(a:file,rtp,a:count)
if file ==# ''
return ''
else
return fnamemodify(file,':p')
endif
endfunction
" vim:set et sw=2 foldmethod=expr foldexpr=getline(v\:lnum)=~'^\"\ Section\:'?'>1'\:getline(v\:lnum)=~#'^fu'?'a1'\:getline(v\:lnum)=~#'^endf'?'s1'\:'=':

View File

@@ -0,0 +1,41 @@
---
name: "Bug Report"
about: "nerdtree-git-plugin is misbehaving? Tell us about it."
labels: bug
---
<!-- Attention! Please Read!
Please fill out ALL the information below so that the issue can be fully
understood. Omitting information will delay the resolution of your issue. It
will be labeled "Needs More Info", and may be closed until there is enough
information.
Keep in mind that others may have the same question in the future. The better
your information, the more likely they'll be able to help themselves. -->
#### Self-Diagnosis
<!-- Check the boxes after creating the issue, or use [x]. -->
- [ ] I have searched the [issues](https://github.com/Xuyuanp/nerdtree-git-plugin/issues) for an answer to my question.
- [ ] I have reviewed the NERDTree documentation(README.md).
- [ ] I have searched the web for an answer to my question.
#### Environment (for bug reports)
- [ ] Operating System:
- [ ] vimrc settings
```vim
" all settings about nerdtree and other plugins
```
- Other NERDTree-dependent Plugins
- [ ] jistr/vim-nerdtree-tabs
- [ ] ryanoasis/vim-devicons
- [ ] tiagofumo/vim-nerdtree-syntax-highlight
- [ ] Others (specify):
- [ ] I've verified the issue occurs with only `nerdtree-git-plugin` installed.
- [ ] Copy-Paste `call gitstatus#doctor#Say()` outputs
#### Steps to Reproduce the Issue
1.
#### Current Result (Include screenshots where appropriate.)
#### Expected Result

View File

@@ -0,0 +1,8 @@
---
name: "Feature Request"
about: "What new feature are you requesting for nerdtree-git-plugin?"
labels: "feature request"
---
#### Description

View File

@@ -0,0 +1,23 @@
---
name: "General Question"
about: "Having trouble setting up nerdtree-git-plugin? Need clarification on a setting? Ask your question here."
labels: "general question"
---
<!-- Attention! Please Read!
Please fill out ALL the information below so that the issue can be fully
understood. Omitting information will delay the resolution of your issue. It
will be labeled "Needs More Info", and may be closed until there is enough
information.
Keep in mind that others may have the same question in the future. The better
your information, the more likely they'll be able to help themselves. -->
#### Self-Diagnosis
<!-- Check the boxes after creating the issue, or use [x]. -->
- [ ] I have searched the [issues](https://github.com/Xuyuanp/nerdtree-git-plugin/issues) for an answer to my question.
- [ ] I have reviewed the NERDTree documentation(README.md).
- [ ] I have searched the web for an answer to my question.
#### State Your Question

View File

@@ -0,0 +1,3 @@
### Description of Changes
Closes # <!-- Enter the issue number this PR addresses. If none, remove this line. -->

View File

@@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@@ -0,0 +1,57 @@
name: CI
on: [push, pull_request]
jobs:
vint:
name: Vint
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Run vint with reviewdog
uses: reviewdog/action-vint@v1.0.1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review
test:
name: Unit tests
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
neovim: [true, false]
version: [stable, nightly]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout themis.vim
uses: actions/checkout@v2
with:
repository: thinca/vim-themis
path: tmp/vim-themis
- name: Checkout nerdtree
uses: actions/checkout@v2
with:
repository: preservim/nerdtree
path: tmp/nerdtree
# Remove apt repos that are known to break from time to time
# See https://github.com/actions/virtual-environments/issues/323
- name: Remove broken apt repos [Ubuntu]
if: matrix.os == 'ubuntu-latest'
run: |
for apt_file in `grep -lr microsoft /etc/apt/sources.list.d/`; do sudo rm $apt_file; done
- name: Install Vim or Neovim
uses: rhysd/action-setup-vim@v1
id: vim
with:
neovim: ${{ matrix.neovim }}
version: ${{ matrix.version }}
- name: Run unit tests
env:
THEMIS_VIM: ${{ steps.vim.outputs.executable }}
THEMIS_PROFILE: profile.txt
run: |
echo $THEMIS_VIM
./tmp/vim-themis/bin/themis --runtimepath ./tmp/nerdtree --reporter spec tests/
# TODO: coverage

View File

@@ -0,0 +1,14 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
- id: mixed-line-ending
- repo: https://github.com/Vimjas/vint
rev: master
hooks:
- id: vint

View File

@@ -0,0 +1,40 @@
cmdargs:
# Checking more strictly
severity: style_problem
# Enable coloring
color: false
# Enable Neovim syntax
env:
neovim: true
policies:
ProhibitAutocmdWithNoGroup:
enabled: true
ProhibitCommandRelyOnUser:
enabled: true
ProhibitCommandWithUnintendedSideEffect:
enabled: true
ProhibitEncodingOptionAfterScriptEncoding:
enabled: true
ProhibitEqualTildeOperator:
enabled: true
ProhibitImplicitScopeBuiltinVariable:
enabled: true
ProhibitMissingScriptEncoding:
enabled: true
ProhibitNoAbortFunction:
enabled: true
ProhibitSetNoCompatible:
enabled: true
ProhibitUnnecessaryDoubleQuote:
enabled: true
ProhibitUnusedVariable:
enabled: true
ProhibitUsingUndeclaredVariable:
enabled: true
ProhibitAbbreviationOption:
enabled: true
ProhibitImplicitScopeVariable:
enabled: true

View File

@@ -0,0 +1,14 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@@ -0,0 +1,104 @@
nerdtree-git-plugin
===================
[![Github Action](https://img.shields.io/github/workflow/status/Xuyuanp/nerdtree-git-plugin/CI)](https://github.com/Xuyuanp/nerdtree-git-plugin/actions?query=workflow%3ACI)
[![License: WTFPL](https://img.shields.io/github/license/Xuyuanp/nerdtree-git-plugin)](http://www.wtfpl.net/about/)
[![GitHub contributors](https://img.shields.io/github/contributors/Xuyuanp/nerdtree-git-plugin)](https://github.com/Xuyuanp/nerdtree-git-plugin/graphs/contributors)
A plugin of [NERDTree](https://github.com/preservim/nerdtree) showing git status flags.
The original project [git-nerdtree](https://github.com/Xuyuanp/git-nerdtree) will not be maintained any longer.
![Imgur](http://i.imgur.com/jSCwGjU.gif?1)
## Installation
Use your favorite package manager. Here is the example of using [vim-plug](https://github.com/junegunn/vim-plug)
```vim script
Plug 'preservim/nerdtree' |
\ Plug 'Xuyuanp/nerdtree-git-plugin'
```
## FAQ
> Got error message like `Error detected while processing function
177[2]..178[22]..181[7]..144[9]..142[36]..238[4]..NERDTreeGitStatusRefreshListener[2]..NERDTreeGitStatusRefresh:
line 6:
E484: Can't open file /tmp/vZEZ6gM/1` while nerdtree opening in fish, how to resolve this problem?
This was because that vim couldn't execute `system` function in `fish`. Add `set shell=sh` in your vimrc.
This issue has been fixed.
> How to config custom symbols?
Use this variable to change symbols.
```vim
let g:NERDTreeGitStatusIndicatorMapCustom = {
\ 'Modified' :'✹',
\ 'Staged' :'✚',
\ 'Untracked' :'✭',
\ 'Renamed' :'➜',
\ 'Unmerged' :'═',
\ 'Deleted' :'✖',
\ 'Dirty' :'✗',
\ 'Ignored' :'☒',
\ 'Clean' :'✔︎',
\ 'Unknown' :'?',
\ }
```
There is a predefined map used *nerdfonts*, to enable it
```vim
let g:NERDTreeGitStatusUseNerdFonts = 1 " you should install nerdfonts by yourself. default: 0
```
> How to show `ignored` status?
```vim
let g:NERDTreeGitStatusShowIgnored = 1 " a heavy feature may cost much more time. default: 0
```
> How to cooperate with [vim-devicons](https://github.com/ryanoasis/vim-devicons)
```vim
Plug 'preservim/nerdtree' |
\ Plug 'Xuyuanp/nerdtree-git-plugin' |
\ Plug 'ryanoasis/vim-devicons'
```
Make sure they are in the right order.
> How to indicate every single `untracked` file under an `untracked` dir?
```vim
let g:NERDTreeGitStatusUntrackedFilesMode = 'all' " a heave feature too. default: normal
```
> How to set `git` executable file path?
```vim
let g:NERDTreeGitStatusGitBinPath = '/your/file/path' " defualt: git (auto find in path)
```
> How to show `Clean` indicator?
```vim
let g:NERDTreeGitStatusShowClean = 1 " default: 0
```
> How to hide the boring brackets(`[ ]`)?
```vim
let g:NERDTreeGitStatusConcealBrackets = 1 " default: 0
```
**NOTICE**: DO NOT enable this feature if you have also installed [vim-devicons](https://github.com/ryanoasis/vim-devicons).
## Credits
* [scrooloose](https://github.com/scrooloose): Open API for me.
* [git\_nerd](https://github.com/swerner/git_nerd): Where my idea comes from.
* [PickRelated](https://github.com/PickRelated): Add custom indicators & Review code.

View File

@@ -0,0 +1,58 @@
" ============================================================================
" File: autoload/gitstatus/job.vim
" Description: git status indicator syntax highlighting
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
if !get(g:, 'NERDTreeGitStatusEnable', 0)
finish
endif
function! s:getIndicator(status) abort
return gitstatus#getIndicator(a:status)
endfunction
if gitstatus#shouldConceal()
" Hide the backets
syntax match hideBracketsInNerdTreeL "\]" contained conceal containedin=NERDTreeFlags
syntax match hideBracketsInNerdTreeR "\[" contained conceal containedin=NERDTreeFlags
setlocal conceallevel=3
setlocal concealcursor=nvic
endif
function! s:highlightFromGroup(group) abort
let l:synid = synIDtrans(hlID(a:group))
let [l:ctermfg, l:guifg] = [synIDattr(l:synid, 'fg', 'cterm'), synIDattr(l:synid, 'fg', 'gui')]
return 'cterm=NONE ctermfg=' . l:ctermfg . ' ctermbg=NONE gui=NONE guifg=' . l:guifg . ' guibg=NONE'
endfunction
function! s:setHightlighting() abort
let l:synlist = [
\ ['Unmerged', 'Function'],
\ ['Modified', 'Special'],
\ ['Staged', 'Function'],
\ ['Renamed', 'Title'],
\ ['Unmerged', 'Label'],
\ ['Untracked', 'Comment'],
\ ['Dirty', 'Tag'],
\ ['Deleted', 'Operator'],
\ ['Ignored', 'SpecialKey'],
\ ['Clean', 'Method'],
\ ]
for [l:name, l:group] in l:synlist
let l:indicator = escape(s:getIndicator(l:name), '\#-*.$')
let l:synname = 'NERDTreeGitStatus' . l:name
execute 'silent! syntax match ' . l:synname . ' #\m\C\zs[' . l:indicator . ']\ze[^\]]*\]# containedin=NERDTreeFlags'
let l:hipat = get(get(g:, 'NERDTreeGitStatusHighlightingCustom', {}),
\ l:name,
\ s:highlightFromGroup(l:group))
execute 'silent! highlight ' . l:synname . ' ' . l:hipat
endfor
endfunction
silent! call s:setHightlighting()

View File

@@ -0,0 +1,69 @@
" ============================================================================
" File: autoload/gitstatus.vim
" Description: library for indicators
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
if exists('g:loaded_nerdtree_git_status_autoload')
finish
endif
let g:loaded_nerdtree_git_status_autoload = 1
function! gitstatus#isWin() abort
return has('win16') || has('win32') || has('win64')
endfunction
if get(g:, 'NERDTreeGitStatusUseNerdFonts', 0)
let s:indicatorMap = {
\ 'Modified' :nr2char(61545),
\ 'Staged' :nr2char(61543),
\ 'Untracked' :nr2char(61736),
\ 'Renamed' :nr2char(62804),
\ 'Unmerged' :nr2char(61556),
\ 'Deleted' :nr2char(63167),
\ 'Dirty' :nr2char(61453),
\ 'Ignored' :nr2char(61738),
\ 'Clean' :nr2char(61452),
\ 'Unknown' :nr2char(61832)
\ }
elseif &encoding ==? 'utf-8'
let s:indicatorMap = {
\ 'Modified' :nr2char(10041),
\ 'Staged' :nr2char(10010),
\ 'Untracked' :nr2char(10029),
\ 'Renamed' :nr2char(10140),
\ 'Unmerged' :nr2char(9552),
\ 'Deleted' :nr2char(10006),
\ 'Dirty' :nr2char(10007),
\ 'Ignored' :nr2char(33),
\ 'Clean' :nr2char(10004),
\ 'Unknown' :nr2char(120744)
\ }
else
let s:indicatorMap = {
\ 'Modified' :'*',
\ 'Staged' :'+',
\ 'Untracked' :'!',
\ 'Renamed' :'R',
\ 'Unmerged' :'=',
\ 'Deleted' :'D',
\ 'Dirty' :'X',
\ 'Ignored' :'?',
\ 'Clean' :'C',
\ 'Unknown' :'E'
\ }
endif
function! gitstatus#getIndicator(status) abort
return get(get(g:, 'NERDTreeGitStatusIndicatorMapCustom', {}),
\ a:status,
\ s:indicatorMap[a:status])
endfunction
function! gitstatus#shouldConceal() abort
return has('conceal') && g:NERDTreeGitStatusConcealBrackets
endfunction

View File

@@ -0,0 +1,167 @@
" ============================================================================
" File: autoload/gitstatus/doctor.vim
" Description: what does the doctor say?
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
let s:types = {
\ 'NUMBER': type(0),
\ 'STRING': type(''),
\ 'FUNCREF': type(function('tr')),
\ 'LIST': type([]),
\ 'DICT': type({}),
\ 'FLOAT': type(0.0),
\ 'BOOL': type(v:true),
\ 'NULL': type(v:null)
\ }
let s:type_formatters = {}
let s:type_formatters[s:types.NUMBER] = { nbr -> string(nbr) }
let s:type_formatters[s:types.STRING] = { str -> printf("'%s'", str) }
let s:type_formatters[s:types.FUNCREF] = { fn -> string(fn) }
let s:type_formatters[s:types.LIST] = { lst -> s:prettifyList(lst, ' \ ', 0, ' ') }
let s:type_formatters[s:types.DICT] = { dct -> s:prettifyDict(dct, ' \ ', 0, ' ') }
let s:type_formatters[s:types.FLOAT] = { flt -> string(flt) }
let s:type_formatters[s:types.BOOL] = { bol -> bol ? 'v:true' : 'v:false' }
let s:type_formatters[s:types.NULL] = { nul -> string(nul) }
function! s:get_git_version() abort
return split(system('git version'), "\n")[0]
endfunction
function! s:get_git_status_output(workdir) abort
return system(join(gitstatus#util#BuildGitStatusCommand(a:workdir, g:), ' '))
endfunction
function! s:prettifyDict(obj, prefix, level, indent) abort
let l:prefix = a:prefix . repeat(a:indent, a:level)
if empty(a:obj)
return '{}'
endif
let l:res = "{\n"
for [l:key, l:val] in items(a:obj)
let l:type = type(l:val)
if l:type is# s:types.DICT
let l:val = s:prettifyDict(l:val, a:prefix, a:level + 1, a:indent)
elseif l:type is# s:types.LIST
let l:val = s:prettifyList(l:val, a:prefix , a:level + 1, a:indent)
else
let l:val = s:prettify(l:val)
endif
let l:res .= l:prefix . a:indent . "'" . l:key . "': " . l:val . ",\n"
endfor
let l:res .= l:prefix . '}'
return l:res
endfunction
function! s:prettifyList(obj, prefix, level, indent) abort
let l:prefix = a:prefix . repeat(a:indent, a:level)
if empty(a:obj)
return '[]'
endif
let l:res = "[\n"
for l:val in a:obj
let l:type = type(l:val)
if l:type is# s:types.LIST
let l:val = s:prettifyList(l:val, a:prefix, a:level + 1, a:indent)
elseif l:type is# s:types.DICT
let l:val = s:prettifyDict(l:val, a:prefix, a:level + 1, a:indent)
else
let l:val = s:prettify(l:val)
endif
let l:res .= l:prefix . a:indent . l:val . ",\n"
endfor
let l:res .= l:prefix . ']'
return l:res
endfunction
function! s:prettify(obj) abort
let l:type = type(a:obj)
return call(s:type_formatters[l:type], [a:obj])
endfunction
function! s:loaded_vim_devicons() abort
return get(g:, 'loaded_webdevicons', 0) && get(g:, 'webdevicons_enable', 0) && get(g:, 'webdevicons_enable_nerdtree', 0)
endfunction
function! s:loaded_vim_nerdtree_syntax_highlight() abort
return exists('g:NERDTreeSyntaxEnabledExtensions')
endfunction
function! s:loaded_vim_nerdtree_tabs() abort
return exists('g:nerdtree_tabs_open_on_gui_startup')
endfunction
function! gitstatus#doctor#Say() abort
call g:NERDTree.MustBeOpen()
call g:NERDTree.CursorToTreeWin()
let l:line = repeat('=', 80)
echo has('nvim') ? 'Neovim:' : 'Vim:'
echo execute('version')
echo l:line
echo 'NERDTree:'
echo 'version: ' . nerdtree#version()
echo 'root: ' . b:NERDTree.root.path.str()
echo l:line
echo 'Git:'
echo 'version: ' . s:get_git_version()
let l:git_workdir = get(g:, 'NTGitWorkdir', '')
echo 'workdir: ' . l:git_workdir
if !empty(l:git_workdir)
echo 'status output:'
echo s:get_git_status_output(l:git_workdir)
endif
echo l:line
echo 'Options:'
for [l:key, l:val] in items(g:)
if l:key =~# 'NERDTreeGitStatus*'
echo '' . l:key . ' = ' . s:prettify(l:val)
endif
endfor
echo l:line
echo 'Others:'
echo 'vim-devicons: ' . (s:loaded_vim_devicons() ? 'yes' : 'no')
if s:loaded_vim_devicons()
for [l:key, l:val] in items(g:)
if l:key =~# 'WebDevIconsNerdTree*'
echo '' . l:key . ' = ' . s:prettify(l:val)
endif
endfor
endif
echo repeat('-', 40)
echo 'vim-nerdtree-syntax-highlight: ' . (s:loaded_vim_nerdtree_syntax_highlight() ? 'yes': 'no')
if s:loaded_vim_nerdtree_syntax_highlight()
for [l:key, l:val] in items(g:)
if l:key =~# 'NERDTreeSyntax*'
echo '' . l:key . ' = ' . s:prettify(l:val)
endif
endfor
endif
echo repeat('-', 40)
echo 'vim-nerdtree-tabs: ' . (s:loaded_vim_nerdtree_tabs() ? 'yes': 'no')
if s:loaded_vim_nerdtree_tabs()
for [l:key, l:val] in items(g:)
if l:key =~# 'nerdtree_tabs_*'
echo '' . l:key . ' = ' . s:prettify(l:val)
endif
endfor
endif
echo l:line
endfunction

View File

@@ -0,0 +1,131 @@
" ============================================================================
" File: autoload/gitstatus/job.vim
" Description: async-jobs
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
if exists('g:loaded_nerdtree_git_status_job')
finish
endif
let g:loaded_nerdtree_git_status_job = 1
" stolen from vim-plug
let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait'))
let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
let s:Job = {
\ 'running': 0,
\ 'failed': 0,
\ 'chunks': [''],
\ 'err_chunks': [''],
\ }
" disabled ProhibitImplicitScopeVariable because we will use lots of `self`
" disabled ProhibitUnusedVariable because lambda
" vint: -ProhibitImplicitScopeVariable -ProhibitUnusedVariable
function! s:newJob(name, opts) abort
return extend(deepcopy(s:Job), {
\ 'name': a:name,
\ 'opts': a:opts
\ })
endfunction
function! s:Job.onStdoutCB(data) abort
let self.chunks[-1] .= a:data[0]
call extend(self.chunks, a:data[1:])
endfunction
function! s:Job.onStderrCB(data) abort
let self.failed = self.failed || !s:isEOF(a:data)
let self.err_chunks[-1] .= a:data[0]
call extend(self.err_chunks, a:data[1:])
endfunction
function! s:Job.onExitCB() abort
let self.running = 0
if self.failed
call self.onFailed()
else
call self.onSuccess()
endif
endfunction
function! s:Job.onFailed() abort
if has_key(self.opts, 'on_failed_cb')
call call(self.opts.on_failed_cb, [self])
endif
endfunction
function! s:Job.onSuccess() abort
if has_key(self.opts, 'on_success_cb')
call call(self.opts.on_success_cb, [self])
endif
endfunction
if s:nvim
function! s:Job.run(cmd) abort
let jid = jobstart(a:cmd, {
\ 'on_stdout': {_job_id, data, _event -> self.onStdoutCB(data)},
\ 'on_stderr': {_job_id, data, _event -> self.onStderrCB(data)},
\ 'on_exit': {_job_id, _data, _event -> self.onExitCB()},
\ })
let self.id = jid
let self.running = jid > 0
if jid <= 0
let self.failed = 1
let self.err_chunks = jid == 0 ?
\ ['invalid arguments'] :
\ ['command is not executable']
call self.onExitCB()
endif
endfunction
elseif s:vim8
function! s:Job.run(cmd) abort
let options = {
\ 'out_cb': { _ch, data -> self.onStdoutCB([data]) },
\ 'err_cb': { _ch, data -> self.onStderrCB([data]) },
\ 'close_cb': { _ch -> self.onExitCB() },
\ 'out_mode': 'nl',
\ 'err_mode': 'nl',
\ }
if has('patch-8.1.350')
let options['noblock'] = 1
endif
let jid = job_start(a:cmd, options)
if job_status(jid) ==# 'run'
let self.id = jid
let self.running = 1
else
let self.running = 0
let self.failed = 1
let self.err_chunks = ['failed to start job']
call self.onExitCB()
endif
endfunction
else
function! s:Job.run(cmd) abort
let output = substitute(system(join(a:cmd, ' ')), "\<C-A>", "\n", 'g')
let self.failed = v:shell_error isnot# 0
if self.failed
let self.err_chunks = [output]
else
let self.chunks = [output]
endif
call self.onExitCB()
endfunction
endif
" vint: +ProhibitImplicitScopeVariable +ProhibitUnusedVariable
function! s:isEOF(data) abort
return len(a:data) == 1 && a:data[0] is# ''
endfunction
function! gitstatus#job#Spawn(name, cmd, opts) abort
let l:job = s:newJob(a:name, a:opts)
call l:job.run(a:cmd)
return l:job
endfunction

View File

@@ -0,0 +1,112 @@
" ============================================================================
" File: autoload/gitstatus/listener.vim
" Description: nerdtree event listener
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
if exists('g:loaded_nerdtree_git_status_listener')
finish
endif
let g:loaded_nerdtree_git_status_listener = 1
let s:Listener = {
\ 'current': {},
\ 'next': {},
\ }
" disabled ProhibitImplicitScopeVariable because we will use lots of `self`
" vint: -ProhibitImplicitScopeVariable
function! s:Listener.OnInit(event) abort
call self.callback(a:event)
endfunction
function! s:Listener.OnRefresh(event) abort
call self.callback(a:event)
endfunction
function! s:Listener.OnRefreshFlags(event) abort
call self.callback(a:event)
endfunction
function! s:Listener.callback(event) abort
let l:path = a:event.subject
let l:indicator = self.getIndicatorByPath(l:path)
call l:path.flagSet.clearFlags('git')
if l:indicator !=# ''
if gitstatus#shouldConceal()
let l:indicator = printf(' %s ', l:indicator)
endif
call l:path.flagSet.addFlag('git', l:indicator)
endif
endfunction
function!s:Listener.getIndicatorByPath(path) abort
let l:pathStr = gitstatus#util#FormatPath(a:path)
let l:statusKey = get(self.current, l:pathStr, '')
if l:statusKey !=# ''
return gitstatus#getIndicator(l:statusKey)
endif
if self.getOption('ShowClean', 0)
return gitstatus#getIndicator('Clean')
endif
if self.getOption('ConcealBrackets', 0) && self.getOption('AlignIfConceal', 0)
return ' '
endif
return ''
endfunction
function! s:Listener.SetNext(cache) abort
let self.next = a:cache
endfunction
function! s:Listener.HasPath(path_str) abort
return has_key(self.current, a:path_str)
endfunction
function! s:Listener.changed() abort
return self.current !=# self.next
endfunction
function! s:Listener.update() abort
let self.current = self.next
endfunction
function! s:Listener.TryUpdateNERDTreeUI() abort
if !g:NERDTree.IsOpen()
return
endif
if !self.changed()
return
endif
call self.update()
let l:winnr = winnr()
let l:altwinnr = winnr('#')
try
call g:NERDTree.CursorToTreeWin()
call b:NERDTree.root.refreshFlags()
call NERDTreeRender()
finally
exec l:altwinnr . 'wincmd w'
exec l:winnr . 'wincmd w'
endtry
endfunction
function! s:Listener.getOption(name, default) abort
return get(self.opts, 'NERDTreeGitStatus' . a:name, a:default)
endfunction
" vint: +ProhibitImplicitScopeVariable
function! gitstatus#listener#New(opts) abort
return extend(deepcopy(s:Listener), {'opts': a:opts})
endfunction

View File

@@ -0,0 +1,56 @@
" ============================================================================
" File: autoload/gitstatus/job.vim
" Description: leveled-logger
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
if exists('g:loaded_nerdtree_git_status_log')
finish
endif
let g:loaded_nerdtree_git_status_log = 1
let s:debug = 0 | :lockvar s:debug
let s:info = 1 | :lockvar s:info
let s:warning = 2 | :lockvar s:warning
let s:error = 3 | :lockvar s:error
let s:Logger = {}
" vint: -ProhibitImplicitScopeVariable
function! s:Logger.output(level, msg) abort
if a:level < self.level
return
endif
echomsg '[nerdtree-git-status] ' . a:msg
endfunction
function! s:Logger.debug(msg) abort
echohl LineNr |
\ call self.output(s:debug, a:msg) |
\ echohl None
endfunction
function! s:Logger.info(msg) abort
call self.output(s:info, a:msg)
endfunction
function! s:Logger.warning(msg) abort
echohl WarningMsg |
\ call self.output(s:warning, a:msg) |
\ echohl None
endfunction
function! s:Logger.error(msg) abort
echohl ErrorMsg |
\ call self.output(s:error, a:msg) |
\ echohl None
endfunction
" vint: +ProhibitImplicitScopeVariable
function! gitstatus#log#NewLogger(level) abort
return extend(copy(s:Logger), {'level': a:level})
endfunction

View File

@@ -0,0 +1,225 @@
" ============================================================================
" File: autoload/git_status/util.vim
" Description: utils
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
if exists('g:loaded_nerdtree_git_status_util')
finish
endif
let g:loaded_nerdtree_git_status_util = 1
" FUNCTION: gitstatus#utilFormatPath
" This function is used to format nerdtree.Path.
" For Windows, returns in format 'C:/path/to/file'
"
" ARGS:
" path: nerdtree.Path
"
" RETURNS:
" absolute path
if gitstatus#isWin()
if exists('+shellslash')
function! gitstatus#util#FormatPath(path) abort
let l:sslbak = &shellslash
try
set shellslash
return a:path.str()
finally
let &shellslash = l:sslbak
endtry
endfunction
else
function! gitstatus#util#FormatPath(path) abort
let l:pathStr = a:path.str()
let l:pathStr = a:path.WinToUnixPath(l:pathStr)
let l:pathStr = a:path.drive . l:pathStr
return l:pathStr
endfunction
endif
else
function! gitstatus#util#FormatPath(path) abort
return a:path.str()
endfunction
endif
function! gitstatus#util#BuildGitWorkdirCommand(root, opts) abort
return [
\ get(a:opts, 'NERDTreeGitStatusGitBinPath', 'git'),
\ '-C', a:root,
\ 'rev-parse',
\ '--show-toplevel',
\ ]
endfunction
function! gitstatus#util#BuildGitStatusCommand(root, opts) abort
let l:cmd = [
\ get(a:opts, 'NERDTreeGitStatusGitBinPath', 'git'),
\ '-C', a:root,
\ 'status',
\ '--porcelain' . (get(a:opts, 'NERDTreeGitStatusPorcelainVersion', 2) ==# 2 ? '=v2' : ''),
\ '-z'
\ ]
if has_key(a:opts, 'NERDTreeGitStatusUntrackedFilesMode')
let l:cmd += ['--untracked-files=' . a:opts['NERDTreeGitStatusUntrackedFilesMode']]
endif
if get(a:opts, 'NERDTreeGitStatusShowIgnored', 0)
let l:cmd += ['--ignored=traditional']
endif
if has_key(a:opts, 'NERDTreeGitStatusIgnoreSubmodules')
let l:cmd += ['--ignore-submodules=' . a:opts['NERDTreeGitStatusIgnoreSubmodules']]
endif
return l:cmd
endfunction
function! gitstatus#util#ParseGitStatusLines(root, statusLines, opts) abort
let l:result = {}
let l:is_rename = 0
for l:line in a:statusLines
if l:is_rename
call gitstatus#util#UpdateParentDirsStatus(l:result, a:root, a:root . '/' . l:line, 'Dirty', a:opts)
let l:is_rename = 0
continue
endif
let [l:pathStr, l:statusKey] = gitstatus#util#ParseGitStatusLine(l:line, a:opts)
let l:pathStr = a:root . '/' . l:pathStr
if l:pathStr[-1:-1] is# '/'
let l:pathStr = l:pathStr[:-2]
endif
let l:is_rename = l:statusKey is# 'Renamed'
let l:result[l:pathStr] = l:statusKey
call gitstatus#util#UpdateParentDirsStatus(l:result, a:root, l:pathStr, l:statusKey, a:opts)
endfor
return l:result
endfunction
let s:unmerged_status = {
\ 'DD': 1,
\ 'AU': 1,
\ 'UD': 1,
\ 'UA': 1,
\ 'DU': 1,
\ 'AA': 1,
\ 'UU': 1,
\ }
" Function: s:getStatusKey() function {{{2
" This function is used to get git status key
"
" Args:
" x: index tree
" y: work tree
"
"Returns:
" status key
"
" man git-status
" X Y Meaning
" -------------------------------------------------
" [MD] not updated
" M [ MD] updated in index
" A [ MD] added to index
" D [ M] deleted from index
" R [ MD] renamed in index
" C [ MD] copied in index
" [MARC] index and work tree matches
" [ MARC] M work tree changed since index
" [ MARC] D deleted in work tree
" -------------------------------------------------
" D D unmerged, both deleted
" A U unmerged, added by us
" U D unmerged, deleted by them
" U A unmerged, added by them
" D U unmerged, deleted by us
" A A unmerged, both added
" U U unmerged, both modified
" -------------------------------------------------
" ? ? untracked
" ! ! ignored
" -------------------------------------------------
function! s:getStatusKey(x, y) abort
let l:xy = a:x . a:y
if get(s:unmerged_status, l:xy, 0)
return 'Unmerged'
elseif l:xy ==# '??'
return 'Untracked'
elseif l:xy ==# '!!'
return 'Ignored'
elseif a:y ==# 'M'
return 'Modified'
elseif a:y ==# 'D'
return 'Deleted'
elseif a:y =~# '[RC]'
return 'Renamed'
elseif a:x ==# 'D'
return 'Deleted'
elseif a:x =~# '[MA]'
return 'Staged'
elseif a:x =~# '[RC]'
return 'Renamed'
else
return 'Unknown'
endif
endfunction
function! gitstatus#util#ParseGitStatusLine(statusLine, opts) abort
if get(a:opts, 'NERDTreeGitStatusPorcelainVersion', 2) ==# 2
if a:statusLine[0] ==# '1'
let l:statusKey = s:getStatusKey(a:statusLine[2], a:statusLine[3])
let l:pathStr = a:statusLine[113:]
elseif a:statusLine[0] ==# '2'
let l:statusKey = 'Renamed'
let l:pathStr = a:statusLine[113:]
let l:pathStr = l:pathStr[stridx(l:pathStr, ' ')+1:]
elseif a:statusLine[0] ==# 'u'
let l:statusKey = 'Unmerged'
let l:pathStr = a:statusLine[161:]
elseif a:statusLine[0] ==# '?'
let l:statusKey = 'Untracked'
let l:pathStr = a:statusLine[2:]
elseif a:statusLine[0] ==# '!'
let l:statusKey = 'Ignored'
let l:pathStr = a:statusLine[2:]
else
throw '[nerdtree_git_status] unknown status: ' . a:statusLine
endif
return [l:pathStr, l:statusKey]
else
let l:pathStr = a:statusLine[3:]
let l:statusKey = s:getStatusKey(a:statusLine[0], a:statusLine[1])
return [l:pathStr, l:statusKey]
endif
endfunction
function! gitstatus#util#UpdateParentDirsStatus(cache, root, pathStr, statusKey, opts) abort
let l:dirtyPath = fnamemodify(a:pathStr, ':h')
let l:dir_dirty_only = get(a:opts, 'NERDTreeGitStatusDirDirtyOnly', 1)
while l:dirtyPath !=# a:root
let l:key = get(a:cache, l:dirtyPath, '')
if l:dir_dirty_only
if l:key ==# ''
let a:cache[l:dirtyPath] = 'Dirty'
else
return
endif
else
if l:key ==# ''
let a:cache[l:dirtyPath] = a:statusKey
elseif l:key ==# 'Dirty' || l:key ==# a:statusKey
return
else
let a:cache[l:dirtyPath] = 'Dirty'
endif
endif
let l:dirtyPath = fnamemodify(l:dirtyPath, ':h')
endwhile
endfunction

View File

@@ -0,0 +1,343 @@
" ============================================================================
" File: git_status.vim
" Description: plugin for NERD Tree that provides git status support
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
scriptencoding utf-8
if exists('g:loaded_nerdtree_git_status')
finish
endif
let g:loaded_nerdtree_git_status = 1
let s:is_win = gitstatus#isWin()
" stolen from nerdtree
"Function: s:initVariable() function {{{2
"This function is used to initialise a given variable to a given value. The
"variable is only initialised if it does not exist prior
"
"Args:
"var: the name of the var to be initialised
"value: the value to initialise var to
"
"Returns:
"1 if the var is set, 0 otherwise
function! s:initVariable(var, value) abort
if !exists(a:var)
exec 'let ' . a:var . ' = ' . "'" . substitute(a:value, "'", "''", 'g') . "'"
return 1
endif
return 0
endfunction
let s:default_vals = {
\ 'g:NERDTreeGitStatusEnable': 1,
\ 'g:NERDTreeGitStatusUpdateOnWrite': 1,
\ 'g:NERDTreeGitStatusUpdateOnCursorHold': 1,
\ 'g:NERDTreeGitStatusShowIgnored': 0,
\ 'g:NERDTreeGitStatusUseNerdFonts': 0,
\ 'g:NERDTreeGitStatusDirDirtyOnly': 1,
\ 'g:NERDTreeGitStatusConcealBrackets': 0,
\ 'g:NERDTreeGitStatusAlignIfConceal': 1,
\ 'g:NERDTreeGitStatusShowClean': 0,
\ 'g:NERDTreeGitStatusLogLevel': 2,
\ 'g:NERDTreeGitStatusPorcelainVersion': 2,
\ 'g:NERDTreeGitStatusMapNextHunk': ']c',
\ 'g:NERDTreeGitStatusMapPrevHunk': '[c',
\ 'g:NERDTreeGitStatusUntrackedFilesMode': 'normal',
\ 'g:NERDTreeGitStatusGitBinPath': 'git',
\ }
for [s:var, s:value] in items(s:default_vals)
call s:initVariable(s:var, s:value)
endfor
let s:logger = gitstatus#log#NewLogger(g:NERDTreeGitStatusLogLevel)
function! s:deprecated(oldv, newv) abort
call s:logger.warning(printf("option '%s' is deprecated, please use '%s'", a:oldv, a:newv))
endfunction
function! s:migrateVariable(oldv, newv) abort
if exists(a:oldv)
call s:deprecated(a:oldv, a:newv)
exec 'let ' . a:newv . ' = ' . a:oldv
return 1
endif
return 0
endfunction
let s:need_migrate_vals = {
\ 'g:NERDTreeShowGitStatus': 'g:NERDTreeGitStatusEnable',
\ 'g:NERDTreeUpdateOnWrite': 'g:NERDTreeGitStatusUpdateOnWrite',
\ 'g:NERDTreeMapNextHunk': 'g:NERDTreeGitStatusMapNextHunk',
\ 'g:NERDTreeMapPrevHunk': 'g:NERDTreeGitStatusMapPrevHunk',
\ 'g:NERDTreeShowIgnoredStatus': 'g:NERDTreeGitStatusShowIgnored',
\ 'g:NERDTreeIndicatorMapCustom': 'g:NERDTreeGitStatusIndicatorMapCustom',
\ }
for [s:oldv, s:newv] in items(s:need_migrate_vals)
call s:migrateVariable(s:oldv, s:newv)
endfor
if !g:NERDTreeGitStatusEnable
finish
endif
if !executable(g:NERDTreeGitStatusGitBinPath)
call s:logger.error('git command not found')
finish
endif
" FUNCTION: path2str
" This function is used to format nerdtree.Path.
" For Windows, returns in format 'C:/path/to/file'
"
" ARGS:
" path: nerdtree.Path
"
" RETURNS:
" absolute path
function! s:path2str(path) abort
return gitstatus#util#FormatPath(a:path)
endfunction
" disable ProhibitUnusedVariable because these three functions used to callback
" vint: -ProhibitUnusedVariable
function! s:onGitWorkdirSuccessCB(job) abort
let g:NTGitWorkdir = split(join(a:job.chunks, ''), "\n")[0]
call s:logger.debug(printf("'%s' is in a git repo: '%s'", a:job.opts.cwd, g:NTGitWorkdir))
call s:enableLiveUpdate()
call s:refreshGitStatus('init', g:NTGitWorkdir)
endfunction
function! s:onGitWorkdirFailedCB(job) abort
let l:errormsg = join(a:job.err_chunks, '')
if l:errormsg =~# 'fatal: Not a git repository'
call s:logger.debug(printf("'%s' is not in a git repo", a:job.opts.cwd))
endif
call s:disableLiveUpdate()
unlet! g:NTGitWorkdir
endfunction
function! s:getGitWorkdir(ntRoot) abort
call gitstatus#job#Spawn('git-workdir',
\ s:buildGitWorkdirCommand(a:ntRoot),
\ {
\ 'on_success_cb': function('s:onGitWorkdirSuccessCB'),
\ 'on_failed_cb': function('s:onGitWorkdirFailedCB'),
\ 'cwd': a:ntRoot,
\ })
endfunction
" vint: +ProhibitUnusedVariable
function! s:buildGitWorkdirCommand(root) abort
return gitstatus#util#BuildGitWorkdirCommand(a:root, g:)
endfunction
function! s:buildGitStatusCommand(workdir) abort
return gitstatus#util#BuildGitStatusCommand(a:workdir, g:)
endfunction
function! s:refreshGitStatus(name, workdir) abort
let l:opts = {
\ 'on_failed_cb': function('s:onGitStatusFailedCB'),
\ 'on_success_cb': function('s:onGitStatusSuccessCB'),
\ 'cwd': a:workdir
\ }
let l:job = gitstatus#job#Spawn(a:name, s:buildGitStatusCommand(a:workdir), l:opts)
return l:job
endfunction
" vint: -ProhibitUnusedVariable
function! s:onGitStatusSuccessCB(job) abort
if !exists('g:NTGitWorkdir') || g:NTGitWorkdir !=# a:job.opts.cwd
call s:logger.debug(printf("git workdir has changed: '%s' -> '%s'", a:job.opts.cwd, get(g:, 'NTGitWorkdir', '')))
return
endif
let l:output = join(a:job.chunks, '')
let l:lines = split(l:output, "\n")
let l:cache = gitstatus#util#ParseGitStatusLines(a:job.opts.cwd, l:lines, g:)
call s:listener.SetNext(l:cache)
call s:listener.TryUpdateNERDTreeUI()
endfunction
function! s:onGitStatusFailedCB(job) abort
let l:errormsg = join(a:job.err_chunks, '')
if l:errormsg =~# "error: option `porcelain' takes no value"
call s:logger.error(printf("'git status' command failed, please upgrade your git binary('v2.11.0' or higher) or set option 'g:NERDTreeGitStatusPorcelainVersion' to 1 in vimrc"))
call s:disableLiveUpdate()
unlet! g:NTGitWorkdir
elseif l:errormsg =~# '^warning: could not open .* Permission denied'
call s:onGitStatusSuccessCB(a:job)
else
call s:logger.error(printf('job[%s] failed: %s', a:job.name, l:errormsg))
endif
endfunction
" FUNCTION: s:onCursorHold(fname) {{{2
function! s:onCursorHold(fname)
" Do not update when a special buffer is selected
if !empty(&l:buftype)
return
endif
let l:fname = s:is_win ?
\ substitute(a:fname, '\', '/', 'g') :
\ a:fname
if !exists('g:NTGitWorkdir') || !s:hasPrefix(l:fname, g:NTGitWorkdir)
return
endif
let l:job = s:refreshGitStatus('cursor-hold', g:NTGitWorkdir)
call s:logger.debug('run cursor-hold job: ' . l:job.id)
endfunction
" FUNCTION: s:onFileUpdate(fname) {{{2
function! s:onFileUpdate(fname)
let l:fname = s:is_win ?
\ substitute(a:fname, '\', '/', 'g') :
\ a:fname
if !exists('g:NTGitWorkdir') || !s:hasPrefix(l:fname, g:NTGitWorkdir)
return
endif
let l:job = s:refreshGitStatus('file-update', g:NTGitWorkdir)
call s:logger.debug('run file-update job: ' . l:job.id)
endfunction
" vint: +ProhibitUnusedVariable
function! s:hasPrefix(text, prefix) abort
return len(a:text) >= len(a:prefix) && a:text[:len(a:prefix)-1] ==# a:prefix
endfunction
function! s:setupNERDTreeListeners(listener) abort
call g:NERDTreePathNotifier.AddListener('init', a:listener.OnInit)
call g:NERDTreePathNotifier.AddListener('refresh', a:listener.OnRefresh)
call g:NERDTreePathNotifier.AddListener('refreshFlags', a:listener.OnRefreshFlags)
endfunction
" FUNCTION: s:findHunk(node, direction)
" Args:
" node: the current node
" direction: next(>0) or prev(<0)
"
" Returns:
" lineNum if the hunk found, -1 otherwise
function! s:findHunk(node, direction) abort
let l:ui = b:NERDTree.ui
let l:rootLn = l:ui.getRootLineNum()
let l:totalLn = line('$')
let l:currLn = l:ui.getLineNum(a:node)
let l:currLn = l:currLn <= l:rootLn ? l:rootLn+1 : l:currLn
let l:step = a:direction > 0 ? 1 : -1
let l:lines = a:direction > 0 ?
\ range(l:currLn+1, l:totalLn, l:step) + range(l:rootLn+1, l:currLn-1, l:step) :
\ range(l:currLn-1, l:rootLn+1, l:step) + range(l:totalLn, l:currLn+1, l:step)
for l:ln in l:lines
let l:path = s:path2str(l:ui.getPath(l:ln))
if s:listener.HasPath(l:path)
return l:ln
endif
endfor
return -1
endfunction
" vint: -ProhibitUnusedVariable
" FUNCTION: s:jumpToNextHunk(node) {{{2
function! s:jumpToNextHunk(node)
let l:ln = s:findHunk(a:node, 1)
if l:ln > 0
exec '' . l:ln
call s:logger.info('Jump to next hunk')
endif
endfunction
" FUNCTION: s:jumpToPrevHunk(node) {{{2
function! s:jumpToPrevHunk(node)
let l:ln = s:findHunk(a:node, -1)
if l:ln > 0
exec '' . l:ln
call s:logger.info('Jump to prev hunk')
endif
endfunction
" vint: +ProhibitUnusedVariable
" Function: s:SID() {{{2
function s:SID()
if !exists('s:sid')
let s:sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endif
return s:sid
endfun
" FUNCTION: s:setupNERDTreeKeyMappings {{{2
function! s:setupNERDTreeKeyMappings()
let l:s = '<SNR>' . s:SID() . '_'
call NERDTreeAddKeyMap({
\ 'key': g:NERDTreeGitStatusMapNextHunk,
\ 'scope': 'Node',
\ 'callback': l:s.'jumpToNextHunk',
\ 'quickhelpText': 'Jump to next git hunk' })
call NERDTreeAddKeyMap({
\ 'key': g:NERDTreeGitStatusMapPrevHunk,
\ 'scope': 'Node',
\ 'callback': l:s.'jumpToPrevHunk',
\ 'quickhelpText': 'Jump to prev git hunk' })
endfunction
" I don't know why, but vint said they are unused.
" vint: -ProhibitUnusedVariable
function! s:onNERDTreeDirChanged(path) abort
call s:getGitWorkdir(a:path)
endfunction
function! s:onNERDTreeInit(path) abort
call s:getGitWorkdir(a:path)
endfunction
" vint: +ProhibitUnusedVariable
function! s:enableLiveUpdate() abort
augroup nerdtreegitplugin_liveupdate
autocmd!
if g:NERDTreeGitStatusUpdateOnWrite
autocmd BufWritePost * silent! call s:onFileUpdate(expand('%:p'))
endif
if g:NERDTreeGitStatusUpdateOnCursorHold
autocmd CursorHold * silent! call s:onCursorHold(expand('%:p'))
endif
" TODO: is it necessary to pass the buffer name?
autocmd User FugitiveChanged silent! call s:onFileUpdate(expand('%:p'))
autocmd BufEnter NERD_tree_* call s:onNERDTreeInit(s:path2str(b:NERDTree.root.path))
augroup end
endfunction
function! s:disableLiveUpdate() abort
augroup nerdtreegitplugin_liveupdate
autocmd!
augroup end
endfunction
augroup nerdtreegitplugin
autocmd!
autocmd User NERDTreeInit call s:onNERDTreeInit(s:path2str(b:NERDTree.root.path))
autocmd User NERDTreeNewRoot call s:onNERDTreeDirChanged(s:path2str(b:NERDTree.root.path))
augroup end
call s:setupNERDTreeKeyMappings()
let s:listener = gitstatus#listener#New(g:)
call s:setupNERDTreeListeners(s:listener)

View File

@@ -0,0 +1,4 @@
if exists('$THEMIS_PROFILE')
execute 'profile' 'start' $THEMIS_PROFILE
profile! file ./autoload/*
endif

View File

@@ -0,0 +1,109 @@
let s:suite = themis#suite('Test for nerdtree-git-plugin')
let s:assert = themis#helper('assert')
call themis#helper('command').with(s:)
function! s:suite.Initializing() abort
NERDTreeFocus
call s:assert.exists('g:NERDTree')
call s:assert.exists('g:loaded_nerdtree_git_status')
call g:NERDTree.CursorToTreeWin()
call s:assert.exists('b:NERDTree')
endfunction
function! s:suite.BuildGitWorkdirCommand() abort
let l:cmd = gitstatus#util#BuildGitWorkdirCommand('/workdir', {})
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'rev-parse', '--show-toplevel'])
let l:cmd = gitstatus#util#BuildGitWorkdirCommand('/workdir', {'NERDTreeGitStatusGitBinPath': '/path/to/git'})
call s:assert.equal(l:cmd, ['/path/to/git', '-C', '/workdir', 'rev-parse', '--show-toplevel'])
endfunction
function! s:suite.BuildGitStatusCommand() abort
let l:cmd = gitstatus#util#BuildGitStatusCommand('/workdir', {})
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'status', '--porcelain=v2', '-z'])
let l:cmd = gitstatus#util#BuildGitStatusCommand('/workdir', {
\ 'NERDTreeGitStatusPorcelainVersion': 1
\ })
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'status', '--porcelain', '-z'])
let l:cmd = gitstatus#util#BuildGitStatusCommand('/workdir', {
\ 'NERDTreeGitStatusUntrackedFilesMode': 'all'
\ })
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'status', '--porcelain=v2', '-z', '--untracked-files=all'])
let l:cmd = gitstatus#util#BuildGitStatusCommand('/workdir', {
\ 'NERDTreeGitStatusShowIgnored': 1
\ })
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'status', '--porcelain=v2', '-z', '--ignored=traditional'])
let l:cmd = gitstatus#util#BuildGitStatusCommand('/workdir', {
\ 'NERDTreeGitStatusShowIgnored': 0
\ })
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'status', '--porcelain=v2', '-z'])
let l:cmd = gitstatus#util#BuildGitStatusCommand('/workdir', {
\ 'NERDTreeGitStatusIgnoreSubmodules': 'dirty'
\ })
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'status', '--porcelain=v2', '-z', '--ignore-submodules=dirty'])
let l:cmd = gitstatus#util#BuildGitStatusCommand('/workdir', {
\ 'NERDTreeGitStatusPorcelainVersion': 1,
\ 'NERDTreeGitStatusUntrackedFilesMode': 'all',
\ 'NERDTreeGitStatusShowIgnored': 1,
\ 'NERDTreeGitStatusIgnoreSubmodules': 'dirty'
\ })
call s:assert.equal(l:cmd, ['git', '-C', '/workdir', 'status', '--porcelain', '-z',
\ '--untracked-files=all',
\ '--ignored=traditional',
\ '--ignore-submodules=dirty'])
endfunction
function! s:suite.Logger() abort
let l:logger = gitstatus#log#NewLogger(1) " info
let l:messages = execute('messages')
call l:logger.debug('debug')
call s:assert.equal(execute('messages'), l:messages)
call l:logger.error('error')
call s:assert.equal(execute('messages'), l:messages . "\n[nerdtree-git-status] error")
endfunction
function! s:suite.CustomIndicator() abort
let g:NERDTreeGitStatusIndicatorMapCustom = {'Untracked': '~'}
let l:staged = gitstatus#getIndicator('Staged')
call s:assert.equal(gitstatus#getIndicator('Staged'), l:staged)
call s:assert.equal(gitstatus#getIndicator('Untracked'), '~')
" Vim(return):E716: Key not present in Dictionary
Throws /E716/ gitstatus#getIndicator('no such status')
endfunction
function! s:suite.UpdateParentDirsStatus() abort
let l:opts = {'NERDTreeGitStatusDirDirtyOnly': 1}
let l:root = '/root'
let l:cache = {}
let l:pathStr = '/root/dir1/dir2/dir3'
let l:cache[l:pathStr] = 'Untracked'
call gitstatus#util#UpdateParentDirsStatus(l:cache, l:root, l:pathStr, 'Untracked', l:opts)
call s:assert.equal({'/root/dir1': 'Dirty', '/root/dir1/dir2': 'Dirty', '/root/dir1/dir2/dir3': 'Untracked'}, l:cache)
let l:pathStr = '/root/dir1/dir2/file0'
let l:cache[l:pathStr] = 'Staged'
call gitstatus#util#UpdateParentDirsStatus(l:cache, l:root, l:pathStr, 'Staged', l:opts)
call s:assert.equal({'/root/dir1': 'Dirty', '/root/dir1/dir2': 'Dirty', '/root/dir1/dir2/dir3': 'Untracked', '/root/dir1/dir2/file0': 'Staged'}, l:cache)
let l:opts = {'NERDTreeGitStatusDirDirtyOnly': 0}
let l:cache = {}
let l:pathStr = '/root/dir1/dir2/dir3'
let l:cache[l:pathStr] = 'Untracked'
call gitstatus#util#UpdateParentDirsStatus(l:cache, l:root, l:pathStr, 'Untracked', l:opts)
call s:assert.equal({'/root/dir1': 'Untracked', '/root/dir1/dir2': 'Untracked', '/root/dir1/dir2/dir3': 'Untracked'}, l:cache)
let l:cache['/root/dir1/file1'] = 'Staged'
call gitstatus#util#UpdateParentDirsStatus(l:cache, l:root, '/root/dir1/file1', 'Staged', l:opts)
call s:assert.equal({'/root/dir1': 'Dirty','/root/dir1/file1': 'Staged', '/root/dir1/dir2': 'Untracked', '/root/dir1/dir2/dir3': 'Untracked'}, l:cache)
endfunction

View File

@@ -0,0 +1,46 @@
---
name: "Bug Report"
about: "NERDTree is misbehaving? Tell us about it."
labels: bug
---
<!-- Attention! Please Read!
Please fill out ALL the information below so that the issue can be fully understood. Omitting
information will delay the resolution of your issue. It will be labeled "Needs More Info", and
may be closed until there is enough information.
Keep in mind that others may have the same question in the future. The better your information,
the more likely they'll be able to help themselves.
-->
#### Self-Diagnosis
Before creating an issue, take some time to search these resources for an answer. It's possible that someone else has already seen and solved your issue.
- [old NERDTree issues](https://github.com/preservim/nerdtree/issues?q=is%3Aissue)
- NERDTree documentation - `:h NERDTree`
- [NERDTree Wiki](https://github.com/preservim/nerdtree/wiki)
- Other resources: <https://stackoverflow.com>, <https://vi.stackexchange.com>, etc.
#### Environment
- Operating System:
- Vim/Neovim version `:version`:
- NERDTree version, found on first line of quickhelp `?`:
- Are you using any of these NERDTree-dependent plugins? <!-- Check the boxes after creating the issue. -->
- [ ] [Xuyuanp/nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin)
- [ ] [ryanoasis/vim-devicons](https://github.com/ryanoasis/vim-devicons)
- [ ] [tiagofumo/vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight)
- [ ] [scrooloose/nerdtree-project-plugin](https://github.com/scrooloose/nerdtree-project-plugin)
- [ ] [PhilRunninger/nerdtree-buffer-ops](https://github.com/PhilRunninger/nerdtree-buffer-ops)
- [ ] [PhilRunninger/nerdtree-visual-selection](https://github.com/PhilRunninger/nerdtree-visual-selection)
- [ ] [jistr/vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs)
- [ ] Others (specify):
- Provide a minimal **.vimrc** file that will reproduce the issue.
```vim
```
#### Steps to Reproduce the Issue
1.
#### Current Behavior (Include screenshots where appropriate.)
#### Expected Result

View File

@@ -0,0 +1,8 @@
---
name: "Feature Request"
about: "What new feature are you requesting for NERDTree?"
labels: "feature request"
---
#### Description

View File

@@ -0,0 +1,13 @@
---
name: "General Question"
about: "Having trouble setting up NERDTree? Need clarification on a setting? Ask your question here."
labels: "general question"
---
Before creating an issue, take some time to search these resources. It's possible that someone else has already asked your question and gotten an answer.
- [old NERDTree issues](https://github.com/preservim/nerdtree/issues?q=is%3Aissue)
- NERDTree documentation - `:h NERDTree`
- [NERDTree Wiki](https://github.com/preservim/nerdtree/wiki)
- Other resource: <https://stackoverflow.com>, <https://vi.stackexchange.com>, etc.
#### State Your Question

View File

@@ -0,0 +1,22 @@
### Description of Changes
Closes # <!-- Enter the issue number this PR addresses. If none, remove this line. -->
---
### New Version Info
#### Author's Instructions
- [ ] Derive a new `MAJOR.MINOR.PATCH` version number. Increment the:
- `MAJOR` version when you make incompatible API changes
- `MINOR` version when you add functionality in a backwards-compatible manner
- `PATCH` version when you make backwards-compatible bug fixes
- [ ] Update [CHANGELOG.md](https://github.com/scrooloose/nerdtree/blob/master/CHANGELOG.md), following the established pattern.
#### Collaborator's Instructions
- [ ] Review [CHANGELOG.md](https://github.com/scrooloose/nerdtree/blob/master/CHANGELOG.md), suggesting a different version number if necessary.
- [ ] After merging, tag the commit using these (Mac-compatible) bash commands:
```bash
git checkout master
git pull
sed -n "$(grep -n -m2 '####' CHANGELOG.md | cut -f1 -d: | sed 'N;s/\n/,/')p" CHANGELOG.md | sed '$d'
git tag -a $(read -p "Tag Name: " tag;echo $tag) -m"$(git show --quiet --pretty=%s)";git push origin --tags
```

View File

@@ -0,0 +1,15 @@
name: Vint
on: [push, pull_request]
jobs:
vint:
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Run vint with reviewdog
uses: reviewdog/action-vint@v1.0.1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review

View File

@@ -0,0 +1,3 @@
*~
*.swp
tags

View File

@@ -0,0 +1,5 @@
cmdargs:
severity: style_problem
color: true
env:
neovim: false

View File

@@ -0,0 +1,307 @@
# NERDTree Change Log
<!-- Introduce a new MAJOR or MINOR version with a 4-hash header.
PATCH versions are listed from newest to oldest under their respective MAJOR.MINOR
version in an unordered list. The format is:
- **.PATCH**: Pull Request Title (PR Author) [PR Number](Link to PR)
-->
#### 6.10
- **.16**: Fix documentation errors. (lifecrisis) [#1269](https://github.com/preservim/nerdtree/pull/1269)
- **.15**: Ensure backward compatible testing of types. (lifecrisis) [#1266](https://github.com/preservim/nerdtree/pull/1266)
- **.14**: Replace trim() with a version-compatible alternative. (PhilRunninger) [#1265](https://github.com/preservim/nerdtree/pull/1265)
- **.13**: Change highlighting of bookmarks in the tree. (PhilRunninger) [#1261](https://github.com/preservim/nerdtree/pull/1261)
- **.12**: Answer the question about accessing files over scp or ftp. (PhilRunninger) [#1259](https://github.com/preservim/nerdtree/pull/1259)
- **.11**: Trim filenames created via the fs_menu (elanorigby) [#1243](https://github.com/preservim/nerdtree/pull/1243)
- **.10**: Improve F.A.Q. Answers and Issue Templates (PhilRunninger) [#1249](https://github.com/preservim/nerdtree/pull/1249)
- **.9**: `go` on a bookmark directory will NERDTreeFind it. (PhilRunninger) [#1236](https://github.com/preservim/nerdtree/pull/1236)
- **.8**: Put `Callback` function variables in local scope. (PhilRunninger) [#1230](https://github.com/preservim/nerdtree/pull/1230)
- **.7**: Fix mouse-clicking a file to open it. (PhilRunninger) [#1225](https://github.com/preservim/nerdtree/pull/1225)
- **.6**: Restore the default behavior of the `<CR>` key. (PhilRunninger) [#1221](https://github.com/preservim/nerdtree/pull/1221)
- **.5**: Fix `{'keepopen':0}` in NERDTreeCustomOpenArgs (PhilRunninger) [#1217](https://github.com/preservim/nerdtree/pull/1217)
- **.4**: Removed directory separator from sort key (Daniel E) [#1219](https://github.com/preservim/nerdtree/pull/1219)
- **.3**: Add new FAQ and answer: How to prevent buffers replacing NERDTree. (PhilRunninger) [#1215](https://github.com/preservim/nerdtree/pull/1215)
- **.2**: New menu command: Run a system command in this directory. (PhilRunninger) [#1214](https://github.com/preservim/nerdtree/pull/1214)
- **.1**: Escape quotation marks so they can be used in key mappings. (PhilRunninger) [#1213](https://github.com/preservim/nerdtree/pull/1213)
- **.0**: Enable full path specifications for NERDTreeIgnore (PhilRunninger) [#1207](https://github.com/preservim/nerdtree/pull/1207)
#### 6.9
- **.12**: Respect NERDTreeCustomOpenArgs when opening bookmark (przepompownia) [#1200](https://github.com/preservim/nerdtree/pull/1200)
- **.11**: Revamp the README. (buncis, PhilRunninger) [#1192](https://github.com/preservim/nerdtree/pull/1192), [#1193](https://github.com/preservim/nerdtree/pull/1193)
- **.10**: Open a mirrored NERDTree with correct width (PhilRunninger) [#1177](https://github.com/preservim/nerdtree/pull/1177)
- **.9**: Updated Readme, removed typo (H3RSKO) [#1167](https://github.com/preservim/nerdtree/pull/1167)
- **.8**: Refactor sort comparison functions, removing redundancy (PhilRunninger) [#1166](https://github.com/preservim/nerdtree/pull/1166)
- **.7**: Fix argument of `exists()` function calls checking for autocommands. (PhilRunninger) [#1165](https://github.com/preservim/nerdtree/pull/1165)
- **.6**: Don't use silent when raising User events (PhilRunninger) [#1164](https://github.com/preservim/nerdtree/pull/1164)
- **.5**: Fix highlight for file node. (pirey) [#1157](https://github.com/preservim/nerdtree/pull/1157)
- **.4**: Make sure symbolic links' flags are highlighted correctly. (PhilRunninger) [#1156](https://github.com/preservim/nerdtree/pull/1156)
- **.3**: Fix new NERDTrees' width when previous one was in the only window. (PhilRunninger) [#1153](https://github.com/preservim/nerdtree/pull/1153)
- **.2**: Fix the scope of several key mappings (lifecrisis, PhilRunninger) [#1151](https://github.com/preservim/nerdtree/pull/1151)
- **.1**: Respect user's `&shellslash` setting in CopyNode and RemoveNode functions (PhilRunninger) [#1150](https://github.com/preservim/nerdtree/pull/1150)
- **.0**: Enable opening bookmarks in split windows. (PhilRunninger) [#1144](https://github.com/preservim/nerdtree/pull/1144)
#### 6.8
- **.0**: Allow concealed characters to show another character. (PhilRunninger) [#1138](https://github.com/preservim/nerdtree/pull/1138)
#### 6.7
- **.15**: Add curly braces to the list of characters to be escaped. (PhilRunninger) [#1128](https://github.com/preservim/nerdtree/pull/1128)
- **.14**: Use backward-compatible `nerdtree#and()` in one place that was missed. (PhilRunninger) [#1134](https://github.com/preservim/nerdtree/pull/1134)
- **.13**: `cmd.exe /c start "" <filename>` for windows default viewer support. (J. Altayó) [#1130](https://github.com/preservim/nerdtree/pull/1130)
- **.12**: Fixed a bug that caused the file-tree construction to slow down significantly. (Eugenij-W) [#1126](https://github.com/preservim/nerdtree/pull/1126)
- **.11**: Fix exception in NERDTreeFind (on windows OS and If the file is located in the root directory of the disk) (Eugenij-W) [#1122](https://github.com/preservim/nerdtree/pull/1122)
- **.10**: Do not consider the tree root to be "cascadable". (lifecrisis) [#1120](https://github.com/preservim/nerdtree/pull/1120)
- **.9**: Force `:NERDTreeFocus` to allow events to be fired when switching windows. (PhilRunninger) [#1118](https://github.com/preservim/nerdtree/pull/1118)
- **.8**: Fix example code for the `NERDTreeAddKeyMap()` function. (PhilRunninger) [#1116](https://github.com/preservim/nerdtree/pull/1116)
- **.7**: Put `'%'` argument in `bufname()` for backwards compatibility. (PhilRunninger) [#1105](https://github.com/preservim/nerdtree/pull/1105)
- **.6**: If a file's already open in the window, don't edit it again. (PhilRunninger) [#1103](https://github.com/preservim/nerdtree/pull/1103)
- **.5**: Prevent unneeded tree creation in `:NERDTreeToggle[VCS] <path>` (PhilRunninger) [#1101](https://github.com/preservim/nerdtree/pull/1101)
- **.4**: Add missing calls to the `shellescape()` function (lifecrisis) [#1099](https://github.com/preservim/nerdtree/pull/1099)
- **.3**: Fix vsplit to not open empty buffers when opening previously closed file (AwkwardKore) [#1098](https://github.com/preservim/nerdtree/pull/1098)
- **.2**: Fix infinity loop (on winvim) in FindParentVCSRoot (Eugenij-W) [#1095](https://github.com/preservim/nerdtree/pull/1095)
- **.1**: File Move: Escape existing directory name when looking for open files. (PhilRunninger) [#1094](https://github.com/preservim/nerdtree/pull/1094)
- **.0**: Open the parent directory when revealing a non-existent file with :NERDTreeFind (bouk) [#1090](https://github.com/preservim/nerdtree/pull/1090)
#### 6.6
- **.1**: [add] How to install using dein.vim (kazukazuinaina) [#1087](https://github.com/preservim/nerdtree/pull/1087)
- **.0**: Add the ability to turn off directory arrows (PhilRunninger) [#1085](https://github.com/preservim/nerdtree/pull/1085)
#### 6.5
- **.0**: `NERDTreeToggle <start-directory>` always sets NERDTree root. (PhilRunninger) [#1083](https://github.com/preservim/nerdtree/pull/1083)
#### 6.4
- **.6**: NERDTreeFind shows expected message if file doesn't exist e.g. with vim-startify (andys8). [#1081](https://github.com/preservim/nerdtree/pull/1081)
- **.5**: Ensure events are (or aren't) being ignored correctly. (PhilRunninger) [#1080](https://github.com/preservim/nerdtree/pull/1080)
- **.4**: Prevent overwriting existing files/dirs on node move. (PhilRunninger) [#1079](https://github.com/preservim/nerdtree/pull/1079)
- **.3**: Fix regex that finds keyword for minimal menu. (PhilRunninger) [#1075](https://github.com/preservim/nerdtree/pull/1075)
- **.2**: Lint vimscript, fix errors and warnings, add CI job to review PRs (Caleb Maclennan) [#1071](https://github.com/preservim/nerdtree/pull/1071)
- **.1**: Ensure backward compatibility. v:t_func is not available before Vim 8.0 (Phil Runninger)
- **.0**: Allow use of function references as callbacks (HiPhish) [#1067](https://github.com/preservim/nerdtree/pull/1067)
#### 6.3
- **.0**: Add new command that behaves like NERDTreeToggle but defaults to the root of a VCS repository. (willfindlay) [#1060](https://github.com/preservim/nerdtree/pull/1060)
#### 6.2
- **.1**: Menu option, 'copy path to clipboard' is aware of VIM clipboard option (jhzn) [#1056](https://github.com/preservim/nerdtree/pull/1056)
- **.0**: Support tab-specific CWDs (PhilRunninger) [#1032](https://github.com/preservim/nerdtree/pull/1032)
#### 6.1
- **.4**: Add VIM built-in package management to read me file. (pesarkhobeee) [#1049](https://github.com/preservim/nerdtree/pull/1049)
- **.3**: Save/Set screen state also on WinLeave and WinEnter. (PhilRunninger) [#1048](https://github.com/preservim/nerdtree/pull/1048)
- **.2**: Wrap saveScreenState's statements in a try-catch block. (PhilRunninger) [#1047](https://github.com/preservim/nerdtree/pull/1047)
- **.1**: Catch errors when trying to read CHANGELOG.md. (PhilRunninger) [#1045](https://github.com/preservim/nerdtree/pull/1045)
- **.0**: If file path doesn't exist, :NERDTreeFind its parent directory instead. (PhilRunninger) [#1043](https://github.com/preservim/nerdtree/pull/1043)
#### 6.0
- **.1**: Reintroduce necessary variable mistakenly removed. (PhilRunninger) [#1040](https://github.com/preservim/nerdtree/pull/1040)
- **.0**: Make the behavior of window splits consistent (dragonxlwang, PhilRunninger) [#1035](https://github.com/preservim/nerdtree/pull/1035)
#### 5.3
- **.3**: Fix (p)ath not displaying in the minimal menu (tuzz) [#1038](https://github.com/preservim/nerdtree/pull/1038)
- **.2**: Enable events when closing NerdTree window. (PhilRunninger) [#1037](https://github.com/preservim/nerdtree/pull/1037)
- **.1**: Fix the `e` key mapping to use netrw if desired (PhilRunninger) [#1031](https://github.com/preservim/nerdtree/pull/1031)
- **.0**: Add file extension and size to sorting capabilities (PhilRunninger) [#1029](https://github.com/preservim/nerdtree/pull/1029)
#### 5.2
- **.9**: Suppress events for intermediate window/tab/buffer changes (PhilRunninger) [#1026](https://github.com/preservim/nerdtree/pull/1026)
- **.8**: Revert [#1019](https://github.com/preservim/nerdtree/pull/1019) to fix nvim artifacts and flickering. (PhilRunninger) [#1021](https://github.com/preservim/nerdtree/pull/1021)
- **.7**: Use :mode only in neovim. MacVim still needs to use :redraw! (PhilRunninger) [#1019](https://github.com/preservim/nerdtree/pull/1019)
- **.6**: In CHANGELOG.md and PR template, make reference to PR a true HTML link. (PhilRunninger) [#1017](https://github.com/preservim/nerdtree/pull/1017)
- **.5**: Use `:mode` instead of `:redraw!` when updating menu. (PhilRunninger) [#1016](https://github.com/preservim/nerdtree/pull/1016)
- **.4**: When searching for root line num, stop at end of file. (PhilRunninger) [#1015](https://github.com/preservim/nerdtree/pull/1015)
- **.3**: Fix `<CR>` key map on the bookmark (lkebin) [#1014](https://github.com/preservim/nerdtree/pull/1014)
- **.2**: Make Enter work on the `.. ( up a dir )` line (PhilRunninger) [#1013](https://github.com/preservim/nerdtree/pull/1013)
- **.1**: Fix nerdtree#version() on Windows. (PhilRunninger)
- **.0**: Expand functionality of `<CR>` mapping. (PhilRunninger) [#1011](https://github.com/preservim/nerdtree/pull/1011)
#### 5.1
- **.3**: Remove @mentions from PR template and change log. They weren't working. (PhilRunninger) [#1009](https://github.com/preservim/nerdtree/pull/1009)
- **.2**: Fix NERDTree opening with the wrong size. (PhilRunninger) [#1008](https://github.com/preservim/nerdtree/pull/1008)
- **.1**: Update Changelog and create PR Template (PhilRunninger) [#1007](https://github.com/preservim/nerdtree/pull/1007)
- **.0**: Too many changes for one patch...
- Refresh a dir_node if the file wasn't found in it, and look once more. (PhilRunninger) [#1005](https://github.com/preservim/nerdtree/pull/1005)
- Add a "copy path to clipboard" menu option (PhilRunninger) [#1002](https://github.com/preservim/nerdtree/pull/1002)
- Enable root refresh on "vim ." a different way than [#999](https://github.com/preservim/nerdtree/pull/999). (PhilRunninger) [#1001](https://github.com/preservim/nerdtree/pull/1001)
- Fix refreshroot (PhilRunninger) [#999](https://github.com/preservim/nerdtree/pull/999)
- Change version check to look for 703 not 730 (vhalis) [#994](https://github.com/preservim/nerdtree/pull/994)
- Change minimum vim (PhilRunninger) [#991](https://github.com/preservim/nerdtree/pull/991)
- Allow multi-character DirArrows (PhilRunninger) [#985](https://github.com/preservim/nerdtree/pull/985)
- Remove redraw! while still clearing last message empty string. (PhilRunninger) [#979](https://github.com/preservim/nerdtree/pull/979)
- fix `_initChildren` function value set to numChildrenCached error (terryding77) [#969](https://github.com/preservim/nerdtree/pull/969)
- On Windows, do a case-insensitive comparison of paths. (PhilRunninger) [#967](https://github.com/preservim/nerdtree/pull/967)
- Remove the **Please wait... DONE** messages. (PhilRunninger) [#966](https://github.com/preservim/nerdtree/pull/966)
- Smarter delimiter default (PhilRunninger) [#963](https://github.com/preservim/nerdtree/pull/963)
- Update directory .vimdc readme example (spencerdcarlson) [#961](https://github.com/preservim/nerdtree/pull/961)
- Preview bookmarks (PhilRunninger) [#956](https://github.com/preservim/nerdtree/pull/956)
- Add new value to NERDTreeQuitOnOpen to close bookmark table (PhilRunninger) [#955](https://github.com/preservim/nerdtree/pull/955)
- Add an :EditBookmarks command to edit the bookmarks file (PhilRunninger) [#954](https://github.com/preservim/nerdtree/pull/954)
- Before copying, turn off &shellslash. Restore after copy is finished. (PhilRunninger) [#952](https://github.com/preservim/nerdtree/pull/952)
- Set a maximum window size when zooming. (PhilRunninger) [#950](https://github.com/preservim/nerdtree/pull/950)
- Confirm the wipeout of a unsaved buffer whose file has been renamed. (PhilRunninger) [#949](https://github.com/preservim/nerdtree/pull/949)
- Escape a backslash so it can be used in a key mapping. (PhilRunninger) [#948](https://github.com/preservim/nerdtree/pull/948)
- Add a NERDTreeMinimalMenu feature (tuzz) [#938](https://github.com/preservim/nerdtree/pull/938)
- fixed root path error for windows (zcodes) [#935](https://github.com/preservim/nerdtree/pull/935)
- Restore getDirChildren for use in nerdtree-project-plugin. (PhilRunninger) [#929](https://github.com/preservim/nerdtree/pull/929)
- Document NERDTreeNodeDelimiter [#912](https://github.com/preservim/nerdtree/pull/912) (PhilRunninger) [#926](https://github.com/preservim/nerdtree/pull/926)
- Allow modification of menu keybindings (Leandros) [#923](https://github.com/preservim/nerdtree/pull/923)
- Add two more disqualifications for isCascadable(). (PhilRunninger) [#914](https://github.com/preservim/nerdtree/pull/914)
- Allow highlighting more than one flag. (kristijanhusak) [#908](https://github.com/preservim/nerdtree/pull/908)
- Support sorting files and directories by modification time. (PhilRunninger) [#901](https://github.com/preservim/nerdtree/pull/901)
- Parse . and .. from path string with trailing slash. (PhilRunninger) [#899](https://github.com/preservim/nerdtree/pull/899)
- Force sort to recalculate the cached sortKey. (PhilRunninger) [#898](https://github.com/preservim/nerdtree/pull/898)
- Add NERDTreeRefreshRoot command (wgfm) [#897](https://github.com/preservim/nerdtree/pull/897)
- Call Resolve on the file's path when calling :NERDTreeFind. (PhilRunninger) [#896](https://github.com/preservim/nerdtree/pull/896)
- Catch all errors, not just NERDTree errors. (PhilRunninger) [#894](https://github.com/preservim/nerdtree/pull/894)
- Fix typo in help file (lvoisin) [#892](https://github.com/preservim/nerdtree/pull/892)
- Make NERDTreeCreator set the `'nolist'` option (lifecrisis) [#889](https://github.com/preservim/nerdtree/pull/889)
- Refresh buffers after `m`, `m` operation on a folder (PhilRunninger) [#888](https://github.com/preservim/nerdtree/pull/888)
- Use a better arg for FINDSTR when using the m,l command in Windows. (PhilRunninger) [#887](https://github.com/preservim/nerdtree/pull/887)
- Fix the <C-J>/<C-K> motions, which currently fail with cascades (lifecrisis) [#886](https://github.com/preservim/nerdtree/pull/886)
- Function "s:UI.getLineNum()" doesn't always work on cascades. (lifecrisis) [#882](https://github.com/preservim/nerdtree/pull/882)
- NERDTreeCWD: reset CWD if changed by NERDTreeFocus (PhilRunninger) [#878](https://github.com/preservim/nerdtree/pull/878)
- Use <count>tabnext instead of <count>gt to allow users to remap gt. (PhilRunninger) [#877](https://github.com/preservim/nerdtree/pull/877)
- Do a case sensitive comparison of new/existing buffers. (PhilRunninger) [#875](https://github.com/preservim/nerdtree/pull/875)
- Fix opening sub-directories that have commas in their name. (PhilRunninger) [#873](https://github.com/preservim/nerdtree/pull/873)
- Add new command to open NERDTree in the root of a VCS repository. (PhilRunninger) [#872](https://github.com/preservim/nerdtree/pull/872)
- Make sure the path to the bookmarks file exists before writing it. (PhilRunninger) [#871](https://github.com/preservim/nerdtree/pull/871)
- Unzoom NERDTree when opening a file (PhilRunninger) [#870](https://github.com/preservim/nerdtree/pull/870)
- Support unusual characters in file and directory names (PhilRunninger) [#868](https://github.com/preservim/nerdtree/pull/868)
- Reword renamed-buffer prompt to be more clear (aflock) [#867](https://github.com/preservim/nerdtree/pull/867)
- Default to placing cursor on root when closing bookmark table (lifecrisis) [#866](https://github.com/preservim/nerdtree/pull/866)
- Fix issues with sorting of nodes (PhilRunninger) [#856](https://github.com/preservim/nerdtree/pull/856)
- Better OSX detection (bubba-h57) [#853](https://github.com/preservim/nerdtree/pull/853)
- Bugfix - ensure keymaps dictionary exists before using it (mnussbaum) [#852](https://github.com/preservim/nerdtree/pull/852)
- Decrease startup-time by avoiding linear-time iteration over key mappings (mnussbaum) [#851](https://github.com/preservim/nerdtree/pull/851)
- Add code to sort mappings in quickhelp (lifecrisis) [#849](https://github.com/preservim/nerdtree/pull/849)
- Use ":clearjumps" in new NERDTree windows (lifecrisis) [#844](https://github.com/preservim/nerdtree/pull/844)
- Like m-c did before, create parent directories if needed on m-m. (PhilRunninger) [#840](https://github.com/preservim/nerdtree/pull/840)
- BUGFIX: Repair a problem with the `'u'` mapping. (lifecrisis) [#838](https://github.com/preservim/nerdtree/pull/838)
- Make the NERDTree buffer writable when rendering it. (PhilRunninger) [#837](https://github.com/preservim/nerdtree/pull/837)
- Code cleanup: Remove unsupported bookmark table mappings (lifecrisis) [#835](https://github.com/preservim/nerdtree/pull/835)
- Replace strcharpart() with substitute() for backward compatibility (bravestarr) [#834](https://github.com/preservim/nerdtree/pull/834)
- Fixed error `unknown function strcharpart` for older versions of Vim (hav4ik) [#833](https://github.com/preservim/nerdtree/pull/833)
- Clear output when NERDTree menu is aborted (lifecrisis) [#832](https://github.com/preservim/nerdtree/pull/832)
- Display a path with multi-byte characters correctly when it is truncated (bravestarr) [#830](https://github.com/preservim/nerdtree/pull/830)
- Support revealing file and executing file with xdg-open for Linux (ngnmhieu) [#824](https://github.com/preservim/nerdtree/pull/824)
- If node isn't open, count children on disk before deleting. (PhilRunninger) [#822](https://github.com/preservim/nerdtree/pull/822)
- Add new variable g:NERDTreeRemoveFileCmd (kutsan) [#816](https://github.com/preservim/nerdtree/pull/816)
- Use a better check for existence of the NERDTree buffer. (PhilRunninger) [#814](https://github.com/preservim/nerdtree/pull/814)
- Fix focussing previous buffer when closing NERDTree (mrubli) [#801](https://github.com/preservim/nerdtree/pull/801)
- Update the docs for "NERDTreeStatusline" (lifecrisis) [#796](https://github.com/preservim/nerdtree/pull/796)
- BUGFIX: Unstable behavior in the "getPath()" method (lifecrisis) [#795](https://github.com/preservim/nerdtree/pull/795)
- Revert the bugfix from pull request [#785](https://github.com/preservim/nerdtree/pull/785) (lifecrisis) [#794](https://github.com/preservim/nerdtree/pull/794)
- BUGFIX: Allow ":NERDTreeFind" to discover hidden files (lifecrisis) [#786](https://github.com/preservim/nerdtree/pull/786)
- BUGFIX: Allow ":NERDTreeFind" to reveal new files (lifecrisis) [#785](https://github.com/preservim/nerdtree/pull/785)
- Add modelines (lifecrisis) [#782](https://github.com/preservim/nerdtree/pull/782)
- Change the type of completion used by NERDTreeFind (lifecrisis) [#781](https://github.com/preservim/nerdtree/pull/781)
- change NERDTreeFind with args (zhenyangze) [#778](https://github.com/preservim/nerdtree/pull/778)
- Style Choice: Using confirm() when deleting a bookmark (lifecrisis) [#777](https://github.com/preservim/nerdtree/pull/777)
- remove useless substitute when `file =~# "/$"` (skyblueee) [#773](https://github.com/preservim/nerdtree/pull/773)
- remove useless removeLeadingSpaces in _stripMarkup (skyblueee) [#772](https://github.com/preservim/nerdtree/pull/772)
- Make the "o" mapping consistent with "x" (lifecrisis) [#769](https://github.com/preservim/nerdtree/pull/769)
- Fix a problem with the "x" handler (lifecrisis) [#768](https://github.com/preservim/nerdtree/pull/768)
- Clean up the handler for the "x" mapping (lifecrisis) [#767](https://github.com/preservim/nerdtree/pull/767)
- Revert change to tab opening method (lifecrisis) [#766](https://github.com/preservim/nerdtree/pull/766)
- BUGFIX: Add back support for "b:NERDTreeRoot" (lifecrisis) [#765](https://github.com/preservim/nerdtree/pull/765)
- Fix broken "t" and "T" mappings, tabs now open at end (lifecrisis) [#759](https://github.com/preservim/nerdtree/pull/759)
- Update doc with already existing mapping variables (asnr) [#699](https://github.com/preservim/nerdtree/pull/699)
- Fix the broken g:NERDTreeBookmarksSort setting (lifecrisis) [#696](https://github.com/preservim/nerdtree/pull/696)
- Correct NERDTreeIgnore pattern in doc (cntoplolicon) [#648](https://github.com/preservim/nerdtree/pull/648)
- Remove empty segments when splitting path (sooth-sayer) [#574](https://github.com/preservim/nerdtree/pull/574)
- Suppress autocmds less agressively (wincent) [#578](https://github.com/preservim/nerdtree/pull/578) [#691](https://github.com/preservim/nerdtree/pull/691)
- Add an Issues template to ask for more info initially.
- Fix markdown headers in readme (josephfrazier) [#676](https://github.com/preservim/nerdtree/pull/676)
- Don't touch `@o` and `@h` registers when rendering
- Fix bug with files and directories with dollar signs (alegen) [#649](https://github.com/preservim/nerdtree/pull/649)
- Reuse/reopen existing window trees where possible [#244](https://github.com/preservim/nerdtree/pull/244)
- Remove NERDTree.previousBuf()
- Change color of arrow (Leeiio) [#630](https://github.com/preservim/nerdtree/pull/630)
- Improved a tip in README.markdown (ggicci) [#628](https://github.com/preservim/nerdtree/pull/628)
- Shorten delete confimration of empty directory to `y` (mikeperri) [#530](https://github.com/preservim/nerdtree/pull/530)
- Fix API call to open directory tree in window (devm33) [#533](https://github.com/preservim/nerdtree/pull/533)
- Change default arrows on non-Windows platforms (gwilk) [#546](https://github.com/preservim/nerdtree/pull/546)
- Update to README - combine cd and git clone (zwhitchcox) [#584](https://github.com/preservim/nerdtree/pull/584)
- Update to README - Tip: start NERDTree when vim starts (therealplato) [#593](https://github.com/preservim/nerdtree/pull/593)
- Escape filename when moving an open buffer (zacharyvoase) [#595](https://github.com/preservim/nerdtree/pull/595)
- Fixed incorrect :helptags command in README (curran) [#619](https://github.com/preservim/nerdtree/pull/619)
- Fixed incomplete escaping of folder arrows (adityanatraj) [#548](https://github.com/preservim/nerdtree/pull/548)
- Added NERDTreeCascadeSingleChildDir option (juanibiapina) [#558](https://github.com/preservim/nerdtree/pull/558)
- Replace strchars() with backward compatible workaround.
- Add support for copy command in Windows (SkylerLipthay) [#231](https://github.com/preservim/nerdtree/pull/231)
- Fixed typo in README.markdown - :Helptags -> :helptags
- Rename "primary" and "secondary" trees to "tab" and "window" trees.
- Move a bunch of buffer level variables into the NERDTree and UI classes.
- Display cascading dirs on one line to save vertical/horizontal space (matt-gardner: brainstorming/testing)
- Remove the old style UI - Remove `NERDTreeDirArrows` option.
- On windows default to + and ~ for expand/collapse directory symbols.
- Lots more refactoring. Move a bunch of b: level vars into b:NERDTree and friends.
#### 5.0.0
- Refactor the code significantly:
* Break the classes out into their own files.
* Make the majority of the code OO - previously large parts were effectively a tangle of "global" methods.
- Add an API to assign flags to nodes. This allows VCS plugins like https://github.com/Xuyuanp/nerdtree-git-plugin to exist. Thanks to **Xuyuanp** for helping design/test/build said API.
- add `scope` argument to the key map API see :help NERDTreeAddKeyMap()
- add magic [[dir]] and [[file]] flags to NERDTreeIgnore
- add support for custom path filters. See :help NERDTreeAddPathFilter()
- add path listener API. See :help NERDTreePathListenerAPI.
- expand the fs menu functionality to list file properties (PhilRunninger, apbarrero, JESii)
- make bookmarks work with `~` home shortcuts (hiberabyss)
- show OSX specific fsmenu options in regular vim on mac (evindor)
- make dir arrow icons configurable (PickRelated)
- optimise node sorting performance when opening large dirs (vtsang)
- make the root note render prettier by truncating it at a path slash (gcmt)
- remove NERDChristmasTree option - its always christmas now
- add "cascade" open and closing for dirs containing only another single dir. See :help NERDTreeCascadeOpenSingleChildDir (pendulm)
- Many other fixes, doc updates and contributions from: **actionshrimp**, **agrussellknives**, **alvan**, **AndrewRadev**, **cperl82** (*many small fixes*), **devmanhinton**, **egalpin**, **franksort**, **gastropoda**, **handcraftedbits**, **kelaban**, **lucascaton**, **mixvin**, **pendulm**, **SchDen**, **shanesmith**, **staeff**, **stephenprater**, **toiffel**, **Twinside**, **WoLpH**, **xiaodili**, **zhangoose**
#### 4.2.0
- Add NERDTreeDirArrows option to make the UI use pretty arrow chars instead of the old +~| chars to define the tree structure (sickill)
- shift the syntax highlighting out into its own syntax file (gnap)
- add some mac specific options to the filesystem menu - for macvim only (andersonfreitas)
- Add NERDTreeMinimalUI option to remove some non functional parts of the nerdtree ui (camthompson)
- tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the new behaviour (benjamingeiger)
- if no name is given to :Bookmark, make it default to the name of the target file/dir (minyoung)
- use `file` completion when doing copying, create, and move operations (EvanDotPro)
- lots of misc bug fixes from: **AndrewRadev**, **Bogdanov**, **camthompson**, **kml**, **mathias**, **paddyoloughlin**, **scottstvnsn**, **sdewald**, **Vitaly**, **wycats**, me RAWR!
#### 4.1.0
- features:
- NERDTreeFind to reveal the node for the current buffer in the tree, see `|NERDTreeFind|`. This effectively merges the FindInNERDTree plugin (by **Doug McInnes**) into the script.
- make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to **Stefan Ritter** and **Rémi Prévost**.
- truncate the root node if wider than the tree window. Thanks to **Victor Gonzalez**.
- bugfixes:
- really fix window state restoring
- fix some win32 path escaping issues. Thanks to **Stephan Baumeister**, **Ricky**, **jfilip1024**, and **Chris Chambers**.
#### 4.0.0
- add a new programmable menu system (see `:help NERDTreeMenu`).
- add new APIs to add menus/menu-items to the menu system as well as custom key mappings to the NERD tree buffer (see `:help NERDTreeAPI`).
- removed the old API functions
- added a mapping to maximize/restore the size of nerd tree window, thanks to Guillaume Duranceau for the patch. See :help NERDTree-A for details.
- fix a bug where secondary nerd trees (netrw hijacked trees) and NERDTreeQuitOnOpen didnt play nicely, thanks to **Curtis Harvey**.
- fix a bug where the script ignored directories whose name ended in a dot, thanks to **Aggelos Orfanakos** for the patch.
- fix a bug when using the x mapping on the tree root, thanks to **Bryan Venteicher** for the patch.
- fix a bug where the cursor position/window size of the nerd tree buffer wasnt being stored on closing the window, thanks to **Richard Hart**.
- fix a bug where NERDTreeMirror would mirror the wrong tree
#### 3.1.1
- fix a bug where a non-listed no-name buffer was getting created every time the tree windows was created, thanks to **Derek Wyatt** and **owen1**
- make `<CR>` behave the same as the `o` mapping
- some helptag fixes in the doc, thanks **strull**.
- fix a bug when using `:set nohidden` and opening a file where the previous buf was modified. Thanks **iElectric**.
- other minor fixes
#### 3.1.0
- New features:
- add mappings to open files in a vsplit, see `:help NERDTree-s` and `:help NERDTree-gs`
- make the statusline for the nerd tree window default to something hopefully more useful. See `:help 'NERDTreeStatusline'`
- Bugfixes:
- make the hijack netrw functionality work when vim is started with `vim <some dir>` (thanks to **Alf Mikula** for the patch).
- fix a bug where the CWD wasnt being changed for some operations even when NERDTreeChDirMode==2 (thanks to **Lucas S. Buchala**)
- add -bar to all the nerd tree :commands so they can chain with other :commands (thanks to **tpope**)
- fix bugs when ignorecase was set (thanks to **nach**)
- fix a bug with the relative path code (thanks to **nach**)
- fix a bug where doing a `:cd` would cause `:NERDTreeToggle` to fail (thanks **nach**)
#### 3.0.1
- Bugfixes:
- fix bugs with :NERDTreeToggle and :NERDTreeMirror when `'hidden'` was not set
- fix a bug where `:NERDTree <path>` would fail if `<path>` was relative and didnt start with a `./` or `../` Thanks to **James Kanze**.
- make the `q` mapping work with secondary (`:e <dir>` style) trees, thanks to **jamessan**
- fix a bunch of small bugs with secondary trees
- More insane refactoring.
#### 3.0.0
- hijack netrw so that doing an `:edit <directory>` will put a NERD tree in the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw'
- allow sharing of trees across tabs, see `:help :NERDTreeMirror`
- remove "top" and "bottom" as valid settings for NERDTreeWinPos
- change the `'<tab>'` mapping to `'i'`
- change the `'H'` mapping to `'I'`
- lots of refactoring

View File

@@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@@ -0,0 +1,227 @@
![Help Wanted](http://blog.ncce.org/wp-content/uploads/2013/12/help-wanted.jpg)
**NERDTree** is on the lookout for a new maintainer. See [issue #1280](https://github.com/preservim/nerdtree/issues/1280) to submit your name for consideration.
---
# The NERDTree [![Vint](https://github.com/preservim/nerdtree/workflows/Vint/badge.svg)](https://github.com/preservim/nerdtree/actions?workflow=Vint)
## Introduction
The NERDTree is a file system explorer for the Vim editor. Using this plugin, users can visually browse complex directory hierarchies, quickly open files for reading or editing, and perform basic file system operations.
![NERDTree Screenshot](https://github.com/preservim/nerdtree/raw/master/screenshot.png)
## Installation
Use your favorite plugin manager to install this plugin. [tpope/vim-pathogen](https://github.com/tpope/vim-pathogen), [VundleVim/Vundle.vim](https://github.com/VundleVim/Vundle.vim), [junegunn/vim-plug](https://github.com/junegunn/vim-plug), and [Shougo/dein.vim](https://github.com/Shougo/dein.vim) are some of the more popular ones. A lengthy discussion of these and other managers can be found on [vi.stackexchange.com](https://vi.stackexchange.com/questions/388/what-is-the-difference-between-the-vim-plugin-managers). Basic instructions are provided below, but please **be sure to read, understand, and follow all the safety rules that come with your ~~power tools~~ plugin manager.**
If you have no favorite, or want to manage your plugins without 3rd-party dependencies, consider using Vim 8+ packages, as described in Greg Hurrell's excellent Youtube video: [Vim screencast #75: Plugin managers](https://www.youtube.com/watch?v=X2_R3uxDN6g).
<details>
<summary>Pathogen</summary>
Pathogen is more of a runtime path manager than a plugin manager. You must clone the plugins' repositories yourself to a specific location, and Pathogen makes sure they are available in Vim.
1. In the terminal,
```bash
git clone https://github.com/preservim/nerdtree.git ~/.vim/bundle/nerdtree
```
1. In your `vimrc`,
```vim
call pathogen#infect()
syntax on
filetype plugin indent on
```
1. Restart Vim, and run `:helptags ~/.vim/bundle/nerdtree/doc/` or `:Helptags`.
</details>
<details>
<summary>Vundle</summary>
1. Install Vundle, according to its instructions.
1. Add the following text to your `vimrc`.
```vim
call vundle#begin()
Plugin 'preservim/nerdtree'
call vundle#end()
```
1. Restart Vim, and run the `:PluginInstall` statement to install your plugins.
</details>
<details>
<summary>Vim-Plug</summary>
1. Install Vim-Plug, according to its instructions.
1. Add the following text to your `vimrc`.
```vim
call plug#begin()
Plug 'preservim/nerdtree'
call plug#end()
```
1. Restart Vim, and run the `:PlugInstall` statement to install your plugins.
</details>
<details>
<summary>Dein</summary>
1. Install Dein, according to its instructions.
1. Add the following text to your `vimrc`.
```vim
call dein#begin()
call dein#add('preservim/nerdtree')
call dein#end()
```
1. Restart Vim, and run the `:call dein#install()` statement to install your plugins.
</details>
<details>
<summary>Vim 8+ packages</summary>
If you are using Vim version 8 or higher you can use its built-in package management; see `:help packages` for more information. Just run these commands in your terminal:
```bash
git clone https://github.com/preservim/nerdtree.git ~/.vim/pack/vendor/start/nerdtree
vim -u NONE -c "helptags ~/.vim/pack/vendor/start/nerdtree/doc" -c q
```
</details>
## Getting Started
After installing NERDTree, the best way to learn it is to turn on the Quick Help. Open NERDTree with the `:NERDTree` command, and press `?` to turn on the Quick Help, which will show you all the mappings and commands available in the NERDTree. Of course, your most complete source of information is the documentation: `:help NERDTree`.
## NERDTree Plugins
NERDTree can be extended with custom mappings and functions using its built-in API. The details of this API are described in the included documentation. Several plugins have been written, and are available on Github for installation like any other plugin. The plugins in this list are maintained (or not) by their respective owners, and certain combinations may be incompatible.
* [Xuyuanp/nerdtree-git-plugin](https://github.com/Xuyuanp/nerdtree-git-plugin): Shows Git status flags for files and folders in NERDTree.
* [ryanoasis/vim-devicons](https://github.com/ryanoasis/vim-devicons): Adds filetype-specific icons to NERDTree files and folders,
* [tiagofumo/vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight): Adds syntax highlighting to NERDTree based on filetype.
* [scrooloose/nerdtree-project-plugin](https://github.com/scrooloose/nerdtree-project-plugin): Saves and restores the state of the NERDTree between sessions.
* [PhilRunninger/nerdtree-buffer-ops](https://github.com/PhilRunninger/nerdtree-buffer-ops): 1) Highlights open files in a different color. 2) Closes a buffer directly from NERDTree.
* [PhilRunninger/nerdtree-visual-selection](https://github.com/PhilRunninger/nerdtree-visual-selection): Enables NERDTree to open, delete, move, or copy multiple Visually-selected files at once.
If any others should be listed, mention them in an issue or pull request.
## Frequently Asked Questions
In the answers to these questions, you will see code blocks that you can put in your `vimrc` file.
### How can I map a specific key or shortcut to open NERDTree?
NERDTree doesn't create any shortcuts outside of the NERDTree window, so as not to overwrite any of your other shortcuts. Use the `nnoremap` command in your `vimrc`. You, of course, have many keys and NERDTree commands to choose from. Here are but a few examples.
```vim
nnoremap <leader>n :NERDTreeFocus<CR>
nnoremap <C-n> :NERDTree<CR>
nnoremap <C-t> :NERDTreeToggle<CR>
nnoremap <C-f> :NERDTreeFind<CR>
```
### How do I open NERDTree automatically when Vim starts?
Each code block below is slightly different, as described in the `" Comment lines`.
```vim
" Start NERDTree and leave the cursor in it.
autocmd VimEnter * NERDTree
```
---
```vim
" Start NERDTree and put the cursor back in the other window.
autocmd VimEnter * NERDTree | wincmd p
```
---
```vim
" Start NERDTree when Vim is started without file arguments.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists('s:std_in') | NERDTree | endif
```
---
```vim
" Start NERDTree. If a file is specified, move the cursor to its window.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * NERDTree | if argc() > 0 || exists("s:std_in") | wincmd p | endif
```
---
```vim
" Start NERDTree, unless a file or session is specified, eg. vim -S session_file.vim.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists('s:std_in') && v:this_session == '' | NERDTree | endif
```
---
```vim
" Start NERDTree when Vim starts with a directory argument.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') |
\ execute 'NERDTree' argv()[0] | wincmd p | enew | execute 'cd '.argv()[0] | endif
```
### How can I close Vim or a tab automatically when NERDTree is the last window?
```vim
" Exit Vim if NERDTree is the only window remaining in the only tab.
autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif
```
---
```vim
" Close the tab if NERDTree is the only window remaining in it.
autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif
```
### How can I prevent other buffers replacing NERDTree in its window?
```vim
" If another buffer tries to replace NERDTree, put it in the other window, and bring back NERDTree.
autocmd BufEnter * if bufname('#') =~ 'NERD_tree_\d\+' && bufname('%') !~ 'NERD_tree_\d\+' && winnr('$') > 1 |
\ let buf=bufnr() | buffer# | execute "normal! \<C-W>w" | execute 'buffer'.buf | endif
```
### Can I have the same NERDTree on every tab automatically?
```vim
" Open the existing NERDTree on each new tab.
autocmd BufWinEnter * if getcmdwintype() == '' | silent NERDTreeMirror | endif
```
or change your NERDTree-launching shortcut key like so:
```vim
" Mirror the NERDTree before showing it. This makes it the same on all tabs.
nnoremap <C-n> :NERDTreeMirror<CR>:NERDTreeFocus<CR>
```
### How can I change the default arrows?
```vim
let g:NERDTreeDirArrowExpandable = '?'
let g:NERDTreeDirArrowCollapsible = '?'
```
The preceding values are the non-Windows default arrow symbols. Setting these variables to empty strings will remove the arrows completely and shift the entire tree two character positions to the left. See `:h NERDTreeDirArrowExpandable` for more details.
### Can NERDTree access remote files via scp or ftp?
Short answer: No, and there are no plans to add that functionality. However, Vim ships with a plugin that does just that. It's called netrw, and by adding the following lines to your `.vimrc`, you can use it to open files over the `scp:`, `ftp:`, or other protocols, while still using NERDTree for all local files. The function seamlessly makes the decision to open NERDTree or netrw, and other supported protocols can be added to the regular expression.
```vim
" Function to open the file or NERDTree or netrw.
" Returns: 1 if either file explorer was opened; otherwise, 0.
function! s:OpenFileOrExplorer(...)
if a:0 == 0 || a:1 == ''
NERDTree
elseif filereadable(a:1)
execute 'edit '.a:1
return 0
elseif a:1 =~? '^\(scp\|ftp\)://' " Add other protocols as needed.
execute 'Vexplore '.a:1
elseif isdirectory(a:1)
execute 'NERDTree '.a:1
endif
return 1
endfunction
" Auto commands to handle OS commandline arguments
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc()==1 && !exists('s:std_in') | if <SID>OpenFileOrExplorer(argv()[0]) | wincmd p | enew | wincmd p | endif | endif
" Command to call the OpenFileOrExplorer function.
command! -n=? -complete=file -bar Edit :call <SID>OpenFileOrExplorer('<args>')
" Command-mode abbreviation to replace the :edit Vim command.
cnoreabbrev e Edit
```

View File

@@ -0,0 +1 @@
theme: jekyll-theme-cayman

View File

@@ -0,0 +1,249 @@
if exists('g:loaded_nerdtree_autoload')
finish
endif
let g:loaded_nerdtree_autoload = 1
let s:rootNERDTreePath = resolve(expand('<sfile>:p:h:h'))
"FUNCTION: nerdtree#version(...) {{{1
" If any value is given as an argument, the entire line of text from the
" change log is shown for the current version; otherwise, only the version
" number is shown.
function! nerdtree#version(...) abort
let l:text = 'Unknown'
try
let l:changelog = readfile(join([s:rootNERDTreePath, 'CHANGELOG.md'], nerdtree#slash()))
let l:line = 0
while l:line <= len(l:changelog)
if l:changelog[l:line] =~# '\d\+\.\d\+'
let l:text = substitute(l:changelog[l:line], '.*\(\d\+.\d\+\).*', '\1', '')
let l:text .= substitute(l:changelog[l:line+1], '^.\{-}\(\.\d\+\).\{-}:\(.*\)', a:0>0 ? '\1:\2' : '\1', '')
break
endif
let l:line += 1
endwhile
catch
endtry
return l:text
endfunction
" SECTION: General Functions {{{1
"============================================================
" FUNCTION: nerdtree#closeTreeOnOpen() {{{2
function! nerdtree#closeTreeOnOpen() abort
return g:NERDTreeQuitOnOpen == 1 || g:NERDTreeQuitOnOpen == 3
endfunction
" FUNCTION: nerdtree#closeBookmarksOnOpen() {{{2
function! nerdtree#closeBookmarksOnOpen() abort
return g:NERDTreeQuitOnOpen == 2 || g:NERDTreeQuitOnOpen == 3
endfunction
" FUNCTION: nerdtree#slash() {{{2
" Return the path separator used by the underlying file system. Special
" consideration is taken for the use of the 'shellslash' option on Windows
" systems.
function! nerdtree#slash() abort
if nerdtree#runningWindows()
if exists('+shellslash') && &shellslash
return '/'
endif
return '\'
endif
return '/'
endfunction
"FUNCTION: nerdtree#checkForBrowse(dir) {{{2
"inits a window tree in the current buffer if appropriate
function! nerdtree#checkForBrowse(dir) abort
if !isdirectory(a:dir)
return
endif
if s:reuseWin(a:dir)
return
endif
call g:NERDTreeCreator.CreateWindowTree(a:dir)
endfunction
"FUNCTION: s:reuseWin(dir) {{{2
"finds a NERDTree buffer with root of dir, and opens it.
function! s:reuseWin(dir) abort
let path = g:NERDTreePath.New(fnamemodify(a:dir, ':p'))
for i in range(1, bufnr('$'))
unlet! nt
let nt = getbufvar(i, 'NERDTree')
if empty(nt)
continue
endif
if nt.isWinTree() && nt.root.path.equals(path)
call nt.setPreviousBuf(bufnr('#'))
exec 'buffer ' . i
return 1
endif
endfor
return 0
endfunction
" FUNCTION: nerdtree#completeBookmarks(A,L,P) {{{2
" completion function for the bookmark commands
function! nerdtree#completeBookmarks(A,L,P) abort
return filter(g:NERDTreeBookmark.BookmarkNames(), 'v:val =~# "^' . a:A . '"')
endfunction
"FUNCTION: nerdtree#compareNodes(n1, n2) {{{2
function! nerdtree#compareNodes(n1, n2) abort
return nerdtree#compareNodePaths(a:n1.path, a:n2.path)
endfunction
"FUNCTION: nerdtree#compareNodePaths(p1, p2) {{{2
function! nerdtree#compareNodePaths(p1, p2) abort
let sortKey1 = a:p1.getSortKey()
let sortKey2 = a:p2.getSortKey()
let i = 0
while i < min([len(sortKey1), len(sortKey2)])
" Compare chunks upto common length.
" If chunks have different type, the one which has
" integer type is the lesser.
if type(sortKey1[i]) == type(sortKey2[i])
if sortKey1[i] <# sortKey2[i]
return - 1
elseif sortKey1[i] ># sortKey2[i]
return 1
endif
elseif type(sortKey1[i]) == type(0)
return -1
elseif type(sortKey2[i]) == type(0)
return 1
endif
let i += 1
endwhile
" Keys are identical upto common length.
" The key which has smaller chunks is the lesser one.
if len(sortKey1) < len(sortKey2)
return -1
elseif len(sortKey1) > len(sortKey2)
return 1
else
return 0
endif
endfunction
" FUNCTION: nerdtree#deprecated(func, [msg]) {{{2
" Issue a deprecation warning for a:func. If a second arg is given, use this
" as the deprecation message
function! nerdtree#deprecated(func, ...) abort
let msg = a:0 ? a:func . ' ' . a:1 : a:func . ' is deprecated'
if !exists('s:deprecationWarnings')
let s:deprecationWarnings = {}
endif
if !has_key(s:deprecationWarnings, a:func)
let s:deprecationWarnings[a:func] = 1
echomsg msg
endif
endfunction
" FUNCTION: nerdtree#exec(cmd, ignoreAll) {{{2
" Same as :exec cmd but, if ignoreAll is TRUE, set eventignore=all for the duration
function! nerdtree#exec(cmd, ignoreAll) abort
let old_ei = &eventignore
if a:ignoreAll
set eventignore=all
endif
try
exec a:cmd
finally
let &eventignore = old_ei
endtry
endfunction
" FUNCTION: nerdtree#has_opt(options, name) {{{2
function! nerdtree#has_opt(options, name) abort
return has_key(a:options, a:name) && a:options[a:name] ==# 1
endfunction
" FUNCTION: nerdtree#loadClassFiles() {{{2
function! nerdtree#loadClassFiles() abort
runtime lib/nerdtree/path.vim
runtime lib/nerdtree/menu_controller.vim
runtime lib/nerdtree/menu_item.vim
runtime lib/nerdtree/key_map.vim
runtime lib/nerdtree/bookmark.vim
runtime lib/nerdtree/tree_file_node.vim
runtime lib/nerdtree/tree_dir_node.vim
runtime lib/nerdtree/opener.vim
runtime lib/nerdtree/creator.vim
runtime lib/nerdtree/flag_set.vim
runtime lib/nerdtree/nerdtree.vim
runtime lib/nerdtree/ui.vim
runtime lib/nerdtree/event.vim
runtime lib/nerdtree/notifier.vim
endfunction
" FUNCTION: nerdtree#postSourceActions() {{{2
function! nerdtree#postSourceActions() abort
call g:NERDTreeBookmark.CacheBookmarks(1)
call nerdtree#ui_glue#createDefaultBindings()
"load all nerdtree plugins
runtime! nerdtree_plugin/**/*.vim
endfunction
"FUNCTION: nerdtree#runningWindows(dir) {{{2
function! nerdtree#runningWindows() abort
return has('win16') || has('win32') || has('win64')
endfunction
"FUNCTION: nerdtree#runningCygwin(dir) {{{2
function! nerdtree#runningCygwin() abort
return has('win32unix')
endfunction
" SECTION: View Functions {{{1
"============================================================
"FUNCTION: nerdtree#echo {{{2
"A wrapper for :echo. Appends 'NERDTree:' on the front of all messages
"
"Args:
"msg: the message to echo
function! nerdtree#echo(msg) abort
redraw
echomsg empty(a:msg) ? '' : ('NERDTree: ' . a:msg)
endfunction
"FUNCTION: nerdtree#echoError {{{2
"Wrapper for nerdtree#echo, sets the message type to errormsg for this message
"Args:
"msg: the message to echo
function! nerdtree#echoError(msg) abort
echohl errormsg
call nerdtree#echo(a:msg)
echohl normal
endfunction
"FUNCTION: nerdtree#echoWarning {{{2
"Wrapper for nerdtree#echo, sets the message type to warningmsg for this message
"Args:
"msg: the message to echo
function! nerdtree#echoWarning(msg) abort
echohl warningmsg
call nerdtree#echo(a:msg)
echohl normal
endfunction
"FUNCTION: nerdtree#renderView {{{2
function! nerdtree#renderView() abort
call b:NERDTree.render()
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -0,0 +1,732 @@
if exists('g:loaded_nerdtree_ui_glue_autoload')
finish
endif
let g:loaded_nerdtree_ui_glue_autoload = 1
" FUNCTION: nerdtree#ui_glue#createDefaultBindings() {{{1
function! nerdtree#ui_glue#createDefaultBindings() abort
let s = '<SNR>' . s:SID() . '_'
call NERDTreeAddKeyMap({ 'key': '<MiddleMouse>', 'scope': 'all', 'callback': s . 'handleMiddleMouse' })
call NERDTreeAddKeyMap({ 'key': '<LeftRelease>', 'scope': 'all', 'callback': s.'handleLeftClick' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'DirNode', 'callback': s.'activateDirNode' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'FileNode', 'callback': s.'activateFileNode' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'Bookmark', 'callback': s.'activateBookmark' })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': 'all', 'callback': s.'activateAll' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'FileNode', 'callback': s.'customOpenFile'})
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'DirNode', 'callback': s.'customOpenDir'})
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'Bookmark', 'callback': s.'customOpenBookmark'})
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCustomOpen, 'scope':'all', 'callback': s.'activateAll' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'DirNode', 'callback': s.'activateDirNode' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'FileNode', 'callback': s.'activateFileNode' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'Bookmark', 'callback': s.'activateBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': 'Bookmark', 'callback': s.'previewBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': 'all', 'callback': s.'activateAll' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': 'FileNode', 'callback': s.'openHSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': 'Bookmark', 'callback': s.'openHSplitBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': 'FileNode', 'callback': s.'openVSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': 'Bookmark', 'callback': s.'openVSplitBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': 'FileNode', 'callback': s.'previewNodeCurrent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': 'FileNode', 'callback': s.'previewNodeHSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': 'Bookmark', 'callback': s.'previewNodeHSplitBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': 'FileNode', 'callback': s.'previewNodeVSplit' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': 'Bookmark', 'callback': s.'previewNodeVSplitBookmark' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenRecursively, 'scope': 'DirNode', 'callback': s.'openNodeRecursively' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdir, 'scope': 'all', 'callback': s . 'upDirCurrentRootClosed' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdirKeepOpen, 'scope': 'all', 'callback': s . 'upDirCurrentRootOpen' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChangeRoot, 'scope': 'Node', 'callback': s . 'chRoot' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChdir, 'scope': 'Node', 'callback': s.'chCwd' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': 'all', 'callback': s.'closeTreeWindow' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': 'all', 'callback': 'nerdtree#ui_glue#chRootCwd' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': 'all', 'callback': s.'refreshRoot' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': 'Node', 'callback': s.'refreshCurrent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': 'all', 'callback': s.'displayHelp' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': 'all', 'callback': s.'toggleZoom' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': 'all', 'callback': s.'toggleShowHidden' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': 'all', 'callback': s.'toggleIgnoreFilter' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': 'all', 'callback': s.'toggleShowFiles' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': 'all', 'callback': s.'toggleShowBookmarks' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': 'Node', 'callback': s.'closeCurrentDir' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': 'DirNode', 'callback': s.'closeChildren' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': 'Node', 'callback': s.'showMenu' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': 'Node', 'callback': s.'jumpToParent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': 'Node', 'callback': s.'jumpToFirstChild' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': 'Node', 'callback': s.'jumpToLastChild' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': 'all', 'callback': s.'jumpToRoot' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': 'Node', 'callback': s.'jumpToNextSibling' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': 'Node', 'callback': s.'jumpToPrevSibling' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Node', 'callback': s . 'openInNewTab' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Node', 'callback': s . 'openInNewTabSilent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': 'Bookmark', 'callback': s . 'openInNewTab' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': 'Bookmark', 'callback': s . 'openInNewTabSilent' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': 'DirNode', 'callback': s.'openExplorer' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': 'FileNode', 'callback': s.'openExplorer' })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': 'Bookmark', 'callback': s.'deleteBookmark' })
endfunction
"SECTION: Interface bindings {{{1
"============================================================
"FUNCTION: s:customOpenFile() {{{1
" Open file node with the 'custom' key, initially <CR>.
function! s:customOpenFile(node) abort
call a:node.activate(s:initCustomOpenArgs().file)
endfunction
"FUNCTION: s:customOpenDir() {{{1
" Open directory node with the 'custom' key, initially <CR>.
function! s:customOpenDir(node) abort
call s:activateDirNode(a:node, s:initCustomOpenArgs().dir)
endfunction
"FUNCTION: s:customOpenBookmark() {{{1
" Open bookmark node with the 'custom' key, initially <CR>.
function! s:customOpenBookmark(node) abort
if a:node.path.isDirectory
call a:node.activate(b:NERDTree, s:initCustomOpenArgs().dir)
else
call a:node.activate(b:NERDTree, s:initCustomOpenArgs().file)
endif
endfunction
"FUNCTION: s:initCustomOpenArgs() {{{1
function! s:initCustomOpenArgs() abort
let l:defaultOpenArgs = {'file': {'reuse': 'all', 'where': 'p', 'keepopen':!nerdtree#closeTreeOnOpen()}, 'dir': {}}
try
let g:NERDTreeCustomOpenArgs = get(g:, 'NERDTreeCustomOpenArgs', {})
call extend(g:NERDTreeCustomOpenArgs, l:defaultOpenArgs, 'keep')
catch /^Vim(\a\+):E712:/
call nerdtree#echoWarning('g:NERDTreeCustomOpenArgs is not set properly. Using default value.')
let g:NERDTreeCustomOpenArgs = l:defaultOpenArgs
finally
return g:NERDTreeCustomOpenArgs
endtry
endfunction
"FUNCTION: s:activateAll() {{{1
"handle the user activating the updir line
function! s:activateAll() abort
if getline('.') ==# g:NERDTreeUI.UpDirLine()
return nerdtree#ui_glue#upDir(0)
endif
endfunction
" FUNCTION: s:activateDirNode(directoryNode, options) {{{1
" Open a directory with optional options
function! s:activateDirNode(directoryNode, ...) abort
if a:directoryNode.isRoot() && a:directoryNode.isOpen
call nerdtree#echo('cannot close tree root')
return
endif
call a:directoryNode.activate((a:0 > 0) ? a:1 : {})
endfunction
"FUNCTION: s:activateFileNode() {{{1
"handle the user activating a tree node
function! s:activateFileNode(node) abort
call a:node.activate({'reuse': 'all', 'where': 'p', 'keepopen': !nerdtree#closeTreeOnOpen()})
endfunction
"FUNCTION: s:activateBookmark(bookmark) {{{1
"handle the user activating a bookmark
function! s:activateBookmark(bm) abort
call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'p', 'keepopen': !nerdtree#closeTreeOnOpen()} : {})
endfunction
" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1
" Associate the current node with the given name
function! nerdtree#ui_glue#bookmarkNode(...) abort
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode !=# {}
let name = a:1
if empty(name)
let name = currentNode.path.getLastPathComponent(0)
endif
try
call currentNode.bookmark(name)
call b:NERDTree.render()
catch /^NERDTree.IllegalBookmarkNameError/
call nerdtree#echo('bookmark names must not contain spaces')
endtry
else
call nerdtree#echo('select a node first')
endif
endfunction
" FUNCTION: s:chCwd(node) {{{1
function! s:chCwd(node) abort
try
call a:node.path.changeToDir()
catch /^NERDTree.PathChangeError/
call nerdtree#echoWarning('could not change cwd')
endtry
endfunction
" FUNCTION: s:chRoot(node) {{{1
" changes the current root to the selected one
function! s:chRoot(node) abort
call b:NERDTree.changeRoot(a:node)
endfunction
" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1
" Change the NERDTree root to match the current working directory.
function! nerdtree#ui_glue#chRootCwd() abort
NERDTreeCWD
endfunction
" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1
function! nerdtree#ui_glue#clearBookmarks(bookmarks) abort
if a:bookmarks ==# ''
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode !=# {}
call currentNode.clearBookmarks()
endif
else
for name in split(a:bookmarks, ' ')
let bookmark = g:NERDTreeBookmark.BookmarkFor(name)
call bookmark.delete()
endfor
endif
call b:NERDTree.root.refresh()
call b:NERDTree.render()
endfunction
" FUNCTION: s:closeChildren(node) {{{1
" closes all childnodes of the current node
function! s:closeChildren(node) abort
call a:node.closeChildren()
call b:NERDTree.render()
call a:node.putCursorHere(0, 0)
endfunction
" FUNCTION: s:closeCurrentDir(node) {{{1
" Close the parent directory of the current node.
function! s:closeCurrentDir(node) abort
if a:node.isRoot()
call nerdtree#echo('cannot close parent of tree root')
return
endif
let l:parent = a:node.parent
while l:parent.isCascadable()
let l:parent = l:parent.parent
endwhile
if l:parent.isRoot()
call nerdtree#echo('cannot close tree root')
return
endif
call l:parent.close()
call b:NERDTree.render()
call l:parent.putCursorHere(0, 0)
endfunction
" FUNCTION: s:closeTreeWindow() {{{1
" close the tree window
function! s:closeTreeWindow() abort
if b:NERDTree.isWinTree() && b:NERDTree.previousBuf() !=# -1
exec 'buffer ' . b:NERDTree.previousBuf()
else
if winnr('$') > 1
call g:NERDTree.Close()
else
call nerdtree#echo('Cannot close last window')
endif
endif
endfunction
" FUNCTION: s:deleteBookmark(bookmark) {{{1
" Prompt the user to confirm the deletion of the selected bookmark.
function! s:deleteBookmark(bookmark) abort
let l:message = 'Delete the bookmark "' . a:bookmark.name
\ . '" from the bookmark list?'
let l:choices = "&Yes\n&No"
echo | redraw
let l:selection = confirm(l:message, l:choices, 1, 'Warning')
if l:selection !=# 1
call nerdtree#echo('bookmark not deleted')
return
endif
try
call a:bookmark.delete()
silent call b:NERDTree.root.refresh()
call b:NERDTree.render()
echo | redraw
catch /^NERDTree/
call nerdtree#echoWarning('could not remove bookmark')
endtry
endfunction
" FUNCTION: s:displayHelp() {{{1
" toggles the help display
function! s:displayHelp() abort
call b:NERDTree.ui.toggleHelp()
call b:NERDTree.render()
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:findAndRevealPath(pathStr) {{{1
function! s:findAndRevealPath(pathStr) abort
let l:pathStr = !empty(a:pathStr) ? a:pathStr : expand('%:p')
let l:revealOpts = {}
if empty(l:pathStr)
call nerdtree#echoWarning('no file for the current buffer')
return
endif
if !filereadable(l:pathStr)
let l:pathStr = fnamemodify(l:pathStr, ':h')
let l:revealOpts['open'] = 1
endif
try
let l:pathStr = g:NERDTreePath.Resolve(l:pathStr)
let l:pathObj = g:NERDTreePath.New(l:pathStr)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echoWarning('invalid path')
return
endtry
if !g:NERDTree.ExistsForTab()
try
let l:cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo('current directory does not exist.')
let l:cwd = l:pathObj.getParent()
endtry
if l:pathObj.isUnder(l:cwd)
call g:NERDTreeCreator.CreateTabTree(l:cwd.str())
else
call g:NERDTreeCreator.CreateTabTree(l:pathObj.getParent().str())
endif
else
NERDTreeFocus
if !l:pathObj.isUnder(b:NERDTree.root.path)
call s:chRoot(g:NERDTreeDirNode.New(l:pathObj.getParent(), b:NERDTree))
endif
endif
if l:pathObj.isHiddenUnder(b:NERDTree.root.path)
call b:NERDTree.ui.setShowHidden(1)
endif
let l:node = b:NERDTree.root.reveal(l:pathObj, l:revealOpts)
call b:NERDTree.render()
call l:node.putCursorHere(1, 0)
endfunction
"FUNCTION: s:handleLeftClick() {{{1
"Checks if the click should open the current node
function! s:handleLeftClick() abort
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode !=# {}
"the dir arrows are multibyte chars, and vim's string functions only
"deal with single bytes - so split the line up with the hack below and
"take the line substring manually
let line = split(getline(line('.')), '\zs')
let startToCur = ''
for i in range(0,len(line)-1)
let startToCur .= line[i]
endfor
if currentNode.path.isDirectory
if startToCur =~# g:NERDTreeUI.MarkupReg() && startToCur =~# '[+~'.g:NERDTreeDirArrowExpandable.g:NERDTreeDirArrowCollapsible.'] \?$'
call currentNode.activate()
return
endif
endif
if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3
let char = strpart(startToCur, strlen(startToCur)-1, 1)
if char !~# g:NERDTreeUI.MarkupReg()
if currentNode.path.isDirectory
call currentNode.activate()
else
call currentNode.activate({'reuse': 'all', 'where': 'p', 'keepopen':!nerdtree#closeTreeOnOpen()})
endif
return
endif
endif
endif
endfunction
" FUNCTION: s:handleMiddleMouse() {{{1
function! s:handleMiddleMouse() abort
" A middle mouse click does not automatically position the cursor as one
" would expect. Forcing the execution of a regular left mouse click here
" fixes this problem.
execute "normal! \<LeftMouse>"
let l:currentNode = g:NERDTreeFileNode.GetSelected()
if empty(l:currentNode)
call nerdtree#echoError('use the pointer to select a node')
return
endif
if l:currentNode.path.isDirectory
call l:currentNode.openExplorer()
else
call l:currentNode.open({'where': 'h'})
endif
endfunction
" FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1
"this is needed since I cant figure out how to invoke dict functions from a
"key map
function! nerdtree#ui_glue#invokeKeyMap(key) abort
call g:NERDTreeKeyMap.Invoke(a:key)
endfunction
" FUNCTION: s:jumpToFirstChild(node) {{{1
function! s:jumpToFirstChild(node) abort
call s:jumpToChild(a:node, 0)
endfunction
" FUNCTION: s:jumpToLastChild(node) {{{1
function! s:jumpToLastChild(node) abort
call s:jumpToChild(a:node, 1)
endfunction
" FUNCTION: s:jumpToChild(node, last) {{{1
" Jump to the first or last child node at the same file system level.
"
" Args:
" node: the node on which the cursor currently sits
" last: 1 (true) if jumping to last child, 0 (false) if jumping to first
function! s:jumpToChild(node, last) abort
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
if l:node.isRoot()
return
endif
let l:parent = l:node.parent
let l:children = l:parent.getVisibleChildren()
let l:target = a:last ? l:children[len(l:children) - 1] : l:children[0]
call l:target.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToParent(node) {{{1
" Move the cursor to the parent of the specified node. For a cascade, move to
" the parent of the cascade's first node. At the root node, do nothing.
function! s:jumpToParent(node) abort
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
if l:node.isRoot()
return
endif
if empty(l:node.parent)
call nerdtree#echo('could not jump to parent node')
return
endif
call l:node.parent.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToRoot() {{{1
" moves the cursor to the root node
function! s:jumpToRoot() abort
call b:NERDTree.root.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToNextSibling(node) {{{1
function! s:jumpToNextSibling(node) abort
call s:jumpToSibling(a:node, 1)
endfunction
" FUNCTION: s:jumpToPrevSibling(node) {{{1
function! s:jumpToPrevSibling(node) abort
call s:jumpToSibling(a:node, 0)
endfunction
" FUNCTION: s:jumpToSibling(node, forward) {{{1
" Move the cursor to the next or previous node at the same file system level.
"
" Args:
" node: the node on which the cursor currently sits
" forward: 0 to jump to previous sibling, 1 to jump to next sibling
function! s:jumpToSibling(node, forward) abort
let l:node = a:node.path.isDirectory ? a:node.getCascadeRoot() : a:node
let l:sibling = l:node.findSibling(a:forward)
if empty(l:sibling)
return
endif
call l:sibling.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1
" Open the Bookmark that has the specified name. This function provides the
" implementation for the :OpenBookmark command.
function! nerdtree#ui_glue#openBookmark(name) abort
try
let l:bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echoError('bookmark "' . a:name . '" not found')
return
endtry
if l:bookmark.path.isDirectory
call l:bookmark.open(b:NERDTree)
return
endif
call l:bookmark.open(b:NERDTree, s:initCustomOpenArgs().file)
endfunction
" FUNCTION: s:openHSplit(target) {{{1
function! s:openHSplit(target) abort
call a:target.activate({'where': 'h', 'keepopen': !nerdtree#closeTreeOnOpen()})
endfunction
" FUNCTION: s:openVSplit(target) {{{1
function! s:openVSplit(target) abort
call a:target.activate({'where': 'v', 'keepopen': !nerdtree#closeTreeOnOpen()})
endfunction
"FUNCTION: s:openHSplitBookmark(bookmark) {{{1
"handle the user activating a bookmark
function! s:openHSplitBookmark(bm) abort
call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'h', 'keepopen': !nerdtree#closeTreeOnOpen()} : {})
endfunction
"FUNCTION: s:openVSplitBookmark(bookmark) {{{1
"handle the user activating a bookmark
function! s:openVSplitBookmark(bm) abort
call a:bm.activate(b:NERDTree, !a:bm.path.isDirectory ? {'where': 'v', 'keepopen': !nerdtree#closeTreeOnOpen()} : {})
endfunction
" FUNCTION: s:previewHSplitBookmark(bookmark) {{{1
function! s:previewNodeHSplitBookmark(bookmark) abort
call a:bookmark.activate(b:NERDTree, !a:bookmark.path.isDirectory ? {'stay': 1, 'where': 'h', 'keepopen': 1} : {})
endfunction
" FUNCTION: s:previewVSplitBookmark(bookmark) {{{1
function! s:previewNodeVSplitBookmark(bookmark) abort
call a:bookmark.activate(b:NERDTree, !a:bookmark.path.isDirectory ? {'stay': 1, 'where': 'v', 'keepopen': 1} : {})
endfunction
" FUNCTION: s:openExplorer(node) {{{1
function! s:openExplorer(node) abort
call a:node.openExplorer()
endfunction
" FUNCTION: s:openInNewTab(target) {{{1
function! s:openInNewTab(target) abort
let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't', 'keepopen': !nerdtree#closeTreeOnOpen()})
call l:opener.open(a:target)
endfunction
" FUNCTION: s:openInNewTabSilent(target) {{{1
function! s:openInNewTabSilent(target) abort
let l:opener = g:NERDTreeOpener.New(a:target.path, {'where': 't', 'keepopen': !nerdtree#closeTreeOnOpen(), 'stay': 1})
call l:opener.open(a:target)
endfunction
" FUNCTION: s:openNodeRecursively(node) {{{1
function! s:openNodeRecursively(node) abort
call nerdtree#echo('Recursively opening node. Please wait...')
call a:node.openRecursively()
call b:NERDTree.render()
call nerdtree#echo('')
endfunction
" FUNCTION: s:previewBookmark(bookmark) {{{1
function! s:previewBookmark(bookmark) abort
if a:bookmark.path.isDirectory
execute 'NERDTreeFind '.a:bookmark.path.str()
else
call a:bookmark.activate(b:NERDTree, {'stay': 1, 'where': 'p', 'keepopen': 1})
endif
endfunction
"FUNCTION: s:previewNodeCurrent(node) {{{1
function! s:previewNodeCurrent(node) abort
call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeHSplit(node) {{{1
function! s:previewNodeHSplit(node) abort
call a:node.open({'stay': 1, 'where': 'h', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeVSplit(node) {{{1
function! s:previewNodeVSplit(node) abort
call a:node.open({'stay': 1, 'where': 'v', 'keepopen': 1})
endfunction
" FUNCTION: nerdtree#ui_glue#revealBookmark(name) {{{1
" put the cursor on the node associate with the given name
function! nerdtree#ui_glue#revealBookmark(name) abort
try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0, b:NERDTree)
call targetNode.putCursorHere(0, 1)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echo('Bookmark isn''t cached under the current root')
endtry
endfunction
" FUNCTION: s:refreshRoot() {{{1
" Reloads the current root. All nodes below this will be lost and the root dir
" will be reloaded.
function! s:refreshRoot() abort
if !g:NERDTree.IsOpen()
return
endif
call nerdtree#echo('Refreshing the root node. This could take a while...')
let l:curWin = winnr()
call nerdtree#exec(g:NERDTree.GetWinNum() . 'wincmd w', 1)
call b:NERDTree.root.refresh()
call b:NERDTree.render()
redraw
call nerdtree#exec(l:curWin . 'wincmd w', 1)
call nerdtree#echo('')
endfunction
" FUNCTION: s:refreshCurrent(node) {{{1
" refreshes the root for the current node
function! s:refreshCurrent(node) abort
let node = a:node
if !node.path.isDirectory
let node = node.parent
endif
call nerdtree#echo('Refreshing node. This could take a while...')
call node.refresh()
call b:NERDTree.render()
call nerdtree#echo('')
endfunction
" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1
function! nerdtree#ui_glue#setupCommands() abort
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.ToggleTabTree('<args>')
command! -n=0 -bar NERDTreeClose :call g:NERDTree.Close()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreateTabTree('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=? -complete=file -bar NERDTreeFind call s:findAndRevealPath('<args>')
command! -n=0 -bar NERDTreeRefreshRoot call s:refreshRoot()
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
endfunction
" Function: s:SID() {{{1
function! s:SID() abort
if !exists('s:sid')
let s:sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endif
return s:sid
endfun
" FUNCTION: s:showMenu(node) {{{1
function! s:showMenu(node) abort
let mc = g:NERDTreeMenuController.New(g:NERDTreeMenuItem.AllEnabled())
call mc.showMenu()
endfunction
" FUNCTION: s:toggleIgnoreFilter() {{{1
function! s:toggleIgnoreFilter() abort
call b:NERDTree.ui.toggleIgnoreFilter()
endfunction
" FUNCTION: s:toggleShowBookmarks() {{{1
function! s:toggleShowBookmarks() abort
call b:NERDTree.ui.toggleShowBookmarks()
endfunction
" FUNCTION: s:toggleShowFiles() {{{1
function! s:toggleShowFiles() abort
call b:NERDTree.ui.toggleShowFiles()
endfunction
" FUNCTION: s:toggleShowHidden() {{{1
" toggles the display of hidden files
function! s:toggleShowHidden() abort
call b:NERDTree.ui.toggleShowHidden()
endfunction
" FUNCTION: s:toggleZoom() {{{1
function! s:toggleZoom() abort
call b:NERDTree.ui.toggleZoom()
endfunction
" FUNCTION: nerdtree#ui_glue#upDir(preserveState) {{{1
" Move the NERDTree up one level.
"
" Args:
" preserveState: if 1, the current root is left open when the new tree is
" rendered; if 0, the current root node is closed
function! nerdtree#ui_glue#upDir(preserveState) abort
try
call b:NERDTree.root.cacheParent()
catch /^NERDTree.CannotCacheParentError/
call nerdtree#echo('already at root directory')
return
endtry
let l:oldRoot = b:NERDTree.root
let l:newRoot = b:NERDTree.root.parent
call l:newRoot.open()
call l:newRoot.transplantChild(l:oldRoot)
if !a:preserveState
call l:oldRoot.close()
endif
call b:NERDTree.changeRoot(l:newRoot)
call l:oldRoot.putCursorHere(0, 0)
endfunction
" FUNCTION: s:upDirCurrentRootOpen() {{{1
function! s:upDirCurrentRootOpen() abort
call nerdtree#ui_glue#upDir(1)
endfunction
" FUNCTION: s:upDirCurrentRootClosed() {{{1
function! s:upDirCurrentRootClosed() abort
call nerdtree#ui_glue#upDir(0)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,365 @@
" ============================================================================
" CLASS: Bookmark
"
" The Bookmark class serves two purposes:
" (1) It is the top-level prototype for new, concrete Bookmark objects.
" (2) It provides an interface for client code to query and manipulate the
" global list of Bookmark objects within the current Vim session.
" ============================================================================
let s:Bookmark = {}
let g:NERDTreeBookmark = s:Bookmark
" FUNCTION: Bookmark.activate(nerdtree) {{{1
function! s:Bookmark.activate(nerdtree, ...)
call self.open(a:nerdtree, a:0 ? a:1 : {})
endfunction
" FUNCTION: Bookmark.AddBookmark(name, path) {{{1
" Class method to add a new bookmark to the list, if a previous bookmark exists
" with the same name, just update the path for that bookmark
function! s:Bookmark.AddBookmark(name, path)
for i in s:Bookmark.Bookmarks()
if i.name ==# a:name
let i.path = a:path
return
endif
endfor
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
endfunction
" FUNCTION: Bookmark.Bookmarks() {{{1
" Class method to get all bookmarks. Lazily initializes the bookmarks global
" variable
function! s:Bookmark.Bookmarks()
if !exists('g:NERDTreeBookmarks')
let g:NERDTreeBookmarks = []
endif
return g:NERDTreeBookmarks
endfunction
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
" class method that returns 1 if a bookmark with the given name is found, 0
" otherwise
function! s:Bookmark.BookmarkExistsFor(name)
try
call s:Bookmark.BookmarkFor(a:name)
return 1
catch /^NERDTree.BookmarkNotFoundError/
return 0
endtry
endfunction
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
" Class method that returns the Bookmark object having the specified name.
" Throws NERDTree.BookmarkNotFoundError if no Bookmark is found.
function! s:Bookmark.BookmarkFor(name)
let l:result = {}
for l:bookmark in s:Bookmark.Bookmarks()
if l:bookmark.name ==# a:name
let l:result = l:bookmark
break
endif
endfor
if empty(l:result)
throw 'NERDTree.BookmarkNotFoundError: "' . a:name . '" not found'
endif
return l:result
endfunction
" FUNCTION: Bookmark.BookmarkNames() {{{1
" Class method to return an array of all bookmark names
function! s:Bookmark.BookmarkNames()
let names = []
for i in s:Bookmark.Bookmarks()
call add(names, i.name)
endfor
return names
endfunction
" FUNCTION: Bookmark.CacheBookmarks(silent) {{{1
" Class method to read all bookmarks from the bookmarks file initialize
" bookmark objects for each one.
"
" Args:
" silent - dont echo an error msg if invalid bookmarks are found
function! s:Bookmark.CacheBookmarks(silent)
if filereadable(g:NERDTreeBookmarksFile)
let g:NERDTreeBookmarks = []
let g:NERDTreeInvalidBookmarks = []
let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
let invalidBookmarksFound = 0
for i in bookmarkStrings
"ignore blank lines
if i !=# ''
let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
let path = fnamemodify(path, ':p')
try
let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path))
call add(g:NERDTreeBookmarks, bookmark)
catch /^NERDTree.InvalidArgumentsError/
call add(g:NERDTreeInvalidBookmarks, i)
let invalidBookmarksFound += 1
endtry
endif
endfor
if invalidBookmarksFound
call s:Bookmark.Write()
if !a:silent
call nerdtree#echo(invalidBookmarksFound . ' invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.')
endif
endif
endif
endfunction
" FUNCTION: Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark) {{{1
" Class method that indicates the relative position of two bookmarks when
" placed in alphabetical order by name. Case-sensitivity is determined by an
" option. Supports the s:Bookmark.SortBookmarksList() method.
function! s:Bookmark.CompareBookmarksByName(firstBookmark, secondBookmark)
let l:result = 0
if g:NERDTreeBookmarksSort ==# 1
if a:firstBookmark.name <? a:secondBookmark.name
let l:result = -1
elseif a:firstBookmark.name >? a:secondBookmark.name
let l:result = 1
endif
elseif g:NERDTreeBookmarksSort ==# 2
if a:firstBookmark.name <# a:secondBookmark.name
let l:result = -1
elseif a:firstBookmark.name ># a:secondBookmark.name
let l:result = 1
endif
endif
return l:result
endfunction
" FUNCTION: Bookmark.ClearAll() {{{1
" Class method to delete all bookmarks.
function! s:Bookmark.ClearAll()
for i in s:Bookmark.Bookmarks()
call i.delete()
endfor
call s:Bookmark.Write()
endfunction
" FUNCTION: Bookmark.delete() {{{1
" Delete this bookmark. If the node for this bookmark is under the current
" root, then recache bookmarks for its Path object
function! s:Bookmark.delete()
call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
call s:Bookmark.Write()
endfunction
" FUNCTION: s:Edit() {{{1
" opens the NERDTreeBookmarks file for manual editing
function! s:Bookmark.Edit()
call nerdtree#exec('wincmd w', 1)
call nerdtree#exec('edit '.g:NERDTreeBookmarksFile, 1)
endfunction
" FUNCTION: Bookmark.getNode(nerdtree, searchFromAbsoluteRoot) {{{1
" Returns the tree node object associated with this Bookmark.
" Throws NERDTree.BookmarkedNodeNotFoundError if the node is not found.
"
" Args:
" searchFromAbsoluteRoot: boolean flag, search from the highest cached node
" if true and from the current tree root if false
function! s:Bookmark.getNode(nerdtree, searchFromAbsoluteRoot)
if a:searchFromAbsoluteRoot
let l:searchRoot = a:nerdtree.root.AbsoluteTreeRoot()
else
let l:searchRoot = a:nerdtree.root
endif
let l:targetNode = l:searchRoot.findNode(self.path)
if empty(l:targetNode)
throw 'NERDTree.BookmarkedNodeNotFoundError: node for bookmark "' . self.name . '" not found'
endif
return l:targetNode
endfunction
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree) {{{1
" Class method that returns the tree node object for the Bookmark with the
" given name. Throws NERDTree.BookmarkNotFoundError if a Bookmark with the
" name does not exist. Throws NERDTree.BookmarkedNodeNotFoundError if a
" tree node for the named Bookmark could not be found.
function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot, nerdtree)
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
return l:bookmark.getNode(a:nerdtree, a:searchFromAbsoluteRoot)
endfunction
" FUNCTION: Bookmark.GetSelected() {{{1
" returns the Bookmark the cursor is over, or {}
function! s:Bookmark.GetSelected()
let line = getline('.')
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
if name !=# line
try
return s:Bookmark.BookmarkFor(name)
catch /^NERDTree.BookmarkNotFoundError/
return {}
endtry
endif
return {}
endfunction
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
" Class method to get all invalid bookmark strings read from the bookmarks
" file
function! s:Bookmark.InvalidBookmarks()
if !exists('g:NERDTreeInvalidBookmarks')
let g:NERDTreeInvalidBookmarks = []
endif
return g:NERDTreeInvalidBookmarks
endfunction
" FUNCTION: Bookmark.mustExist() {{{1
function! s:Bookmark.mustExist()
if !self.path.exists()
call s:Bookmark.CacheBookmarks(1)
throw 'NERDTree.BookmarkPointsToInvalidLocationError: the bookmark "'.
\ self.name .'" points to a non existing location: "'. self.path.str()
endif
endfunction
" FUNCTION: Bookmark.New(name, path) {{{1
" Create a new bookmark object with the given name and path object
function! s:Bookmark.New(name, path)
if a:name =~# ' '
throw 'NERDTree.IllegalBookmarkNameError: illegal name:' . a:name
endif
let newBookmark = copy(self)
let newBookmark.name = a:name
let newBookmark.path = a:path
return newBookmark
endfunction
" FUNCTION: Bookmark.open(nerdtree, [options]) {{{1
"Args:
"
"nerdtree: the tree to load open the bookmark in
"
"A dictionary containing the following keys (all optional):
" 'where': Specifies whether the node should be opened in new split/tab or in
" the previous window. Can be either 'v' (vertical split), 'h'
" (horizontal split), 't' (new tab) or 'p' (previous window).
" 'reuse': if a window is displaying the file then jump the cursor there
" 'keepopen': dont close the tree window
" 'stay': open the file, but keep the cursor in the tree win
"
function! s:Bookmark.open(nerdtree, ...)
let opts = a:0 ? a:1 : {}
if nerdtree#closeBookmarksOnOpen()
call a:nerdtree.ui.toggleShowBookmarks()
endif
if self.path.isDirectory && !has_key(opts, 'where')
call self.toRoot(a:nerdtree)
else
let opener = g:NERDTreeOpener.New(self.path, opts)
call opener.open(self)
endif
endfunction
" FUNCTION: Bookmark.openInNewTab(options) {{{1
" Create a new bookmark object with the given name and path object
function! s:Bookmark.openInNewTab(options)
call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead')
call self.open(a:options)
endfunction
" FUNCTION: Bookmark.setPath(path) {{{1
" makes this bookmark point to the given path
function! s:Bookmark.setPath(path)
let self.path = a:path
endfunction
" FUNCTION: Bookmark.SortBookmarksList() {{{1
" Class method that sorts the global list of bookmarks alphabetically by name.
" Note that case-sensitivity is determined by a user option.
function! s:Bookmark.SortBookmarksList()
call sort(s:Bookmark.Bookmarks(), s:Bookmark.CompareBookmarksByName, s:Bookmark)
endfunction
" FUNCTION: Bookmark.str() {{{1
" Get the string that should be rendered in the view for this bookmark
function! s:Bookmark.str()
let pathStrMaxLen = winwidth(g:NERDTree.GetWinNum()) - 4 - strdisplaywidth(self.name)
if &number
let pathStrMaxLen = pathStrMaxLen - &numberwidth
endif
let pathStr = self.path.str({'format': 'UI'})
if strdisplaywidth(pathStr) > pathStrMaxLen
while strdisplaywidth(pathStr) > pathStrMaxLen && strchars(pathStr) > 0
let pathStr = substitute(pathStr, '^.', '', '')
endwhile
let pathStr = '<' . pathStr
endif
return '>' . self.name . ' ' . pathStr
endfunction
" FUNCTION: Bookmark.toRoot(nerdtree) {{{1
" Set the root of the given NERDTree to the node for this Bookmark. If a node
" for this Bookmark does not exist, a new one is initialized.
function! s:Bookmark.toRoot(nerdtree)
if self.validate()
try
let l:targetNode = self.getNode(a:nerdtree, 1)
call l:targetNode.closeChildren()
catch /^NERDTree.BookmarkedNodeNotFoundError/
let l:targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path, a:nerdtree)
endtry
call a:nerdtree.changeRoot(l:targetNode)
endif
endfunction
" FUNCTION: Bookmark.ToRoot(name, nerdtree) {{{1
" Class method that makes the Bookmark with the given name the root of
" specified NERDTree.
function! s:Bookmark.ToRoot(name, nerdtree)
let l:bookmark = s:Bookmark.BookmarkFor(a:name)
call l:bookmark.toRoot(a:nerdtree)
endfunction
" FUNCTION: Bookmark.validate() {{{1
function! s:Bookmark.validate()
if self.path.exists()
return 1
else
call s:Bookmark.CacheBookmarks(1)
call nerdtree#echo(self.name . 'now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.')
return 0
endif
endfunction
" FUNCTION: Bookmark.Write() {{{1
" Class method to write all bookmarks to the bookmarks file
function! s:Bookmark.Write()
let bookmarkStrings = []
for i in s:Bookmark.Bookmarks()
call add(bookmarkStrings, i.name . ' ' . fnamemodify(i.path.str(), ':~'))
endfor
"add a blank line before the invalid ones
call add(bookmarkStrings, '')
for j in s:Bookmark.InvalidBookmarks()
call add(bookmarkStrings, j)
endfor
try
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
catch
call nerdtree#echoError('Failed to write bookmarks file. Make sure g:NERDTreeBookmarksFile points to a valid location.')
endtry
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -0,0 +1,402 @@
" ============================================================================
" CLASS: Creator
"
" This class is responsible for creating NERDTree instances. The new NERDTree
" may be a tab tree, a window tree, or a mirrored tree. In the process of
" creating a NERDTree, it sets up all of the window and buffer options and key
" mappings etc.
" ============================================================================
let s:Creator = {}
let g:NERDTreeCreator = s:Creator
" FUNCTION: s:Creator._bindMappings() {{{1
function! s:Creator._bindMappings()
call g:NERDTreeKeyMap.BindAll()
command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark call nerdtree#ui_glue#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>', b:NERDTree)
command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call b:NERDTree.render()
command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call b:NERDTree.render()
command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write()
command! -buffer -nargs=0 EditBookmarks call g:NERDTreeBookmark.Edit()
endfunction
" FUNCTION: s:Creator._broadcastInitEvent() {{{1
function! s:Creator._broadcastInitEvent()
if exists('#User#NERDTreeInit')
doautocmd User NERDTreeInit
endif
endfunction
" FUNCTION: s:Creator.BufNamePrefix() {{{1
function! s:Creator.BufNamePrefix()
return 'NERD_tree_'
endfunction
" FUNCTION: s:Creator.CreateTabTree(a:name) {{{1
function! s:Creator.CreateTabTree(name)
let creator = s:Creator.New()
call creator.createTabTree(a:name)
endfunction
" FUNCTION: s:Creator.createTabTree(a:name) {{{1
" name: the name of a bookmark or a directory
function! s:Creator.createTabTree(name)
let l:path = self._pathForString(a:name)
" Abort if an exception was thrown (i.e., if the bookmark or directory
" does not exist).
if empty(l:path)
return
endif
" Obey the user's preferences for changing the working directory.
if g:NERDTreeChDirMode != 0
call l:path.changeToDir()
endif
if g:NERDTree.ExistsForTab()
call g:NERDTree.Close()
call self._removeTreeBufForTab()
endif
call self._createTreeWin()
call self._createNERDTree(l:path, 'tab')
call b:NERDTree.render()
call b:NERDTree.root.putCursorHere(0, 0)
call self._broadcastInitEvent()
endfunction
" FUNCTION: s:Creator.CreateWindowTree(dir) {{{1
function! s:Creator.CreateWindowTree(dir)
let creator = s:Creator.New()
call creator.createWindowTree(a:dir)
endfunction
" FUNCTION: s:Creator.createWindowTree(dir) {{{1
function! s:Creator.createWindowTree(dir)
try
let path = g:NERDTreePath.New(a:dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo('Invalid directory name:' . a:dir)
return
endtry
"we want the directory buffer to disappear when we do the :edit below
setlocal bufhidden=wipe
let previousBuf = expand('#')
"we need a unique name for each window tree buffer to ensure they are
"all independent
exec g:NERDTreeCreatePrefix . ' edit ' . self._nextBufferName()
call self._createNERDTree(path, 'window')
let b:NERDTree._previousBuf = bufnr(previousBuf)
call self._setCommonBufOptions()
call b:NERDTree.render()
call self._broadcastInitEvent()
endfunction
" FUNCTION: s:Creator._createNERDTree(path) {{{1
function! s:Creator._createNERDTree(path, type)
let b:NERDTree = g:NERDTree.New(a:path, a:type)
" TODO: This assignment is kept for compatibility reasons. Many other
" plugins use b:NERDTreeRoot instead of b:NERDTree.root. Remove this
" assignment in the future.
let b:NERDTreeRoot = b:NERDTree.root
call b:NERDTree.root.open()
endfunction
" FUNCTION: s:Creator.CreateMirror() {{{1
function! s:Creator.CreateMirror()
let creator = s:Creator.New()
call creator.createMirror()
endfunction
" FUNCTION: s:Creator.createMirror() {{{1
function! s:Creator.createMirror()
"get the names off all the nerd tree buffers
let treeBufNames = []
for i in range(1, tabpagenr('$'))
let nextName = self._tabpagevar(i, 'NERDTreeBufName')
if nextName != -1 && (!exists('t:NERDTreeBufName') || nextName != t:NERDTreeBufName)
call add(treeBufNames, nextName)
endif
endfor
let treeBufNames = self._uniq(treeBufNames)
"map the option names (that the user will be prompted with) to the nerd
"tree buffer names
let options = {}
let i = 0
while i < len(treeBufNames)
let bufName = treeBufNames[i]
let treeRoot = getbufvar(bufName, 'NERDTree').root
let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName
let i = i + 1
endwhile
"work out which tree to mirror, if there is more than 1 then ask the user
let bufferName = ''
if len(keys(options)) > 1
let choices = ['Choose a tree to mirror']
let choices = extend(choices, sort(keys(options)))
let choice = inputlist(choices)
if choice < 1 || choice > len(options) || choice ==# ''
return
endif
let bufferName = options[sort(keys(options))[choice-1]]
elseif len(keys(options)) ==# 1
let bufferName = values(options)[0]
else
call nerdtree#echo('No trees to mirror')
return
endif
if g:NERDTree.ExistsForTab() && g:NERDTree.IsOpen()
call g:NERDTree.Close()
endif
let t:NERDTreeBufName = bufferName
call self._createTreeWin()
exec 'buffer ' . bufferName
call b:NERDTree.ui.restoreScreenState()
if !&hidden
call b:NERDTree.render()
endif
endfunction
" FUNCTION: s:Creator._createTreeWin() {{{1
" Initialize the NERDTree window. Open the window, size it properly, set all
" local options, etc.
function! s:Creator._createTreeWin()
let l:splitLocation = g:NERDTreeWinPos ==# 'left' ? 'topleft ' : 'botright '
let l:splitSize = g:NERDTreeWinSize
if !g:NERDTree.ExistsForTab()
let t:NERDTreeBufName = self._nextBufferName()
silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' new'
silent! execute 'edit ' . t:NERDTreeBufName
silent! execute 'vertical resize '. l:splitSize
else
silent! execute l:splitLocation . 'vertical ' . l:splitSize . ' split'
silent! execute 'buffer ' . t:NERDTreeBufName
endif
setlocal winfixwidth
call self._setCommonBufOptions()
if has('patch-7.4.1925')
clearjumps
endif
endfunction
" FUNCTION: s:Creator._isBufHidden(nr) {{{1
function! s:Creator._isBufHidden(nr)
redir => bufs
silent ls!
redir END
return bufs =~ a:nr . '..h'
endfunction
" FUNCTION: s:Creator.New() {{{1
function! s:Creator.New()
let newCreator = copy(self)
return newCreator
endfunction
" FUNCTION: s:Creator._nextBufferName() {{{1
" returns the buffer name for the next nerd tree
function! s:Creator._nextBufferName()
let name = s:Creator.BufNamePrefix() . self._nextBufferNumber()
return name
endfunction
" FUNCTION: s:Creator._nextBufferNumber() {{{1
" the number to add to the nerd tree buffer name to make the buf name unique
function! s:Creator._nextBufferNumber()
if !exists('s:Creator._NextBufNum')
let s:Creator._NextBufNum = 1
else
let s:Creator._NextBufNum += 1
endif
return s:Creator._NextBufNum
endfunction
" FUNCTION: s:Creator._pathForString(str) {{{1
" find a bookmark or adirectory for the given string
function! s:Creator._pathForString(str)
let path = {}
if g:NERDTreeBookmark.BookmarkExistsFor(a:str)
let path = g:NERDTreeBookmark.BookmarkFor(a:str).path
else
let dir = a:str ==# '' ? getcwd() : a:str
"hack to get an absolute path if a relative path is given
if dir =~# '^\.'
let dir = getcwd() . nerdtree#slash() . dir
endif
"hack to prevent removing slash if dir is the root of the file system.
if dir !=# '/'
let dir = g:NERDTreePath.Resolve(dir)
endif
try
let path = g:NERDTreePath.New(dir)
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo('No bookmark or directory found for: ' . a:str)
return {}
endtry
endif
if !path.isDirectory
let path = path.getParent()
endif
return path
endfunction
" Function: s:Creator._removeTreeBufForTab() {{{1
function! s:Creator._removeTreeBufForTab()
let buf = bufnr(t:NERDTreeBufName)
"if &hidden is not set then it will already be gone
if buf != -1
"nerdtree buf may be mirrored/displayed elsewhere
if self._isBufHidden(buf)
exec 'bwipeout ' . buf
endif
endif
unlet t:NERDTreeBufName
endfunction
" FUNCTION: s:Creator._setCommonBufOptions() {{{1
function! s:Creator._setCommonBufOptions()
" Options for a non-file/control buffer.
setlocal bufhidden=hide
setlocal buftype=nofile
setlocal noswapfile
" Options for controlling buffer/window appearance.
setlocal foldcolumn=0
setlocal foldmethod=manual
setlocal nobuflisted
setlocal nofoldenable
setlocal nolist
setlocal nospell
setlocal nowrap
if g:NERDTreeShowLineNumbers
setlocal number
else
setlocal nonumber
if v:version >= 703
setlocal norelativenumber
endif
endif
iabc <buffer>
if g:NERDTreeHighlightCursorline
setlocal cursorline
endif
call self._setupStatusline()
call self._bindMappings()
setlocal filetype=nerdtree
endfunction
" FUNCTION: s:Creator._setupStatusline() {{{1
function! s:Creator._setupStatusline()
if g:NERDTreeStatusline != -1
let &l:statusline = g:NERDTreeStatusline
endif
endfunction
" FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1
function! s:Creator._tabpagevar(tabnr, var)
let currentTab = tabpagenr()
let old_ei = &eventignore
set eventignore=all
try
exec 'tabnext ' . a:tabnr
let v = -1
if exists('t:' . a:var)
exec 'let v = t:' . a:var
endif
exec 'tabnext ' . currentTab
finally
let &eventignore = old_ei
endtry
return v
endfunction
" FUNCTION: s:Creator.ToggleTabTree(dir) {{{1
function! s:Creator.ToggleTabTree(dir)
let creator = s:Creator.New()
call creator.toggleTabTree(a:dir)
endfunction
" FUNCTION: s:Creator.toggleTabTree(dir) {{{1
" Toggles the NERD tree. I.e if the NERD tree is open, it is closed. If it is
" closed, it is restored or initialized. If dir is not empty, it will be set
" as the new root.
"
" Args:
" dir: the full path for the root node (is used if the NERD tree is being
" initialized, or to change the root to a new dir.)
function! s:Creator.toggleTabTree(dir)
if g:NERDTree.ExistsForTab()
if !g:NERDTree.IsOpen()
call self._createTreeWin()
if !empty(a:dir) && a:dir !=# b:NERDTree.root.path.str()
call self.createTabTree(a:dir)
elseif !&hidden
call b:NERDTree.render()
endif
call b:NERDTree.ui.restoreScreenState()
else
call g:NERDTree.Close()
endif
else
call self.createTabTree(a:dir)
endif
endfunction
" Function: s:Creator._uniq(list) {{{1
" returns a:list without duplicates
function! s:Creator._uniq(list)
let uniqlist = []
for elem in a:list
if index(uniqlist, elem) ==# -1
let uniqlist += [elem]
endif
endfor
return uniqlist
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -0,0 +1,13 @@
"CLASS: Event
"============================================================
let s:Event = {}
let g:NERDTreeEvent = s:Event
function! s:Event.New(nerdtree, subject, action, params) abort
let newObj = copy(self)
let newObj.nerdtree = a:nerdtree
let newObj.subject = a:subject
let newObj.action = a:action
let newObj.params = a:params
return newObj
endfunction

View File

@@ -0,0 +1,58 @@
"CLASS: FlagSet
"============================================================
let s:FlagSet = {}
let g:NERDTreeFlagSet = s:FlagSet
"FUNCTION: FlagSet.addFlag(scope, flag) {{{1
function! s:FlagSet.addFlag(scope, flag)
let flags = self._flagsForScope(a:scope)
if index(flags, a:flag) == -1
call add(flags, a:flag)
end
endfunction
"FUNCTION: FlagSet.clearFlags(scope) {{{1
function! s:FlagSet.clearFlags(scope)
let self._flags[a:scope] = []
endfunction
"FUNCTION: FlagSet._flagsForScope(scope) {{{1
function! s:FlagSet._flagsForScope(scope)
if !has_key(self._flags, a:scope)
let self._flags[a:scope] = []
endif
return self._flags[a:scope]
endfunction
"FUNCTION: FlagSet.New() {{{1
function! s:FlagSet.New()
let newObj = copy(self)
let newObj._flags = {}
return newObj
endfunction
"FUNCTION: FlagSet.removeFlag(scope, flag) {{{1
function! s:FlagSet.removeFlag(scope, flag)
let flags = self._flagsForScope(a:scope)
let i = index(flags, a:flag)
if i >= 0
call remove(flags, i)
endif
endfunction
"FUNCTION: FlagSet.renderToString() {{{1
function! s:FlagSet.renderToString()
let flagstring = ''
for i in values(self._flags)
let flagstring .= join(i)
endfor
if len(flagstring) == 0
return ''
endif
return '[' . flagstring . ']'
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -0,0 +1,164 @@
"CLASS: KeyMap
"============================================================
let s:KeyMap = {}
let g:NERDTreeKeyMap = s:KeyMap
let s:keyMaps = {}
"FUNCTION: KeyMap.All() {{{1
function! s:KeyMap.All()
let sortedKeyMaps = values(s:keyMaps)
call sort(sortedKeyMaps, s:KeyMap.Compare, s:KeyMap)
return sortedKeyMaps
endfunction
"FUNCTION: KeyMap.Compare(keyMap1, keyMap2) {{{1
function! s:KeyMap.Compare(keyMap1, keyMap2)
if a:keyMap1.key >? a:keyMap2.key
return 1
endif
if a:keyMap1.key <? a:keyMap2.key
return -1
endif
return 0
endfunction
"FUNCTION: KeyMap.FindFor(key, scope) {{{1
function! s:KeyMap.FindFor(key, scope)
return get(s:keyMaps, a:key . a:scope, {})
endfunction
"FUNCTION: KeyMap.BindAll() {{{1
function! s:KeyMap.BindAll()
for i in values(s:keyMaps)
call i.bind()
endfor
endfunction
"FUNCTION: KeyMap.bind() {{{1
function! s:KeyMap.bind()
" If the key sequence we're trying to map contains any '<>' notation, we
" must replace each of the '<' characters with '<lt>' to ensure the string
" is not translated into its corresponding keycode during the later part
" of the map command below
" :he <>
let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)'
if self.key =~# specialNotationRegex
let keymapInvokeString = substitute(self.key, specialNotationRegex, '<lt>\1', 'g')
else
let keymapInvokeString = self.key
endif
let keymapInvokeString = escape(keymapInvokeString, '\"')
let premap = self.key ==# '<LeftRelease>' ? ' <LeftRelease>' : ' '
exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")<cr>'
endfunction
"FUNCTION: KeyMap.Remove(key, scope) {{{1
function! s:KeyMap.Remove(key, scope)
return remove(s:keyMaps, a:key . a:scope)
endfunction
"FUNCTION: KeyMap.invoke() {{{1
"Call the KeyMaps callback function
function! s:KeyMap.invoke(...)
let l:Callback = type(self.callback) ==# type(function('tr')) ? self.callback : function(self.callback)
if a:0
call l:Callback(a:1)
else
call l:Callback()
endif
endfunction
"FUNCTION: KeyMap.Invoke() {{{1
"Find a keymapping for a:key and the current scope invoke it.
"
"Scope is determined as follows:
" * if the cursor is on a dir node then DirNode
" * if the cursor is on a file node then FileNode
" * if the cursor is on a bookmark then Bookmark
"
"If a keymap has the scope of 'all' then it will be called if no other keymap
"is found for a:key and the scope.
function! s:KeyMap.Invoke(key)
"required because clicking the command window below another window still
"invokes the <LeftRelease> mapping - but changes the window cursor
"is in first
"
"TODO: remove this check when the vim bug is fixed
if !g:NERDTree.ExistsForBuf()
return {}
endif
let node = g:NERDTreeFileNode.GetSelected()
if !empty(node)
"try file node
if !node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, 'FileNode')
if !empty(km)
return km.invoke(node)
endif
endif
"try dir node
if node.path.isDirectory
let km = s:KeyMap.FindFor(a:key, 'DirNode')
if !empty(km)
return km.invoke(node)
endif
endif
"try generic node
let km = s:KeyMap.FindFor(a:key, 'Node')
if !empty(km)
return km.invoke(node)
endif
endif
"try bookmark
let bm = g:NERDTreeBookmark.GetSelected()
if !empty(bm)
let km = s:KeyMap.FindFor(a:key, 'Bookmark')
if !empty(km)
return km.invoke(bm)
endif
endif
"try all
let km = s:KeyMap.FindFor(a:key, 'all')
if !empty(km)
return km.invoke()
endif
endfunction
"FUNCTION: KeyMap.Create(options) {{{1
function! s:KeyMap.Create(options)
let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options))
"dont override other mappings unless the 'override' option is given
if get(opts, 'override', 0) ==# 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope']))
return
end
let newKeyMap = copy(self)
let newKeyMap.key = opts['key']
let newKeyMap.quickhelpText = opts['quickhelpText']
let newKeyMap.callback = opts['callback']
let newKeyMap.scope = opts['scope']
call s:KeyMap.Add(newKeyMap)
endfunction
"FUNCTION: KeyMap.Add(keymap) {{{1
function! s:KeyMap.Add(keymap)
let s:keyMaps[a:keymap.key . a:keymap.scope] = a:keymap
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -0,0 +1,211 @@
"CLASS: MenuController
"============================================================
let s:MenuController = {}
let g:NERDTreeMenuController = s:MenuController
"FUNCTION: MenuController.New(menuItems) {{{1
"create a new menu controller that operates on the given menu items
function! s:MenuController.New(menuItems)
let newMenuController = copy(self)
if a:menuItems[0].isSeparator()
let newMenuController.menuItems = a:menuItems[1:-1]
else
let newMenuController.menuItems = a:menuItems
endif
return newMenuController
endfunction
" FUNCTION: s:MenuController.isMinimal() {{{1
function! s:MenuController.isMinimal()
return g:NERDTreeMinimalMenu
endfunction
" FUNCTION: MenuController.showMenu() {{{1
" Enter the main loop of the NERDTree menu, prompting the user to select
" a menu item.
function! s:MenuController.showMenu()
call self._saveOptions()
try
let self.selection = 0
let l:done = 0
while !l:done
if has('nvim')
mode
else
redraw!
endif
call self._echoPrompt()
let l:key = nr2char(getchar())
let l:done = self._handleKeypress(l:key)
endwhile
finally
call self._restoreOptions()
" Redraw when Ctrl-C or Esc is received.
if !l:done || self.selection ==# -1
redraw!
endif
endtry
if self.selection !=# -1
let l:m = self._current()
call l:m.execute()
endif
endfunction
"FUNCTION: MenuController._echoPrompt() {{{1
function! s:MenuController._echoPrompt()
let navHelp = 'Use ' . g:NERDTreeMenuDown . '/' . g:NERDTreeMenuUp . '/enter'
if self.isMinimal()
let selection = self.menuItems[self.selection].text
let keyword = matchstr(selection, '[^ ]*([^ ]*')
let shortcuts = map(copy(self.menuItems), "v:val['shortcut']")
let shortcuts[self.selection] = ' ' . keyword . ' '
echo 'Menu: [' . join(shortcuts, ',') . '] (' . navHelp . ' or shortcut): '
else
echo 'NERDTree Menu. ' . navHelp . ', or the shortcuts indicated'
echo '========================================================='
for i in range(0, len(self.menuItems)-1)
if self.selection ==# i
echo '> ' . self.menuItems[i].text
else
echo ' ' . self.menuItems[i].text
endif
endfor
endif
endfunction
"FUNCTION: MenuController._current(key) {{{1
"get the MenuItem that is currently selected
function! s:MenuController._current()
return self.menuItems[self.selection]
endfunction
"FUNCTION: MenuController._handleKeypress(key) {{{1
"change the selection (if appropriate) and return 1 if the user has made
"their choice, 0 otherwise
function! s:MenuController._handleKeypress(key)
if a:key ==# g:NERDTreeMenuDown
call self._cursorDown()
elseif a:key ==# g:NERDTreeMenuUp
call self._cursorUp()
elseif a:key ==# nr2char(27) "escape
let self.selection = -1
return 1
elseif a:key ==# "\r" || a:key ==# "\n" "enter and ctrl-j
return 1
else
let index = self._nextIndexFor(a:key)
if index !=# -1
let self.selection = index
if len(self._allIndexesFor(a:key)) ==# 1
return 1
endif
endif
endif
return 0
endfunction
"FUNCTION: MenuController._allIndexesFor(shortcut) {{{1
"get indexes to all menu items with the given shortcut
function! s:MenuController._allIndexesFor(shortcut)
let toReturn = []
for i in range(0, len(self.menuItems)-1)
if self.menuItems[i].shortcut ==# a:shortcut
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: MenuController._nextIndexFor(shortcut) {{{1
"get the index to the next menu item with the given shortcut, starts from the
"current cursor location and wraps around to the top again if need be
function! s:MenuController._nextIndexFor(shortcut)
for i in range(self.selection+1, len(self.menuItems)-1)
if self.menuItems[i].shortcut ==# a:shortcut
return i
endif
endfor
for i in range(0, self.selection)
if self.menuItems[i].shortcut ==# a:shortcut
return i
endif
endfor
return -1
endfunction
"FUNCTION: MenuController._setCmdheight() {{{1
"sets &cmdheight to whatever is needed to display the menu
function! s:MenuController._setCmdheight()
if self.isMinimal()
let &cmdheight = 1
else
let &cmdheight = len(self.menuItems) + 3
endif
endfunction
"FUNCTION: MenuController._saveOptions() {{{1
"set any vim options that are required to make the menu work (saving their old
"values)
function! s:MenuController._saveOptions()
let self._oldLazyredraw = &lazyredraw
let self._oldCmdheight = &cmdheight
set nolazyredraw
call self._setCmdheight()
endfunction
"FUNCTION: MenuController._restoreOptions() {{{1
"restore the options we saved in _saveOptions()
function! s:MenuController._restoreOptions()
let &cmdheight = self._oldCmdheight
let &lazyredraw = self._oldLazyredraw
endfunction
"FUNCTION: MenuController._cursorDown() {{{1
"move the cursor to the next menu item, skipping separators
function! s:MenuController._cursorDown()
let done = 0
while !done
if self.selection < len(self.menuItems)-1
let self.selection += 1
else
let self.selection = 0
endif
if !self._current().isSeparator()
let done = 1
endif
endwhile
endfunction
"FUNCTION: MenuController._cursorUp() {{{1
"move the cursor to the previous menu item, skipping separators
function! s:MenuController._cursorUp()
let done = 0
while !done
if self.selection > 0
let self.selection -= 1
else
let self.selection = len(self.menuItems)-1
endif
if !self._current().isSeparator()
let done = 1
endif
endwhile
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View File

@@ -0,0 +1,118 @@
"CLASS: MenuItem
"============================================================
let s:MenuItem = {}
let g:NERDTreeMenuItem = s:MenuItem
"FUNCTION: MenuItem.All() {{{1
"get all top level menu items
function! s:MenuItem.All()
if !exists('s:menuItems')
let s:menuItems = []
endif
return s:menuItems
endfunction
"FUNCTION: MenuItem.AllEnabled() {{{1
"get all top level menu items that are currently enabled
function! s:MenuItem.AllEnabled()
let toReturn = []
for i in s:MenuItem.All()
if i.enabled()
call add(toReturn, i)
endif
endfor
return toReturn
endfunction
"FUNCTION: MenuItem.Create(options) {{{1
"make a new menu item and add it to the global list
function! s:MenuItem.Create(options)
let newMenuItem = copy(self)
let newMenuItem.text = a:options['text']
let newMenuItem.shortcut = a:options['shortcut']
let newMenuItem.children = []
let newMenuItem.isActiveCallback = -1
if has_key(a:options, 'isActiveCallback')
let newMenuItem.isActiveCallback = a:options['isActiveCallback']
endif
let newMenuItem.callback = -1
if has_key(a:options, 'callback')
let newMenuItem.callback = a:options['callback']
endif
if has_key(a:options, 'parent')
call add(a:options['parent'].children, newMenuItem)
else
call add(s:MenuItem.All(), newMenuItem)
endif
return newMenuItem
endfunction
"FUNCTION: MenuItem.CreateSeparator(options) {{{1
"make a new separator menu item and add it to the global list
function! s:MenuItem.CreateSeparator(options)
let standard_options = { 'text': '--------------------',
\ 'shortcut': -1,
\ 'callback': -1 }
let options = extend(a:options, standard_options, 'force')
return s:MenuItem.Create(options)
endfunction
"FUNCTION: MenuItem.CreateSubmenu(options) {{{1
"make a new submenu and add it to global list
function! s:MenuItem.CreateSubmenu(options)
let standard_options = { 'callback': -1 }
let options = extend(a:options, standard_options, 'force')
return s:MenuItem.Create(options)
endfunction
"FUNCTION: MenuItem.enabled() {{{1
"return 1 if this menu item should be displayed
"
"delegates off to the isActiveCallback, and defaults to 1 if no callback was
"specified
function! s:MenuItem.enabled()
if self.isActiveCallback != -1
return type(self.isActiveCallback) == type(function('tr')) ? self.isActiveCallback() : {self.isActiveCallback}()
endif
return 1
endfunction
"FUNCTION: MenuItem.execute() {{{1
"perform the action behind this menu item, if this menuitem has children then
"display a new menu for them, otherwise deletegate off to the menuitem's
"callback
function! s:MenuItem.execute()
if len(self.children)
let mc = g:NERDTreeMenuController.New(self.children)
call mc.showMenu()
else
if self.callback != -1
if type(self.callback) == type(function('tr'))
call self.callback()
else
call {self.callback}()
endif
endif
endif
endfunction
"FUNCTION: MenuItem.isSeparator() {{{1
"return 1 if this menuitem is a separator
function! s:MenuItem.isSeparator()
return self.callback == -1 && self.children == []
endfunction
"FUNCTION: MenuItem.isSubmenu() {{{1
"return 1 if this menuitem is a submenu
function! s:MenuItem.isSubmenu()
return self.callback == -1 && !empty(self.children)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

Some files were not shown because too many files have changed in this diff Show More