Skip to content

Commit

Permalink
Add basic context menu to all views
Browse files Browse the repository at this point in the history
Users can opt-out by setting `disable_context_menus: false` in their
GitSavvy settings.
  • Loading branch information
kaste committed Jun 17, 2024
1 parent d8ebf42 commit e937317
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 1 deletion.
38 changes: 38 additions & 0 deletions Context.sublime-menu
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"caption": "GitSavvy: Line History",
"command": "gs_ctx_line_history"
},
{
"caption": "GitSavvy: Pick-axe",
"command": "gs_ctx_pick_axe"
},
{
"caption": "GitSavvy: Stage selected hunk",
"command": "gs_ctx_stage_hunk"
}
// {
// "caption": " ...",
// "children": [
// {
// "caption": "Repo History",
// "command": "gs_graph",
// "args": { "all": true }
// },
// {
// "caption": "Path History",
// "command": "gs_graph_current_path"
// },
// {
// "caption": "File History",
// "command": "gs_graph_current_file",
// "args": { "all": false }
// },
// { "caption": "-" },
// {
// "caption": "Show current file revision at HEAD",
// "command": "gs_show_file_at_commit"
// },
// ]
// },
]
8 changes: 7 additions & 1 deletion GitSavvy.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -369,5 +369,11 @@
When set to `true`, no views will receive the prompt asking to initialize
Git in the current view's directory when not found.
*/
"disable_git_init_prompt": false
"disable_git_init_prompt": false,

/*
Disable adding any entries to the context menu available when right-clicking
in any view.
*/
"disable_context_menus": false
}
1 change: 1 addition & 0 deletions core/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .cherry_pick import *
from .commit import *
from .commit_compare import *
from .context_menu import *
from .custom import *
from .diff import *
from .fetch import *
Expand Down
111 changes: 111 additions & 0 deletions core/commands/context_menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
from functools import lru_cache

import sublime

from GitSavvy.core.base_commands import GsTextCommand

from typing import Callable, List, Optional, TypeVar
T = TypeVar("T")

__all__ = (
"gs_ctx_line_history",
"gs_ctx_pick_axe",
"gs_ctx_stage_hunk",
)


# Provide a `CommandContext` as the global `Context` which
# is valid for this exact "runtime-task". This is to speed-up
# the preconditions in `is_enabled` and `is_visible`.

def cached_property(fn: Callable[..., T]) -> T:
return property(lru_cache(1)(fn)) # type: ignore[return-value]


class CommandContext:
def __init__(self, cmd: GsTextCommand):
self._cmd = cmd

@cached_property
def enabled(self) -> bool:
return not self._cmd.savvy_settings.get("disable_context_menus")

@cached_property
def sel(self) -> List[sublime.Region]:
return list(self._cmd.view.sel())

@cached_property
def repo_path(self) -> Optional[str]:
return self._cmd.find_repo_path()

@cached_property
def file_path(self) -> Optional[str]:
return self._cmd.file_path


Context = None


def get_context(self) -> CommandContext:
global Context
if not Context:
Context = CommandContext(self)
sublime.set_timeout(reset_context)

return Context


def reset_context():
global Context
Context = None


class gs_ctx_line_history(GsTextCommand):
def is_enabled(self) -> bool:
ctx = get_context(self)
return bool(
ctx.sel
and ctx.repo_path
)

def is_visible(self) -> bool:
ctx = get_context(self)
return ctx.enabled and bool(ctx.repo_path)

def run(self, edit) -> None:
self.view.run_command("gs_line_history")


class gs_ctx_stage_hunk(GsTextCommand):
def is_enabled(self) -> bool:
ctx = get_context(self)
return bool(
ctx.sel
and ctx.repo_path
and self.view.file_name()
and not self.view.is_dirty()
)

def is_visible(self) -> bool:
ctx = get_context(self)
return ctx.enabled and bool(ctx.repo_path)

def run(self, edit) -> None:
self.view.run_command("gs_stage_hunk")


class gs_ctx_pick_axe(GsTextCommand):
def is_enabled(self) -> bool:
ctx = get_context(self)
return bool(
ctx.sel
and ctx.repo_path
and all(self.view.substr(r).strip() for r in ctx.sel)
)

def is_visible(self) -> bool:
ctx = get_context(self)
return ctx.enabled and bool(ctx.repo_path)

def run(self, edit) -> None:
self.view.run_command("gs_graph_pickaxe")

0 comments on commit e937317

Please sign in to comment.