Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question]: Efficient way to show Git repository status in IPython prompt? #11971

Open
dclong opened this issue Nov 27, 2019 · 1 comment
Open

Comments

@dclong
Copy link

dclong commented Nov 27, 2019

I have the following code in my startup file for IPython to make it show status of the current Git repository. However, it runs slowly. Is there a fast way to show Git repository status in IPython prompt?

class MyPrompt(Prompts):

    def _git_status(self) -> List[bytes]:
        try:
            proc = subprocess.run(['git', 'status'], stdout=subprocess.PIPE)
        except (FileNotFoundError, subprocess.CalledProcessError):
            return []
        lines = [line.strip() for line in proc.stdout.splitlines()]
        # get rid of the leading #
        for idx, line in enumerate(lines):
            if line.startswith(b'#'):
                lines[idx] = line[1:].strip()
        return [line for line in lines if line != b'']

    def _changed(self, line: bytes) -> bool:
        """Check whether the line indicating changes in the Git Repository.
        """
        keywords = [
            b'new file:',
            b'deleted:',
            b'modified:',
            b'renamed:',
            b'untracked files:',
            b'your branch is ahead',
        ]
        line = line.lower().strip()
        for key in keywords:
            if line.startswith(key):
                return True
        return False

    def _git_changed(self) -> bool:
        for line in self._git_status():
            if self._changed(line):
                return True
        return False

    def _git_branch(self) -> str:
        """Get the current branch the current Git repository.
        :return: The name of the current branch.
        """
        try:
            proc = subprocess.run(['git', 'branch'], stdout=subprocess.PIPE)
        except (FileNotFoundError, subprocess.CalledProcessError):
            return ''
        for line in proc.stdout.splitlines():
            line = line.strip()
            if line.startswith(b'*'):
                return line[1:].strip().decode()
        return ''

    def _git_remote(self) -> List[str]:
        """Get the remote names of the current Git repository.
        :return: A list of remote names.
        """
        try:
            proc = subprocess.run(['git', 'remote'], stdout=subprocess.PIPE)
        except (FileNotFoundError, subprocess.CalledProcessError):
            return ''
        return [line.strip().decode() for line in proc.stdout.splitlines() if line.strip() != b'']

    def in_prompt_tokens(self, cli=None):
        user = getpass.getuser()
        host = socket.gethostname()
        if host.endswith('.local'):
            host = host[:-6]
        remotes = ''
        branch = ''
        if Path('.git').is_dir():
            remotes = '(' + '|'.join(self._git_remote()) + ')'
            branch = '[' + self._git_branch() + f'{"*" if self._git_changed() else ""}]'
        cwd = Path.cwd()
        return [
            (Token, f'{user}@{host} {cwd} {remotes} {branch}'),
            (Token.Prompt, '\n    >>> ')
        ]


get_ipython().prompts = MyPrompt(get_ipython())
@Carreau
Copy link
Member

Carreau commented Nov 27, 2019

I would look at what xonsh does it should have git integration for the prompt. That will likely give you ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants