Created
March 25, 2025 15:31
-
-
Save ryuukk/df54a08be96cd3c080cf664ada0d099b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sublime | |
import sublime_plugin | |
import re | |
class GetFunctionScopeCommand(sublime_plugin.TextCommand): | |
def run(self, edit): | |
view = self.view | |
cursor_pos = view.sel()[0].begin() | |
current_line_region = view.line(cursor_pos) | |
current_line = view.substr(current_line_region) | |
# Determine syntax (language) | |
syntax = view.syntax().scope.split('.')[-1] if view.syntax() else "unknown" | |
# Find the function name and scope range | |
func_name, scope_start, scope_end = self.deduce_function_scope(view, cursor_pos, syntax) | |
if func_name and scope_start and scope_end: | |
sublime.message_dialog( | |
f"Function: {func_name}\n" | |
f"Scope: Lines {scope_start+1}-{scope_end+1}" | |
) | |
# Highlight the scope (optional) | |
view.add_regions("func_scope", [sublime.Region(scope_start, scope_end)], "comment", "", sublime.DRAW_NO_OUTLINE) | |
else: | |
sublime.message_dialog("Not inside a function.") | |
def deduce_function_scope(self, view, cursor_pos, syntax): | |
# Search backward for function declaration | |
func_decl_pattern = self.get_function_pattern(syntax) | |
if not func_decl_pattern: | |
return None, None, None | |
# Iterate backward to find the nearest function declaration | |
line_regions = reversed(view.lines(sublime.Region(0, cursor_pos))) | |
for line_region in line_regions: | |
line_text = view.substr(line_region).strip() | |
match = re.match(func_decl_pattern, line_text) | |
if match: | |
func_name = match.group(1) | |
scope_start = line_region.begin() | |
# Find scope end based on syntax | |
scope_end = self.find_scope_end(view, line_region, syntax) | |
return func_name, scope_start, scope_end | |
return None, None, None | |
def get_function_pattern(self, syntax): | |
# Regex patterns for function declarations (customize as needed) | |
patterns = { | |
"python": r'^\s*def\s+(\w+)\s*\(', | |
"javascript": r'function\s+(\w+)\s*\(.*\)\s*\{?', | |
"php": r'function\s+(\w+)\s*\(.*\)\s*\{?', | |
"ruby": r'def\s+(\w+)\s*', | |
} | |
return patterns.get(syntax.lower()) | |
def find_scope_end(self, view, decl_region, syntax): | |
# Find end of function scope (braces or indentation) | |
if syntax == "python": | |
return self.find_python_scope_end(view, decl_region) | |
else: | |
return self.find_brace_scope_end(view, decl_region) | |
def find_brace_scope_end(self, view, decl_region): | |
# Match curly braces for languages like JS/PHP/C++ | |
start_pos = decl_region.end() | |
brace_count = 0 | |
for pos in range(start_pos, view.size()): | |
char = view.substr(pos) | |
if char == '{': | |
brace_count += 1 | |
elif char == '}': | |
brace_count -= 1 | |
if brace_count == 0: | |
return pos + 1 # Include closing brace | |
return decl_region.end() # Fallback | |
def find_python_scope_end(self, view, decl_region): | |
# Match indentation level for Python | |
decl_line = view.line(decl_region) | |
base_indent = len(view.substr(decl_line).expandtabs(4)) - len(view.substr(decl_line).lstrip().expandtabs(4)) | |
next_line = decl_line.end() + 1 | |
while next_line < view.size(): | |
line_region = view.line(next_line) | |
line_text = view.substr(line_region) | |
if not line_text.strip(): | |
next_line = line_region.end() + 1 | |
continue | |
current_indent = len(line_text.expandtabs(4)) - len(line_text.lstrip().expandtabs(4)) | |
if current_indent <= base_indent: | |
return line_region.begin() - 1 | |
next_line = line_region.end() + 1 | |
return view.size() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment