Compare commits

..

2 Commits

Author SHA1 Message Date
ff27fbdf6c Merge pull request 'develop' (#2) from develop into master
Reviewed-on: #2
2025-11-30 05:25:34 +00:00
619fae8a20 Merge pull request 'develop' (#1) from develop into master
Reviewed-on: #1
2024-02-11 01:53:00 +00:00
202 changed files with 753 additions and 7880 deletions

View File

@@ -10,19 +10,19 @@ class Manifest:
author: str = "John Doe" author: str = "John Doe"
version: str = "0.0.1" version: str = "0.0.1"
support: str = "" support: str = ""
pre_launch: bool = False
requests: {} = { requests: {} = {
'pass_ui_objects': ["plugin_control_list"], 'pass_ui_objects': ["plugin_control_list"],
'pass_events': True, 'pass_events': "true",
'bind_keys': [] 'bind_keys': []
} }
pre_launch: bool = False
``` ```
### Requests ### Requests
``` ```
requests: {} = { requests: {} = {
'pass_events': true, # If empty or not present will be ignored. 'pass_events': "true", # If empty or not present will be ignored.
"pass_ui_objects": [""], # Request reference to a UI component. Will be passed back as array to plugin. "pass_ui_objects": [""], # Request reference to a UI component. Will be passed back as array to plugin.
'bind_keys': [f"{name}||send_message:<Control>f"], 'bind_keys': [f"{name}||send_message:<Control>f"],
f"{name}||do_save:<Control>s"] # Bind keys with method and key pare using list. Must pass "name" like shown with delimiter to its right. f"{name}||do_save:<Control>s"] # Bind keys with method and key pare using list. Must pass "name" like shown with delimiter to its right.

View File

@@ -1,3 +0,0 @@
"""
Pligin Module
"""

View File

@@ -1,3 +0,0 @@
"""
Pligin Package
"""

View File

@@ -1,7 +0,0 @@
{
"name": "Example Completer",
"author": "John Doe",
"version": "0.0.1",
"support": "",
"requests": {}
}

View File

@@ -1,40 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from libs.dto.base_event import BaseEvent
from libs.event_factory import Event_Factory
from plugins.plugin_types import PluginCode
from .provider import Provider
class Plugin(PluginCode):
def __init__(self):
super(Plugin, self).__init__()
self.provider: Provider = None
def _controller_message(self, event: BaseEvent):
...
def load(self):
self.provider = Provider()
event = Event_Factory.create_event(
"register_provider",
provider_name = "Example Completer",
provider = self.provider,
language_ids = []
)
self.message_to("completion", event)
def run(self):
...

View File

@@ -1,76 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GObject
from gi.repository import GtkSource
# Application imports
from .provider_response_cache import ProviderResponseCache
class Provider(GObject.GObject, GtkSource.CompletionProvider):
"""
This is a custom Completion Example Provider.
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
"""
__gtype_name__ = 'ExampleCompletionProvider'
def __init__(self):
super(Provider, self).__init__()
self.response_cache: ProviderResponseCache = ProviderResponseCache()
def do_get_name(self):
""" Returns: a new string containing the name of the provider. """
return 'Example Code Completion'
def do_match(self, context):
# word = context.get_word()
# if not word or len(word) < 2: return False
""" Get whether the provider match the context of completion detailed in context. """
word = self.response_cache.get_word(context)
if not word or len(word) < 2: return False
return True
def do_get_priority(self):
""" Determin position in result list along other providor results. """
return 5
def do_activate_proposal(self, proposal, iter_):
""" Manually handle actual completion insert or set flags and handle normally. """
buffer = iter_.get_buffer()
# Note: Flag mostly intended for SourceViewsMultiInsertState
# to insure marker processes inserted text correctly.
buffer.is_processing_completion = True
return False
def do_get_activation(self):
""" The context for when a provider will show results """
# return GtkSource.CompletionActivation.NONE
# return GtkSource.CompletionActivation.USER_REQUESTED
# return GtkSource.CompletionActivation.USER_REQUESTED | GtkSource.CompletionActivation.INTERACTIVE
return GtkSource.CompletionActivation.INTERACTIVE
def do_populate(self, context):
results = self.response_cache.filter_with_context(context)
proposals = []
for entry in results:
proposals.append(
self.response_cache.create_completion_item(
entry["label"],
entry["text"],
entry["info"]
)
)
context.add_proposals(self, proposals, True)

View File

@@ -1,109 +0,0 @@
# Python imports
import re
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GtkSource', '4')
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import GtkSource
# Application imports
from libs.event_factory import Code_Event_Types
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
class ProviderResponseCache(ProviderResponseCacheBase):
def __init__(self):
super(ProviderResponseCache, self).__init__()
self.matchers: dict = {
"hello": {
"label": "Hello, World!",
"text": "Hello, World!",
"info": GLib.markup_escape_text( "<b>Says the first ever program developers write...</b>" )
},
"foo": {
"label": "foo",
"text": "foo }}"
},
"bar": {
"label": "bar",
"text": "bar }}"
}
}
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
...
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
...
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
...
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
...
def filter(self, word: str) -> list[dict]:
...
def filter_with_context(self, context) -> list[dict]:
"""
In this instance, it will do 2 things:
1) always provide Hello World! (Not ideal but an option so its in the example)
2) Utilizes the Gtk.TextIter from the TextBuffer to determine if there is a jinja
example of '{{ custom.' if so it will provide you with the options of foo and bar.
If selected it will insert foo }} or bar }}, completing your syntax...
PLEASE NOTE the GtkTextIter Logic and regex are really rough and should be adjusted and tuned
"""
proposals: list[dict] = [
{
"label": self.matchers[ "hello" ]["label"],
"text": self.matchers[ "hello" ]["text"],
"info": self.matchers[ "hello" ]["info"]
}
]
# Gtk Versions differ on get_iter responses...
end_iter = context.get_iter()
if not isinstance(end_iter, Gtk.TextIter):
_, end_iter = context.get_iter()
if not end_iter: return
buf = end_iter.get_buffer()
mov_iter = end_iter.copy()
if mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY):
mov_iter, _ = mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY)
left_text = buf.get_text(mov_iter, end_iter, True)
else:
left_text = ''
if re.match(r'.*\{\{\s*custom\.$', left_text):
# optionally proposed based on left search via regex
proposals.append(
{
"label": self.matchers[ "foo" ]["label"],
"text": self.matchers[ "foo" ]["text"],
"info": ""
}
)
# optionally proposed based on left search via regex
proposals.append(
{
"label": self.matchers[ "bar" ]["label"],
"text": self.matchers[ "bar" ]["text"],
"info": ""
}
)
return proposals

View File

@@ -1,3 +0,0 @@
"""
Pligin Module
"""

View File

@@ -1,3 +0,0 @@
"""
Pligin Package
"""

View File

@@ -1,7 +0,0 @@
{
"name": "LSP Completer",
"author": "ITDominator",
"version": "0.0.1",
"support": "",
"requests": {}
}

View File

@@ -1,43 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from libs.dto.base_event import BaseEvent
from libs.event_factory import Event_Factory
from plugins.plugin_types import PluginCode
from .provider import Provider
class Plugin(PluginCode):
def __init__(self):
super(Plugin, self).__init__()
self.provider: Provider = None
def _controller_message(self, event: BaseEvent):
...
def load(self):
self.provider = Provider()
event = Event_Factory.create_event(
"register_provider",
provider_name = "LSP Completer",
provider = self.provider,
language_ids = []
)
self.message_to("completion", event)
def run(self):
...
def generate_plugin_element(self):
...

View File

@@ -1,82 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GObject
from gi.repository import GtkSource
# Application imports
from .provider_response_cache import ProviderResponseCache
class Provider(GObject.GObject, GtkSource.CompletionProvider):
"""
This code is an LSP code completion plugin for Newton.
# NOTE: Some code pulled/referenced from here --> https://github.com/isamert/gedi
"""
__gtype_name__ = 'LSPProvider'
def __init__(self):
super(Provider, self).__init__()
self.response_cache: ProviderResponseCache = ProviderResponseCache()
def pre_populate(self, context):
...
def do_get_name(self):
return "LSP Code Completion"
def do_match(self, context):
word = self.response_cache.get_word(context)
if not word or len(word) < 2: return False
iter = self.response_cache.get_iter_correctly(context)
iter.backward_char()
ch = iter.get_char()
# NOTE: Look to re-add or apply supprting logic to use spaces
# As is it slows down the editor in certain contexts...
# if not (ch in ('_', '.', ' ') or ch.isalnum()):
if not (ch in ('_', '.') or ch.isalnum()):
return False
buffer = iter.get_buffer()
if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']:
return False
return True
def do_get_priority(self):
return 5
def do_activate_proposal(self, proposal, iter_):
buffer = iter_.get_buffer()
# Note: Flag mostly intended for SourceViewsMultiInsertState
# to insure marker processes inserted text correctly.
buffer.is_processing_completion = True
return False
def do_get_activation(self):
""" The context for when a provider will show results """
# return GtkSource.CompletionActivation.NONE
return GtkSource.CompletionActivation.USER_REQUESTED
# return GtkSource.CompletionActivation.INTERACTIVE
def do_populate(self, context):
results = self.response_cache.filter_with_context(context)
proposals = []
for entry in results:
proposals.append(
self.response_cache.create_completion_item(
entry["label"],
entry["text"],
entry["info"]
)
)
context.add_proposals(self, proposals, True)

View File

@@ -1,45 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from libs.event_factory import Code_Event_Types
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
class ProviderResponseCache(ProviderResponseCacheBase):
def __init__(self):
super(ProviderResponseCache, self).__init__()
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
...
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
...
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
...
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
...
def filter(self, word: str) -> list[dict]:
return []
def filter_with_context(self, context: GtkSource.CompletionContext) -> list[dict]:
proposals = [
{
"label": "LSP Class",
"text": "LSP Code",
"info": "A test LSP completion item..."
}
]
return proposals

View File

@@ -1,3 +0,0 @@
"""
Pligin Module
"""

View File

@@ -1,3 +0,0 @@
"""
Pligin Package
"""

View File

@@ -1,3 +0,0 @@
from .parser import load, loads
from .writer import dump, dumps
from .speg import ParseError

View File

@@ -1,295 +0,0 @@
from .speg import peg
import re, sys
if sys.version_info[0] == 2:
_chr = unichr
else:
_chr = chr
def load(fin):
return loads(fin.read())
def loads(s):
if isinstance(s, bytes):
s = s.decode('utf-8')
if s.startswith(u'\ufeff'):
s = s[1:]
return peg(s.replace('\r\n', '\n'), _p_root)
def _p_ws(p):
p('[ \t]*')
def _p_nl(p):
p(r'([ \t]*(?:#[^\n]*)?\r?\n)+')
def _p_ews(p):
with p:
p(_p_nl)
p(_p_ws)
def _p_id(p):
return p(r'[$a-zA-Z_][$0-9a-zA-Z_]*')
_escape_table = {
'r': '\r',
'n': '\n',
't': '\t',
'f': '\f',
'b': '\b',
}
def _p_unescape(p):
esc = p('\\\\(?:u[0-9a-fA-F]{4}|[^\n])')
if esc[1] == 'u':
return _chr(int(esc[2:], 16))
return _escape_table.get(esc[1:], esc[1:])
_re_indent = re.compile(r'[ \t]*')
def _p_block_str(p, c):
p(r'{c}{c}{c}'.format(c=c))
lines = [['']]
with p:
while True:
s = p(r'(?:{c}(?!{c}{c})|[^{c}\\])*'.format(c=c))
l = s.split('\n')
lines[-1].append(l[0])
lines.extend([x] for x in l[1:])
if p(r'(?:\\\n[ \t]*)*'):
continue
p.commit()
lines[-1].append(p(_p_unescape))
p(r'{c}{c}{c}'.format(c=c))
lines = [''.join(l) for l in lines]
strip_ws = len(lines) > 1
if strip_ws and all(c in ' \t' for c in lines[-1]):
lines.pop()
indent = None
for line in lines[1:]:
if not line:
continue
if indent is None:
indent = _re_indent.match(line).group(0)
continue
for i, (c1, c2) in enumerate(zip(indent, line)):
if c1 != c2:
indent = indent[:i]
break
ind_len = len(indent or '')
if strip_ws and all(c in ' \t' for c in lines[0]):
lines = [line[ind_len:] for line in lines[1:]]
else:
lines[1:] = [line[ind_len:] for line in lines[1:]]
return '\n'.join(lines)
_re_mstr_nl = re.compile(r'(?:[ \t]*\n)+[ \t]*')
_re_mstr_trailing_nl = re.compile(_re_mstr_nl.pattern + r'\Z')
def _p_multiline_str(p, c):
p('{c}(?!{c}{c})(?:[ \t]*\n[ \t]*)?'.format(c=c))
string_parts = []
with p:
while True:
string_parts.append(p(r'[^{c}\\]*'.format(c=c)))
if p(r'(?:\\\n[ \t]*)*'):
string_parts.append('')
continue
p.commit()
string_parts.append(p(_p_unescape))
p(c)
string_parts[-1] = _re_mstr_trailing_nl.sub('', string_parts[-1])
string_parts[::2] = [_re_mstr_nl.sub(' ', part) for part in string_parts[::2]]
return ''.join(string_parts)
def _p_string(p):
with p:
return p(_p_block_str, '"')
with p:
return p(_p_block_str, "'")
with p:
return p(_p_multiline_str, '"')
return p(_p_multiline_str, "'")
def _p_array_value(p):
with p:
p(_p_nl)
return p(_p_object)
with p:
p(_p_ws)
return p(_p_line_object)
p(_p_ews)
return p(_p_simple_value)
def _p_key(p):
with p:
return p(_p_id)
return p(_p_string)
def _p_flow_kv(p):
k = p(_p_key)
p(_p_ews)
p(':')
with p:
p(_p_nl)
return k, p(_p_object)
with p:
p(_p_ws)
return k, p(_p_line_object)
p(_p_ews)
return k, p(_p_simple_value)
def _p_flow_obj_sep(p):
with p:
p(_p_ews)
p(',')
p(_p_ews)
return
p(_p_nl)
p(_p_ws)
def _p_simple_value(p):
with p:
p('null')
return None
with p:
p('false')
return False
with p:
p('true')
return True
with p:
return int(p('0b[01]+')[2:], 2)
with p:
return int(p('0o[0-7]+')[2:], 8)
with p:
return int(p('0x[0-9a-fA-F]+')[2:], 16)
with p:
return float(p(r'-?(?:[1-9][0-9]*|0)?\.[0-9]+(?:[Ee][\+-]?[0-9]+)?|(?:[1-9][0-9]*|0)(?:\.[0-9]+)?[Ee][\+-]?[0-9]+'))
with p:
return int(p('-?[1-9][0-9]*|0'), 10)
with p:
return p(_p_string)
with p:
p(r'\[')
r = []
with p:
p.set('I', '')
r.append(p(_p_array_value))
with p:
while True:
with p:
p(_p_ews)
p(',')
rr = p(_p_array_value)
if not p:
p(_p_nl)
with p:
rr = p(_p_object)
if not p:
p(_p_ews)
rr = p(_p_simple_value)
r.append(rr)
p.commit()
with p:
p(_p_ews)
p(',')
p(_p_ews)
p(r'\]')
return r
p(r'\{')
r = {}
p(_p_ews)
with p:
p.set('I', '')
k, v = p(_p_flow_kv)
r[k] = v
with p:
while True:
p(_p_flow_obj_sep)
k, v = p(_p_flow_kv)
r[k] = v
p.commit()
p(_p_ews)
with p:
p(',')
p(_p_ews)
p(r'\}')
return r
def _p_line_kv(p):
k = p(_p_key)
p(_p_ws)
p(':')
p(_p_ws)
with p:
p(_p_nl)
p(p.get('I'))
return k, p(_p_indented_object)
with p:
return k, p(_p_line_object)
with p:
return k, p(_p_simple_value)
p(_p_nl)
p(p.get('I'))
p('[ \t]')
p(_p_ws)
return k, p(_p_simple_value)
def _p_line_object(p):
k, v = p(_p_line_kv)
r = { k: v }
with p:
while True:
p(_p_ws)
p(',')
p(_p_ws)
k, v = p(_p_line_kv)
r[k] = v # uniqueness
p.commit()
return r
def _p_object(p):
p.set('I', p.get('I') + p('[ \t]*'))
r = p(_p_line_object)
with p:
while True:
p(_p_ws)
with p:
p(',')
p(_p_nl)
p(p.get('I'))
rr = p(_p_line_object)
r.update(rr) # unqueness
p.commit()
return r
def _p_indented_object(p):
p.set('I', p.get('I') + p('[ \t]'))
return p(_p_object)
def _p_root(p):
with p:
p(_p_nl)
with p:
p.set('I', '')
r = p(_p_object)
p(_p_ws)
with p:
p(',')
if not p:
p(_p_ws)
r = p(_p_simple_value)
p(_p_ews)
p(p.eof)
return r

View File

@@ -1 +0,0 @@
from .peg import peg, ParseError

View File

@@ -1,147 +0,0 @@
import sys, re
class ParseError(Exception):
def __init__(self, msg, text, offset, line, col):
self.msg = msg
self.text = text
self.offset = offset
self.line = line
self.col = col
super(ParseError, self).__init__(msg, offset, line, col)
if sys.version_info[0] == 2:
_basestr = basestring
else:
_basestr = str
def peg(s, r):
p = _Peg(s)
try:
return p(r)
except _UnexpectedError as e:
offset = max(p._errors)
err = p._errors[offset]
raise ParseError(err.msg, s, offset, err.line, err.col)
class _UnexpectedError(RuntimeError):
def __init__(self, state, expr):
self.state = state
self.expr = expr
class _PegState:
def __init__(self, pos, line, col):
self.pos = pos
self.line = line
self.col = col
self.vars = {}
self.commited = False
class _PegError:
def __init__(self, msg, line, col):
self.msg = msg
self.line = line
self.col = col
class _Peg:
def __init__(self, s):
self._s = s
self._states = [_PegState(0, 1, 1)]
self._errors = {}
self._re_cache = {}
def __call__(self, r, *args, **kw):
if isinstance(r, _basestr):
compiled = self._re_cache.get(r)
if not compiled:
compiled = re.compile(r)
self._re_cache[r] = compiled
st = self._states[-1]
m = compiled.match(self._s[st.pos:])
if not m:
self.error(expr=r, err=kw.get('err'))
ms = m.group(0)
st.pos += len(ms)
nl_pos = ms.rfind('\n')
if nl_pos < 0:
st.col += len(ms)
else:
st.col = len(ms) - nl_pos
st.line += ms[:nl_pos].count('\n') + 1
return ms
else:
kw.pop('err', None)
return r(self, *args, **kw)
def __repr__(self):
pos = self._states[-1].pos
vars = {}
for st in self._states:
vars.update(st.vars)
return '_Peg(%r, %r)' % (self._s[:pos] + '*' + self._s[pos:], vars)
@staticmethod
def eof(p):
if p._states[-1].pos != len(p._s):
p.error()
def error(self, err=None, expr=None):
st = self._states[-1]
if err is None:
err = 'expected {!r}, found {!r}'.format(expr, self._s[st.pos:st.pos+4])
self._errors[st.pos] = _PegError(err, st.line, st.col)
raise _UnexpectedError(st, expr)
def get(self, key, default=None):
for state in self._states[::-1]:
if key in state.vars:
return state.vars[key][0]
return default
def set(self, key, value):
self._states[-1].vars[key] = value, False
def set_global(self, key, value):
self._states[-1].vars[key] = value, True
def opt(self, *args, **kw):
with self:
return self(*args, **kw)
def not_(self, s, *args, **kw):
with self:
self(s)
self.error()
def __enter__(self):
self._states[-1].committed = False
self._states.append(_PegState(self._states[-1].pos, self._states[-1].line, self._states[-1].col))
def __exit__(self, type, value, traceback):
if type is None:
self.commit()
self._states.pop()
return type == _UnexpectedError
def commit(self):
cur = self._states[-1]
prev = self._states[-2]
for key in cur.vars:
val, g = cur.vars[key]
if not g:
continue
if key in prev.vars:
prev.vars[key] = val, prev.vars[key][1]
else:
prev.vars[key] = val, True
prev.pos = cur.pos
prev.line = cur.line
prev.col = cur.col
prev.committed = True
def __nonzero__(self):
return self._states[-1].committed
__bool__ = __nonzero__

View File

@@ -1,191 +0,0 @@
import re, json, sys
if sys.version_info[0] == 2:
def _is_num(o):
return isinstance(o, int) or isinstance(o, long) or isinstance(o, float)
def _stringify(o):
if isinstance(o, str):
return unicode(o)
if isinstance(o, unicode):
return o
return None
else:
def _is_num(o):
return isinstance(o, int) or isinstance(o, float)
def _stringify(o):
if isinstance(o, bytes):
return o.decode()
if isinstance(o, str):
return o
return None
_id_re = re.compile(r'[$a-zA-Z_][$0-9a-zA-Z_]*\Z')
class CSONEncoder:
def __init__(self, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False,
indent=None, default=None):
self._skipkeys = skipkeys
self._ensure_ascii = ensure_ascii
self._allow_nan = allow_nan
self._sort_keys = sort_keys
self._indent = ' ' * (indent or 4)
self._default = default
if check_circular:
self._obj_stack = set()
else:
self._obj_stack = None
def _format_simple_val(self, o):
if o is None:
return 'null'
if isinstance(o, bool):
return 'true' if o else 'false'
if _is_num(o):
return str(o)
s = _stringify(o)
if s is not None:
return self._escape_string(s)
return None
def _escape_string(self, s):
r = json.dumps(s, ensure_ascii=self._ensure_ascii)
return u"'{}'".format(r[1:-1].replace("'", r"\'"))
def _escape_key(self, s):
if s is None or isinstance(s, bool) or _is_num(s):
s = str(s)
s = _stringify(s)
if s is None:
if self._skipkeys:
return None
raise TypeError('keys must be a string')
if not _id_re.match(s):
return self._escape_string(s)
return s
def _push_obj(self, o):
if self._obj_stack is not None:
if id(o) in self._obj_stack:
raise ValueError('Circular reference detected')
self._obj_stack.add(id(o))
def _pop_obj(self, o):
if self._obj_stack is not None:
self._obj_stack.remove(id(o))
def _encode(self, o, obj_val=False, indent='', force_flow=False):
if isinstance(o, list):
if not o:
if obj_val:
yield ' []\n'
else:
yield indent
yield '[]\n'
else:
if obj_val:
yield ' [\n'
else:
yield indent
yield '[\n'
indent = indent + self._indent
self._push_obj(o)
for v in o:
for chunk in self._encode(v, obj_val=False, indent=indent, force_flow=True):
yield chunk
self._pop_obj(o)
yield indent[:-len(self._indent)]
yield ']\n'
elif isinstance(o, dict):
items = [(self._escape_key(k), v) for k, v in o.items()]
if self._skipkeys:
items = [(k, v) for k, v in items if k is not None]
if self._sort_keys:
items.sort()
if force_flow or not items:
if not items:
if obj_val:
yield ' {}\n'
else:
yield indent
yield '{}\n'
else:
if obj_val:
yield ' {\n'
else:
yield indent
yield '{\n'
indent = indent + self._indent
self._push_obj(o)
for k, v in items:
yield indent
yield k
yield ':'
for chunk in self._encode(v, obj_val=True, indent=indent + self._indent, force_flow=False):
yield chunk
self._pop_obj(o)
yield indent[:-len(self._indent)]
yield '}\n'
else:
if obj_val:
yield '\n'
self._push_obj(o)
for k, v in items:
yield indent
yield k
yield ':'
for chunk in self._encode(v, obj_val=True, indent=indent + self._indent, force_flow=False):
yield chunk
self._pop_obj(o)
else:
v = self._format_simple_val(o)
if v is None:
self._push_obj(o)
v = self.default(o)
for chunk in self._encode(v, obj_val=obj_val, indent=indent, force_flow=force_flow):
yield chunk
self._pop_obj(o)
else:
if obj_val:
yield ' '
else:
yield indent
yield v
yield '\n'
def iterencode(self, o):
return self._encode(o)
def encode(self, o):
return ''.join(self.iterencode(o))
def default(self, o):
if self._default is None:
raise TypeError('Cannot serialize an object of type {}'.format(type(o).__name__))
return self._default(o)
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None,
indent=None, default=None, sort_keys=False, **kw):
if indent is None and cls is None:
return json.dump(obj, fp, skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
allow_nan=allow_nan, default=default, sort_keys=sort_keys, separators=(',', ':'))
if cls is None:
cls = CSONEncoder
encoder = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
allow_nan=allow_nan, sort_keys=sort_keys, indent=indent, default=default, **kw)
for chunk in encoder.iterencode(obj):
fp.write(chunk)
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None,
default=None, sort_keys=False, **kw):
if indent is None and cls is None:
return json.dumps(obj, skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
allow_nan=allow_nan, default=default, sort_keys=sort_keys, separators=(',', ':'))
if cls is None:
cls = CSONEncoder
encoder = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii, check_circular=check_circular,
allow_nan=allow_nan, sort_keys=sort_keys, indent=indent, default=default, **kw)
return encoder.encode(obj)

View File

@@ -1,7 +0,0 @@
{
"name": "Snippets Completer",
"author": "ITDominator",
"version": "0.0.1",
"support": "",
"requests": {}
}

View File

@@ -1,40 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from libs.dto.base_event import BaseEvent
from libs.event_factory import Event_Factory
from plugins.plugin_types import PluginCode
from .provider import Provider
class Plugin(PluginCode):
def __init__(self):
super(Plugin, self).__init__()
self.provider: Provider = None
def _controller_message(self, event: BaseEvent):
...
def load(self):
self.provider = Provider()
event = Event_Factory.create_event(
"register_provider",
provider_name = "Snippets Completer",
provider = self.provider,
language_ids = []
)
self.message_to("completion", event)
def run(self):
...

View File

@@ -1,68 +0,0 @@
# Python imports
import re
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GObject
from gi.repository import GtkSource
# Application imports
from .provider_response_cache import ProviderResponseCache
class Provider(GObject.GObject, GtkSource.CompletionProvider):
"""
This is a Snippits Completion Provider.
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
"""
__gtype_name__ = 'SnippetsCompletionProvider'
def __init__(self):
super(Provider, self).__init__()
self.response_cache: ProviderResponseCache = ProviderResponseCache()
def do_get_name(self):
return 'Snippits Completion'
def do_match(self, context):
word = self.response_cache.get_word(context)
if not word or len(word) < 2: return False
return True
def do_get_priority(self):
return 2
def do_activate_proposal(self, proposal, iter_):
buffer = iter_.get_buffer()
# Note: Flag mostly intended for SourceViewsMultiInsertState
# to insure marker processes inserted text correctly.
buffer.is_processing_completion = True
return False
def do_get_activation(self):
""" The context for when a provider will show results """
# return GtkSource.CompletionActivation.NONE
return GtkSource.CompletionActivation.USER_REQUESTED
# return GtkSource.CompletionActivation.INTERACTIVE
def do_populate(self, context):
word = self.response_cache.get_word(context)
results = self.response_cache.filter(word)
proposals = []
for entry in results:
proposals.append(
self.response_cache.create_completion_item(
entry["label"],
entry["text"],
entry["info"]
)
)
context.add_proposals(self, proposals, True)

View File

@@ -1,68 +0,0 @@
# Python imports
from os import path
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GLib
from gi.repository import GtkSource
# Application imports
from libs.event_factory import Code_Event_Types
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
from . import cson
class ProviderResponseCache(ProviderResponseCacheBase):
def __init__(self):
super(ProviderResponseCache, self).__init__()
self.matchers: dict = {}
self.load_snippets()
def load_snippets(self):
fpath = path.join(path.dirname(path.realpath(__file__)), "snippets.cson")
with open(fpath, 'rb') as f:
self.snippets = cson.load(f)
for group in self.snippets:
self.snippets[group]
for entry in self.snippets[group]:
data = self.snippets[group][entry]
self.matchers[ data["prefix"] ] = {
"label": entry,
"text": data["body"],
"info": GLib.markup_escape_text( data["body"] )
}
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
...
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
...
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
...
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
...
def filter(self, word: str) -> list[dict]:
response: list[dict] = []
for entry in self.matchers:
if not word in entry: continue
data = self.matchers[entry]
response.append(data)
return response
def filter_with_context(self, context: GtkSource.CompletionContext) -> list[dict]:
response: list[dict] = []
return response

View File

@@ -1,614 +0,0 @@
# Your snippets
#
# Atom snippets allow you to enter a simple prefix in the editor and hit tab to
# expand the prefix into a larger code block with templated values.
#
# You can create a new snippet in this file by typing "snip" and then hitting
# tab.
#
# An example CoffeeScript snippet to expand log to console.log:
#
# '.source.coffee':
# 'Console log':
# 'prefix': 'log'
# 'body': 'console.log $1'
#
# Each scope (e.g. '.source.coffee' above) can only be declared once.
#
# This file uses CoffeeScript Object Notation (CSON).
# If you are unfamiliar with CSON, you can read more about it in the
# Atom Flight Manual:
# http://flight-manual.atom.io/using-atom/sections/basic-customization/#_cson
### HTML SNIPPETS ###
'.text.html.basic':
'HTML Template':
'prefix': 'html'
'body': """<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="shortcut icon" href="fave_icon.png">
<link rel="stylesheet" href="resources/css/base.css">
<link rel="stylesheet" href="resources/css/main.css">
</head>
<body>
<script src="resources/js/.js" charset="utf-8"></script>
<script src="resources/js/.js" charset="utf-8"></script>
</body>
</html>
"""
'Canvas Tag':
'prefix': 'canvas'
'body': """<canvas id="canvas" width="800" height="600" style="border:1px solid #c3c3c3;"></canvas>"""
'Img Tag':
'prefix': 'img'
'body': """<img class="" src="" alt="" />"""
'Br Tag':
'prefix': 'br'
'body': """<br/>"""
'Hr Tag':
'prefix': 'hr'
'body': """<hr/>"""
'Server Side Events':
'prefix': 'sse'
'body': """// SSE events if supported
if(typeof(EventSource) !== "undefined") {
let source = new EventSource("resources/php/sse.php");
source.onmessage = (event) => {
if (event.data === "<yourDataStringToLookFor>") {
// code here
}
};
} else {
console.log("SSE Not Supported In Browser...");
}
"""
'AJAX Template Function':
'prefix': 'ajax template'
'body': """const doAjax = async (actionPath, data) => {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
if (this.responseText != null) { // this.responseXML if getting XML fata
handleReturnData(JSON.parse(this.responseText));
} else {
console.log("No content returned. Check the file path.");
}
}
};
xhttp.open("POST", actionPath, true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Force return to be JSON NOTE: Use application/xml to force XML
xhttp.overrideMimeType('application/json');
xhttp.send(data);
}
"""
'CSS Message Colors':
'prefix': 'css colors'
'body': """.error { color: rgb(255, 0, 0); }
.warning { color: rgb(255, 168, 0); }
.success { color: rgb(136, 204, 39); }
"""
### JS SNIPPETS ###
'.source.js':
'Server Side Events':
'prefix': 'sse'
'body': """// SSE events if supported
if(typeof(EventSource) !== "undefined") {
let source = new EventSource("resources/php/sse.php");
source.onmessage = (event) => {
if (event.data === "<yourDataStringToLookFor>") {
// code here
}
};
} else {
console.log("SSE Not Supported In Browser...");
}
"""
'AJAX Template Function':
'prefix': 'ajax template'
'body': """const doAjax = async (actionPath, data) => {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
if (this.responseText != null) { // this.responseXML if getting XML fata
handleReturnData(JSON.parse(this.responseText));
} else {
console.log("No content returned. Check the file path.");
}
}
};
xhttp.open("POST", actionPath, true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Force return to be JSON NOTE: Use application/xml to force XML
xhttp.overrideMimeType('application/json');
xhttp.send(data);
}
"""
'SE6 Function':
'prefix': 'function se6'
'body': """const funcName = (arg = "") => {
}
"""
### CSS SNIPPETS ###
'.source.css':
'CSS Message Colors':
'prefix': 'css colors'
'body': """.error { color: rgb(255, 0, 0); }
.warning { color: rgb(255, 168, 0); }
.success { color: rgb(136, 204, 39); }
"""
### PHP SNIPPETS ###
'.text.html.php':
'SSE PHP':
'prefix': 'sse php'
'body': """<?php
// Start the session
session_start();
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
echo "data:dataToReturn\\\\n\\\\n";
flush();
?>
"""
'PHP Template':
'prefix': 'php'
'body': """<?php
// Start the session
session_start();
// Determin action
chdir("../../"); // Note: If in resources/php/
if (isset($_POST['yourPostID'])) {
// code here
} else {
$message = "Server: [Error] --> Illegal Access Method!";
serverMessage("error", $message);
}
?>
"""
'HTML Template':
'prefix': 'html'
'body': """<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="shortcut icon" href="fave_icon.png">
<link rel="stylesheet" href="resources/css/base.css">
<link rel="stylesheet" href="resources/css/main.css">
</head>
<body>
<script src="resources/js/.js" charset="utf-8"></script>
<script src="resources/js/.js" charset="utf-8"></script>
</body>
</html>
"""
### BASH SNIPPETS ###
'.source.shell':
'Bash or Shell Template':
'prefix': 'bash template'
'body': """#!/bin/bash
# . CONFIG.sh
# set -o xtrace ## To debug scripts
# set -o errexit ## To exit on error
# set -o errunset ## To exit if a variable is referenced but not set
function main() {
cd "$(dirname "$0")"
echo "Working Dir: " $(pwd)
file="$1"
if [ -z "${file}" ]; then
echo "ERROR: No file argument supplied..."
exit
fi
if [[ -f "${file}" ]]; then
echo "SUCCESS: The path and file exists!"
else
echo "ERROR: The path or file '${file}' does NOT exist..."
fi
}
main "$@";
"""
'Bash or Shell Config':
'prefix': 'bash config'
'body': """#!/bin/bash
shopt -s expand_aliases
alias echo="echo -e"
"""
### PYTHON SNIPPETS ###
'.source.python':
'Glade __main__ Class Template':
'prefix': 'glade __main__ class'
'body': """#!/usr/bin/python3
# Python imports
import argparse
import faulthandler
import traceback
import signal
from setproctitle import setproctitle
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib
# Application imports
from app import Application
def run():
try:
setproctitle('<replace this>')
faulthandler.enable() # For better debug info
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit)
parser = argparse.ArgumentParser()
# Add long and short arguments
parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.")
parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.")
parser.add_argument("--no-plugins", "-np", default="false", help="Do not load plugins.")
parser.add_argument("--new-tab", "-t", default="", help="Open a file into new tab.")
parser.add_argument("--new-window", "-w", default="", help="Open a file into a new window.")
# Read arguments (If any...)
args, unknownargs = parser.parse_known_args()
main = Application(args, unknownargs)
Gtk.main()
except Exception as e:
traceback.print_exc()
quit()
if __name__ == "__main__":
''' Set process title, get arguments, and create GTK main thread. '''
run()
"""
'Glade __main__ Testing Template':
'prefix': 'glade testing class'
'body': """#!/usr/bin/python3
# Python imports
import traceback
import faulthandler
import signal
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib
# Application imports
app_name = "Gtk Quick Test"
class Application(Gtk.ApplicationWindow):
def __init__(self):
super(Application, self).__init__()
self._setup_styling()
self._setup_signals()
self._load_widgets()
self.add(Gtk.Box())
self.show_all()
def _setup_styling(self):
self.set_default_size(1670, 830)
self.set_title(f"{app_name}")
# self.set_icon_from_file( settings.get_window_icon() )
self.set_gravity(5) # 5 = CENTER
self.set_position(1) # 1 = CENTER, 4 = CENTER_ALWAYS
def _setup_signals(self):
self.connect("delete-event", Gtk.main_quit)
def _load_widgets(self):
...
def run():
try:
faulthandler.enable() # For better debug info
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit)
main = Application()
Gtk.main()
except Exception as e:
traceback.print_exc()
quit()
if __name__ == "__main__":
''' Set process title, get arguments, and create GTK main thread. '''
run()
"""
'Glade _init_ Class Template':
'prefix': 'glade __init__ class'
'body': """# Python imports
import inspect
# Lib imports
# Application imports
from utils import Settings
from signal_classes import CrossClassSignals
class Main:
def __init__(self, args):
settings = Settings()
builder = settings.returnBuilder()
# Gets the methods from the classes and sets to handler.
# Then, builder connects to any signals it needs.
classes = [CrossClassSignals(settings)]
handlers = {}
for c in classes:
methods = inspect.getmembers(c, predicate=inspect.ismethod)
handlers.update(methods)
builder.connect_signals(handlers)
window = settings.createWindow()
window.show()
"""
'Class Method':
'prefix': 'def1'
'body': """
def fname(self):
...
"""
'Gtk Class Method':
'prefix': 'def2'
'body': """
def fname(self, widget, eve):
...
"""
'Python Glade Settings Template':
'prefix': 'glade settings class'
'body': """# Python imports
import os
# Lib imports
import gi, cairo
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
# Application imports
class Settings:
def __init__(self):
self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + "/"
self.builder = Gtk.Builder()
self.builder.add_from_file(self.SCRIPT_PTH + "../resources/Main_Window.glade")
# 'Filters'
self.office = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx', '.xlm',
'.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf')
self.vids = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv',
'.mpeg', '.mp4', '.webm')
self.txt = ('.txt', '.text', '.sh', '.cfg', '.conf')
self.music = ('.psf', '.mp3', '.ogg' , '.flac')
self.images = ('.png', '.jpg', '.jpeg', '.gif')
self.pdf = ('.pdf')
def createWindow(self):
# Get window and connect signals
window = self.builder.get_object("Main_Window")
window.connect("delete-event", gtk.main_quit)
self.setWindowData(window, False)
return window
def setWindowData(self, window, paintable):
screen = window.get_screen()
visual = screen.get_rgba_visual()
if visual != None and screen.is_composited():
window.set_visual(visual)
# bind css file
cssProvider = gtk.CssProvider()
cssProvider.load_from_path(self.SCRIPT_PTH + '../resources/stylesheet.css')
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER)
window.set_app_paintable(paintable)
if paintable:
window.connect("draw", self.area_draw)
def getMonitorData(self):
screen = self.builder.get_object("Main_Window").get_screen()
monitors = []
for m in range(screen.get_n_monitors()):
monitors.append(screen.get_monitor_geometry(m))
for monitor in monitors:
print(str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y))
return monitors
def area_draw(self, widget, cr):
cr.set_source_rgba(0, 0, 0, 0.54)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
def returnBuilder(self): return self.builder
# Filter returns
def returnOfficeFilter(self): return self.office
def returnVidsFilter(self): return self.vids
def returnTextFilter(self): return self.txt
def returnMusicFilter(self): return self.music
def returnImagesFilter(self): return self.images
def returnPdfFilter(self): return self.pdf
"""
'Python Glade CrossClassSignals Template':
'prefix': 'glade crossClassSignals class'
'body': """# Python imports
import threading
import subprocess
import os
# Lib imports
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class CrossClassSignals:
def __init__(self, settings):
self.settings = settings
self.builder = self.settings.returnBuilder()
def getClipboardData(self):
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE)
retcode = proc.wait()
data = proc.stdout.read()
return data.decode("utf-8").strip()
def setClipboardData(self, data):
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
proc.stdin.write(data)
proc.stdin.close()
retcode = proc.wait()
"""
'Python Glade Generic Template':
'prefix': 'glade generic class'
'body': """# Python imports
# Lib imports
# Application imports
class GenericClass:
def __init__(self):
super(GenericClass, self).__init__()
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets()
def _setup_styling(self):
...
def _setup_signals(self):
...
def _subscribe_to_events(self):
event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
def _load_widgets(self):
...
"""

View File

@@ -1,3 +0,0 @@
"""
Pligin Module
"""

View File

@@ -1,3 +0,0 @@
"""
Pligin Package
"""

View File

@@ -1,53 +0,0 @@
# Python imports
import re
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GtkSource', '4')
from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import GtkSource
# Application imports
from .provider_response_cache import ProviderResponseCache
class Provider(GtkSource.CompletionWords):
"""
This is a Words Completion Provider.
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
"""
__gtype_name__ = 'WordsCompletionProvider'
def __init__(self):
super(Provider, self).__init__()
self.response_cache: ProviderResponseCache = ProviderResponseCache()
def do_get_name(self):
return 'Words Completion'
def do_match(self, context):
word = self.response_cache.get_word(context)
if not word or len(word) < 2: return False
return True
def do_get_priority(self):
return 0
def do_activate_proposal(self, proposal, iter_):
buffer = iter_.get_buffer()
# Note: Flag mostly intended for SourceViewsMultiInsertState
# to insure marker processes inserted text correctly.
buffer.is_processing_completion = True
return False
def do_get_activation(self):
""" The context for when a provider will show results """
# return GtkSource.CompletionActivation.NONE
# return GtkSource.CompletionActivation.USER_REQUESTED
return GtkSource.CompletionActivation.INTERACTIVE

View File

@@ -1,7 +0,0 @@
{
"name": "Words Completer",
"author": "ITDominator",
"version": "0.0.1",
"support": "",
"requests": {}
}

View File

@@ -1,40 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from libs.dto.base_event import BaseEvent
from libs.event_factory import Event_Factory
from plugins.plugin_types import PluginCode
from .provider import Provider
class Plugin(PluginCode):
def __init__(self):
super(Plugin, self).__init__()
self.provider: Provider = None
def _controller_message(self, event: BaseEvent):
...
def load(self):
self.provider = Provider()
event = Event_Factory.create_event(
"register_provider",
provider_name = "Words Completer",
provider = self.provider,
language_ids = []
)
self.message_to("completion", event)
def run(self):
...

View File

@@ -1,71 +0,0 @@
# Python imports
import re
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GObject
from gi.repository import GtkSource
# Application imports
from .provider_response_cache import ProviderResponseCache
class Provider(GObject.GObject, GtkSource.CompletionProvider):
"""
This is a Words Completion Provider.
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
"""
# __gtype_name__ = 'WordsCompletionProvider'
def __init__(self):
super(Provider, self).__init__()
self.response_cache: ProviderResponseCache = ProviderResponseCache()
def do_get_name(self):
return 'Words Completion'
def do_match(self, context):
word = self.response_cache.get_word(context)
if not word or len(word) < 2: return False
return True
def do_get_priority(self):
return 0
def do_activate_proposal(self, proposal, iter_):
buffer = iter_.get_buffer()
# Note: Flag mostly intended for SourceViewsMultiInsertState
# to insure marker processes inserted text correctly.
buffer.is_processing_completion = True
return False
def do_get_activation(self):
""" The context for when a provider will show results """
# return GtkSource.CompletionActivation.NONE
# return GtkSource.CompletionActivation.USER_REQUESTED
return GtkSource.CompletionActivation.INTERACTIVE
def do_populate(self, context):
word = self.response_cache.get_word(context)
results = self.response_cache.filter_with_context(context)
# results = self.response_cache.filter(word)
# if not results:
# results = self.response_cache.filter_with_context(context)
proposals = []
for entry in results:
proposals.append(
self.response_cache.create_completion_item(
entry["label"],
entry["text"],
entry["info"]
)
)
context.add_proposals(self, proposals, True)

View File

@@ -1,117 +0,0 @@
# Python imports
import asyncio
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GLib
from gi.repository import GtkSource
# Application imports
from libs.event_factory import Code_Event_Types
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
class ProviderResponseCache(ProviderResponseCacheBase):
def __init__(self):
super(ProviderResponseCache, self).__init__()
self.matchers: dict = {}
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
buffer = event.file.buffer
asyncio.run( self._handle_change(buffer) )
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
self.matchers[event.file.buffer] = set()
del self.matchers[event.file.buffer]
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
...
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
buffer = event.file.buffer
asyncio.run( self._handle_change(buffer) )
async def _handle_change(self, buffer):
start_itr = buffer.get_start_iter()
end_itr = buffer.get_end_iter()
data = buffer.get_text(start_itr, end_itr, False)
if not data:
GLib.idle_add(self.load_empty_set, buffer)
return
if not buffer in self.matchers:
GLib.idle_add(self.load_as_new_set, buffer, data)
return
new_words = self.get_all_words(data)
GLib.idle_add(self.load_into_set, buffer, new_words)
def filter(self, word: str) -> list[dict]:
response: list[dict] = []
for entry in self.matchers:
if not word in entry: continue
data = self.matchers[entry]
response.append(data)
return response
def filter_with_context(self, context: GtkSource.CompletionContext) -> list[dict]:
buffer = self.get_iter_correctly(context).get_buffer()
word = self.get_word(context).rstrip()
response: list[dict] = []
for entry in self.matchers[buffer]:
if not entry.rstrip().startswith(word): continue
data = {
"label": entry,
"text": entry,
"info": ""
}
response.append(data)
return response
def load_empty_set(self, buffer):
self.matchers[buffer] = set()
def load_into_set(self, buffer, new_words):
self.matchers[buffer].update(new_words)
def load_as_new_set(self, buffer, data):
self.matchers[buffer] = self.get_all_words(data)
def get_all_words(self, data: str):
words = set()
def is_word_char(c):
return c.isalnum() or c == '_'
size = len(data)
i = 0
while i < size:
# Skip non-word characters
while i < size and not is_word_char(data[i]):
i += 1
start = i
# Consume word characters
while i < size and is_word_char(data[i]):
i += 1
word = data[start:i]
if not word: continue
words.add(word)
return words

View File

@@ -1,9 +1,13 @@
{ {
"manifest": {
"name": "Example Plugin", "name": "Example Plugin",
"author": "John Doe", "author": "John Doe",
"version": "0.0.1", "version": "0.0.1",
"support": "", "support": "",
"requests": { "requests": {
"ui_target": "plugin_control_list",
"pass_events": "true",
"bind_keys": ["Example Plugin||send_message:<Control>f"] "bind_keys": ["Example Plugin||send_message:<Control>f"]
} }
}
} }

View File

@@ -1,4 +1,8 @@
# Python imports # Python imports
import os
import threading
import subprocess
import time
# Lib imports # Lib imports
import gi import gi
@@ -6,36 +10,42 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
# Application imports # Application imports
from libs.dto.base_event import BaseEvent
from plugins.plugin_base import PluginBase from plugins.plugin_base import PluginBase
# NOTE: Threads WILL NOT die with parent's destruction.
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
return wrapper
# NOTE: Threads WILL die with parent's destruction.
def daemon_threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper
class Plugin(PluginBase): class Plugin(PluginBase):
def __init__(self): def __init__(self):
super(Plugin, self).__init__() super().__init__()
self.name = "Example Plugin" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
# where self.name should not be needed for message comms
def _controller_message(self, event: BaseEvent): def generate_reference_ui_element(self):
... button = Gtk.Button(label=self.name)
button.connect("button-release-event", self.send_message)
def load(self): return button
ui_element = self.requests_ui_element("plugin_control_list")
ui_element.add( self.generate_plugin_element() )
def run(self): def run(self):
... ...
def generate_plugin_element(self): def send_message(self, widget=None, eve=None):
button = Gtk.Button(label = self.name)
button.connect("button-release-event", self.send_message)
button.show()
return button
def send_message(self, widget = None, eve = None):
message = "Hello, World!" message = "Hello, World!"
self.emit("display_message", ("warning", message, None)) event_system.emit("display_message", ("warning", message, None))

View File

@@ -5,7 +5,7 @@
"reportDuplicateImport": true, "reportDuplicateImport": true,
"executionEnvironments": [ "executionEnvironments": [
{ {
"root": "./src/" "root": "./src/versions/solarfm-0.0.1/solarfm"
} }
], ],
"venvPath": ".", "venvPath": ".",

View File

@@ -9,10 +9,10 @@ import sys
# Application imports # Application imports
# from libs.db import DB # from libs.db import DB
from libs.event_system import EventSystem from libs.event_system import EventSystem
from libs.endpoint_registry import EndpointRegistry
from libs.keybindings import Keybindings from libs.keybindings import Keybindings
from libs.logger import Logger from libs.logger import Logger
from libs.settings.manager import SettingsManager from libs.settings.manager import SettingsManager
from libs.widget_registery import WidgetRegisteryController
@@ -34,8 +34,12 @@ def daemon_threaded_wrapper(fn):
def call_chain_wrapper(fn): def call_chain_wrapper(fn):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
print()
print()
for line in traceback.format_stack(): for line in traceback.format_stack():
print( line.strip() ) print( line.strip() )
print()
print()
return fn(*args, **kwargs) return fn(*args, **kwargs)
return wrapper return wrapper
@@ -47,16 +51,17 @@ builtins.APP_NAME = "<change_me>"
builtins.keybindings = Keybindings() builtins.keybindings = Keybindings()
builtins.event_system = EventSystem() builtins.event_system = EventSystem()
builtins.endpoint_registry = EndpointRegistry()
builtins.settings_manager = SettingsManager() builtins.settings_manager = SettingsManager()
builtins.widget_registery = WidgetRegisteryController()
# builtins.db = DB() # builtins.db = DB()
settings_manager.load_settings() settings_manager.load_settings()
builtins.settings = settings_manager.settings
builtins.logger = Logger( builtins.logger = Logger(
settings_manager.path_manager.get_home_config_path(), \ settings_manager.get_home_config_path(), \
_ch_log_lvl = settings_manager.settings.debugging.ch_log_lvl, \ _ch_log_lvl = settings.debugging.ch_log_lvl, \
_fh_log_lvl = settings_manager.settings.debugging.fh_log_lvl _fh_log_lvl = settings.debugging.fh_log_lvl
).get_logger() ).get_logger()
builtins.threaded = threaded_wrapper builtins.threaded = threaded_wrapper

View File

@@ -23,14 +23,13 @@ class Application:
def __init__(self): def __init__(self):
super(Application, self).__init__() super(Application, self).__init__()
if not settings_manager.is_trace_debug():
self.load_ipc()
self.setup_debug_hook() self.setup_debug_hook()
def run(self): def run(self):
if not settings_manager.is_trace_debug():
if not self.load_ipc():
return
win = Window() win = Window()
win.start() win.start()
@@ -40,31 +39,23 @@ class Application:
ipc_server = IPCServer() ipc_server = IPCServer()
self.ipc_realization_check(ipc_server) self.ipc_realization_check(ipc_server)
if ipc_server.is_ipc_alive: if not ipc_server.is_ipc_alive:
return True
logger.warning(f"{app_name} IPC Server Exists: Have sent path(s) to it and closing...")
for arg in unknownargs + [args.new_tab,]: for arg in unknownargs + [args.new_tab,]:
if os.path.isfile(arg): if os.path.isfile(arg):
message = f"FILE|{arg}" message = f"FILE|{arg}"
ipc_server.send_ipc_message(message) ipc_server.send_ipc_message(message)
if os.path.isdir(arg): raise AppLaunchException(f"{APP_NAME} IPC Server Exists: Have sent path(s) to it and closing...")
message = f"DIR|{arg}"
ipc_server.send_ipc_message(message)
return False
def ipc_realization_check(self, ipc_server): def ipc_realization_check(self, ipc_server):
try: try:
ipc_server.create_ipc_listener() ipc_server.create_ipc_listener()
except (OSError, PermissionError) as e: except Exception:
logger.info(f"IPC listener creation failed: {e}, falling back to test message")
ipc_server.send_test_ipc_message()
except Exception as e:
logger.error(f"Unexpected IPC setup error: {e}")
ipc_server.send_test_ipc_message() ipc_server.send_test_ipc_message()
with suppress(Exception):
ipc_server.create_ipc_listener()
def setup_debug_hook(self): def setup_debug_hook(self):
# Typically: ValueError: signal only works in main thread # Typically: ValueError: signal only works in main thread
with suppress(ValueError): with suppress(ValueError):

View File

@@ -0,0 +1,33 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
class BuilderWrapper(Gtk.Builder):
"""docstring for BuilderWrapper."""
def __init__(self):
super(BuilderWrapper, self).__init__()
self.objects = {}
def get_object(self, id: str, use_gtk: bool = True) -> any:
if not use_gtk:
return self.objects[id]
return super(BuilderWrapper, self).get_object(id)
def expose_object(self, id: str, object: any, use_gtk: bool = True) -> None:
if not use_gtk:
self.objects[id] = object
else:
super(BuilderWrapper, self).expose_object(id, object)
def dereference_object(self, id: str) -> None:
del self.objects[id]

View File

@@ -16,6 +16,8 @@ class BaseContainer(Gtk.Box):
def __init__(self): def __init__(self):
super(BaseContainer, self).__init__() super(BaseContainer, self).__init__()
self.ctx = self.get_style_context()
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
self._subscribe_to_events() self._subscribe_to_events()
@@ -25,10 +27,8 @@ class BaseContainer(Gtk.Box):
def _setup_styling(self): def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("base-container")
self.set_orientation(Gtk.Orientation.VERTICAL) self.set_orientation(Gtk.Orientation.VERTICAL)
self.ctx.add_class("base-container")
def _setup_signals(self): def _setup_signals(self):
... ...
@@ -38,12 +38,12 @@ class BaseContainer(Gtk.Box):
event_system.subscribe("remove-transparency", self._remove_transparency) event_system.subscribe("remove-transparency", self._remove_transparency)
def _load_widgets(self): def _load_widgets(self):
self.add( HeaderContainer() ) self.add(HeaderContainer())
self.add( BodyContainer() ) self.add(BodyContainer())
self.add( FooterContainer() ) self.add(FooterContainer())
def _update_transparency(self): def _update_transparency(self):
self.ctx.add_class(f"mw_transparency_{settings_manager.settings.theming.transparency}") self.ctx.add_class(f"mw_transparency_{settings.theming.transparency}")
def _remove_transparency(self): def _remove_transparency(self):
self.ctx.remove_class(f"mw_transparency_{settings_manager.settings.theming.transparency}") self.ctx.remove_class(f"mw_transparency_{settings.theming.transparency}")

View File

@@ -16,6 +16,8 @@ class BodyContainer(Gtk.Box):
def __init__(self): def __init__(self):
super(BodyContainer, self).__init__() super(BodyContainer, self).__init__()
self.ctx = self.get_style_context()
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
self._subscribe_to_events() self._subscribe_to_events()
@@ -25,10 +27,8 @@ class BodyContainer(Gtk.Box):
def _setup_styling(self): def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("body-container")
self.set_orientation(Gtk.Orientation.HORIZONTAL) self.set_orientation(Gtk.Orientation.HORIZONTAL)
self.ctx.add_class("body-container")
self.set_homogeneous(True) self.set_homogeneous(True)
def _setup_signals(self): def _setup_signals(self):
@@ -37,7 +37,8 @@ class BodyContainer(Gtk.Box):
def _subscribe_to_events(self): def _subscribe_to_events(self):
... ...
def _load_widgets(self): def _load_widgets(self):
self.add( LeftContainer() ) self.add(LeftContainer())
self.add( CenterContainer() ) self.add(CenterContainer())
self.add( RightContainer() ) self.add(RightContainer())

View File

@@ -14,6 +14,7 @@ class CenterContainer(Gtk.Box):
def __init__(self): def __init__(self):
super(CenterContainer, self).__init__() super(CenterContainer, self).__init__()
self._builder = settings_manager.get_builder()
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
@@ -24,13 +25,14 @@ class CenterContainer(Gtk.Box):
def _setup_styling(self): def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("center-container")
self.set_orientation(Gtk.Orientation.VERTICAL) self.set_orientation(Gtk.Orientation.VERTICAL)
self.set_hexpand(True) self.set_hexpand(True)
self.set_vexpand(True) self.set_vexpand(True)
ctx = self.get_style_context()
ctx.add_class("center-container")
def _setup_signals(self): def _setup_signals(self):
... ...
@@ -38,7 +40,7 @@ class CenterContainer(Gtk.Box):
... ...
def _load_widgets(self): def _load_widgets(self):
glade_box = widget_registery.get_object("glade_box") glade_box = self._builder.get_object("glade_box")
button = Gtk.Button(label = "Click Me!") button = Gtk.Button(label = "Click Me!")
button.connect("clicked", self._hello_world) button.connect("clicked", self._hello_world)

View File

@@ -1,3 +0,0 @@
"""
Containers Package
"""

View File

@@ -1,64 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from ...widgets.code.code_base import CodeBase
from ...widgets.separator_widget import Separator
from ...widgets.code.mini_view_widget import MiniViewWidget
from .editors_container import EditorsContainer
class CodeContainer(Gtk.Box):
def __init__(self):
super(CodeContainer, self).__init__()
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets()
self.show_all()
def _setup_styling(self):
self.set_orientation(Gtk.Orientation.VERTICAL)
def _setup_signals(self):
...
def _subscribe_to_events(self):
...
def _load_widgets(self):
code_base = CodeBase()
self.add( self._create_tabs_widgets(code_base) )
self.add( self._create_editor_widget(code_base) )
def _create_tabs_widgets(self, code_base: CodeBase):
scrolled_window = Gtk.ScrolledWindow()
viewport = Gtk.Viewport()
scrolled_window.set_overlay_scrolling(False)
viewport.add( code_base.get_tabs_widget() )
scrolled_window.add( viewport )
return scrolled_window
def _create_editor_widget(self, code_base: CodeBase):
editors_container = Gtk.Box()
editors_container.add( Separator("separator_left") )
editors_container.add( EditorsContainer(code_base) )
editors_container.add( Separator("separator_right") )
editors_container.add( code_base.get_mini_view_widget() )
return editors_container

View File

@@ -1,71 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib
# Application imports
class EditorsContainer(Gtk.Paned):
def __init__(self, code_base: any):
super(EditorsContainer, self).__init__()
self.code_base = code_base
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets()
def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("paned-editors-container")
self.set_hexpand(True)
self.set_vexpand(True)
self.set_wide_handle(True)
def _setup_signals(self):
self.map_id = self.connect("map", self._init_map)
def _subscribe_to_events(self):
...
def _load_widgets(self):
self.scrolled_win1, \
self.scrolled_win2 = self._create_views()
self.pack1( self.scrolled_win1, True, True )
self.pack2( self.scrolled_win2, True, True )
def _create_views(self):
scrolled_win1 = Gtk.ScrolledWindow()
scrolled_win2 = Gtk.ScrolledWindow()
source_view1 = self.code_base.create_source_view()
source_view2 = self.code_base.create_source_view()
source_view1.sibling_right = source_view2
source_view2.sibling_left = source_view1
scrolled_win1.add( source_view1 )
scrolled_win2.add( source_view2 )
return scrolled_win1, scrolled_win2
def _init_map(self, view):
def _first_show_init():
self.disconnect(self.map_id)
del self.map_id
self.code_base.first_map_load()
del self.code_base
return False
GLib.timeout_add(100, _first_show_init)

View File

@@ -6,7 +6,6 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
# Application imports # Application imports
from .code.code_container import CodeContainer
@@ -14,6 +13,8 @@ class FooterContainer(Gtk.Box):
def __init__(self): def __init__(self):
super(FooterContainer, self).__init__() super(FooterContainer, self).__init__()
self.ctx = self.get_style_context()
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
self._subscribe_to_events() self._subscribe_to_events()
@@ -23,17 +24,18 @@ class FooterContainer(Gtk.Box):
def _setup_styling(self): def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("footer-container")
self.set_orientation(Gtk.Orientation.HORIZONTAL) self.set_orientation(Gtk.Orientation.HORIZONTAL)
self.set_hexpand(True) self.set_hexpand(True)
self.ctx.add_class("footer-container")
def _setup_signals(self): def _setup_signals(self):
... ...
def _subscribe_to_events(self): def _subscribe_to_events(self):
... ...
def _load_widgets(self): def _load_widgets(self):
self.add( CodeContainer() ) ...

View File

@@ -15,6 +15,8 @@ class HeaderContainer(Gtk.Box):
def __init__(self): def __init__(self):
super(HeaderContainer, self).__init__() super(HeaderContainer, self).__init__()
self.ctx = self.get_style_context()
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
self._subscribe_to_events() self._subscribe_to_events()
@@ -24,18 +26,19 @@ class HeaderContainer(Gtk.Box):
def _setup_styling(self): def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("header-container")
self.set_orientation(Gtk.Orientation.HORIZONTAL) self.set_orientation(Gtk.Orientation.HORIZONTAL)
self.set_hexpand(True) self.set_hexpand(True)
self.ctx.add_class("header-container")
def _setup_signals(self): def _setup_signals(self):
... ...
def _subscribe_to_events(self): def _subscribe_to_events(self):
event_system.subscribe("tggl-top-main-menubar", self.tggl_top_main_menubar) event_system.subscribe("tggl-top-main-menubar", self.tggl_top_main_menubar)
def _load_widgets(self): def _load_widgets(self):
button = Gtk.Button(label = "Interactive Debug") button = Gtk.Button(label = "Interactive Debug")
button.connect("clicked", self._interactive_debug) button.connect("clicked", self._interactive_debug)

View File

@@ -22,12 +22,13 @@ class LeftContainer(Gtk.Box):
def _setup_styling(self): def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("left-container")
self.set_orientation(Gtk.Orientation.VERTICAL) self.set_orientation(Gtk.Orientation.VERTICAL)
self.set_vexpand(True) self.set_vexpand(True)
ctx = self.get_style_context()
ctx.add_class("left-container")
def _setup_signals(self): def _setup_signals(self):
... ...

View File

@@ -23,12 +23,13 @@ class RightContainer(Gtk.Box):
def _setup_styling(self): def _setup_styling(self):
self.ctx = self.get_style_context()
self.ctx.add_class("right-container")
self.set_orientation(Gtk.Orientation.VERTICAL) self.set_orientation(Gtk.Orientation.VERTICAL)
self.set_vexpand(True) self.set_vexpand(True)
ctx = self.get_style_context()
ctx.add_class("right-container")
def _setup_signals(self): def _setup_signals(self):
... ...

View File

@@ -6,48 +6,33 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
# Application imports # Application imports
from plugins import plugins_controller
from libs.mixins.ipc_signals_mixin import IPCSignalsMixin from libs.mixins.ipc_signals_mixin import IPCSignalsMixin
from libs.mixins.keyboard_signals_mixin import KeyboardSignalsMixin from libs.mixins.keyboard_signals_mixin import KeyboardSignalsMixin
from ..containers.base_container import BaseContainer from ..containers.base_container import BaseContainer
from .base_controller_mixin import BaseControllerMixin from .base_controller_data import BaseControllerData
from .bridge_controller import BridgeController from .bridge_controller import BridgeController
class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerMixin): class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
""" docstring for BaseController. """ """ docstring for BaseController. """
def __init__(self): def __init__(self):
self._setup_controller_data() self._setup_controller_data()
self._load_plugins(is_pre = True)
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
self._subscribe_to_events() self._subscribe_to_events()
self._load_controllers() self._load_controllers()
self._load_plugins(is_pre = False) self._load_plugins_and_files()
self._load_files()
logger.info(f"Made it past {self.__class__} loading...") logger.info(f"Made it past {self.__class__} loading...")
settings_manager.set_end_load_time() settings_manager.set_end_load_time()
settings_manager.log_load_time() settings_manager.log_load_time()
def _setup_controller_data(self):
self.window = settings_manager.get_main_window()
self.base_container = BaseContainer()
self.plugins_controller = plugins_controller
widget_registery.expose_object("main_window", self.window)
settings_manager.register_signals_to_builder([self, self.base_container])
self._collect_files_dirs()
def _setup_styling(self): def _setup_styling(self):
... ...
@@ -65,22 +50,23 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerMixin)
def _load_controllers(self): def _load_controllers(self):
BridgeController() BridgeController()
def _load_plugins(self, is_pre: bool): def _load_plugins_and_files(self):
args, unknownargs = settings_manager.get_starting_args() args, unknownargs = settings_manager.get_starting_args()
if args.no_plugins == "true": return if args.no_plugins == "false":
if is_pre:
self.plugins_controller.pre_launch_plugins() self.plugins_controller.pre_launch_plugins()
return
if not is_pre:
self.plugins_controller.post_launch_plugins() self.plugins_controller.post_launch_plugins()
return
def _load_files(self):
for file in settings_manager.get_starting_files(): for file in settings_manager.get_starting_files():
event_system.emit("post-file-to-ipc", file) event_system.emit("post-file-to-ipc", file)
def _tggl_top_main_menubar(self): def _tggl_top_main_menubar(self):
logger.debug("_tggl_top_main_menubar > stub...") logger.debug("_tggl_top_main_menubar > stub...")
def _load_glade_file(self):
self.builder.add_from_file( settings_manager.get_glade_file() )
self.builder.expose_object("main_window", self.window)
settings_manager.set_builder(self.builder)
self.base_container = BaseContainer()
settings_manager.register_signals_to_builder([self, self.base_container])

View File

@@ -6,11 +6,28 @@ from shutil import which
# Lib imports # Lib imports
# Application imports # Application imports
from plugins.plugins_controller import PluginsController
from ..builder_wrapper import BuilderWrapper
class BaseControllerMixin: class BaseControllerData:
''' BaseControllerMixin contains most of the state of the app at ay given time. It also has some support methods. ''' ''' BaseControllerData contains most of the state of the app at ay given time. It also has some support methods. '''
def _setup_controller_data(self) -> None:
self.window = settings_manager.get_main_window()
self.builder = BuilderWrapper()
self.plugins_controller = PluginsController()
self.base_container = None
self.was_midified_key = False
self.ctrl_down = False
self.shift_down = False
self.alt_down = False
self._collect_files_dirs()
self._load_glade_file()
def _collect_files_dirs(self): def _collect_files_dirs(self):
args, \ args, \

View File

@@ -1,3 +0,0 @@
"""
Code Package
"""

View File

@@ -1,61 +0,0 @@
# Python imports
# Lib imports
# Application imports
from plugins import plugins_controller
from libs.controllers.controller_manager import ControllerManager
from .controllers.files_controller import FilesController
from .controllers.tabs_controller import TabsController
from .controllers.commands_controller import CommandsController
from .controllers.completion_controller import CompletionController
from .controllers.views.source_views_controller import SourceViewsController
from .mini_view_widget import MiniViewWidget
class CodeBase:
def __init__(self):
super(CodeBase, self).__init__()
self.controller_manager: ControllerManager = ControllerManager()
self.miniview_widget: MiniViewWidget = MiniViewWidget()
self._load_controllers()
def _load_controllers(self):
files_controller = FilesController()
tabs_controller = TabsController()
commands_controller = CommandsController()
completion_controller = CompletionController()
source_views_controller = SourceViewsController()
# self.controller_manager.register_controller("base", self)
self.controller_manager.register_controller("files", files_controller)
self.controller_manager.register_controller("tabs", tabs_controller)
self.controller_manager.register_controller("commands", commands_controller)
self.controller_manager.register_controller("completion", completion_controller)
self.controller_manager.register_controller("source_views", source_views_controller)
self.controller_manager.register_controller("plugins", plugins_controller)
self.controller_manager.register_controller("widgets", widget_registery)
def get_tabs_widget(self):
return self.controller_manager["tabs"].get_tabs_widget()
def get_mini_view_widget(self):
return self.miniview_widget
def create_source_view(self):
source_view = self.controller_manager["source_views"].create_source_view()
self.controller_manager["completion"].register_completer(
source_view.get_completion()
)
return source_view
def first_map_load(self):
self.controller_manager["source_views"].first_map_load()

View File

@@ -1,5 +0,0 @@
"""
Code Command System Package
"""
from .command_system import CommandSystem

View File

@@ -1,27 +0,0 @@
# Python imports
# Lib imports
from gi.repository import GtkSource
# Application imports
def set_language_and_style(view, file):
language = view.language_manager.guess_language(file.fname, None)
file.ftype = "buffer" if not language else language
file.buffer.set_language(language)
file.buffer.set_style_scheme(view.syntax_theme)
return language
def update_info_bar_if_focused(command_system, view: GtkSource):
has_focus = command_system.exec("has_focus")
if has_focus:
command_system.exec("update_info_bar")
def get_file_and_buffer(view: GtkSource):
file = view.command.get_file(view)
buffer = file.buffer
return file, buffer

View File

@@ -1,97 +0,0 @@
# Python imports
# Lib imports
# Application imports
from libs.event_factory import Event_Factory, Code_Event_Types
from ..source_view import SourceView
from . import commands
class CommandSystem:
def __init__(self):
super(CommandSystem, self).__init__()
self.data: list = ()
def set_data(self, *args, **kwargs):
self.data = (args, kwargs)
def exec(self, command: str) -> any:
if not hasattr(commands, command): return
method = getattr(commands, command)
args, kwargs = self.data
if kwargs:
return method.execute(*args, kwargs)
else:
return method.execute(*args)
def exec_with_args(self, command: str, args: list) -> any:
if not hasattr(commands, command): return
method = getattr(commands, command)
return method.execute(*args)
def emit(self, event: Code_Event_Types.CodeEvent):
""" Monkey patch 'emit' from command controller... """
...
def emit_to(self, controller: str, event: Code_Event_Types.CodeEvent):
""" Monkey patch 'emit_to' from command controller... """
...
def get_file(self, view: SourceView):
event = Event_Factory.create_event(
"get_file",
view = view,
buffer = view.get_buffer()
)
self.emit_to("files", event)
return event.response
def get_swap_file(self, view: SourceView):
event = Event_Factory.create_event(
"get_swap_file",
view = view,
buffer = view.get_buffer()
)
self.emit_to("files", event)
return event.response
def new_file(self, view: SourceView):
event = Event_Factory.create_event("add_new_file", view = view)
self.emit_to("files", event)
return event.response
def remove_file(self, view: SourceView):
event = Event_Factory.create_event(
"removed_file",
view = view,
buffer = view.get_buffer()
)
self.emit_to("files", event)
return event.response
def request_completion(self, view: SourceView):
event = Event_Factory.create_event(
"request_completion",
view = view,
buffer = view.get_buffer()
)
self.emit_to("completion", event)

View File

@@ -1,16 +0,0 @@
"""
Code Commands Package
"""
import pkgutil
import importlib
__all__ = []
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
module = importlib.import_module(f"{__name__}.{module_name}")
globals()[module_name] = module # Add module to package namespace
__all__.append(module_name)
del pkgutil
del importlib

View File

@@ -1,23 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Buffer Redo")
buffer = view.get_buffer()
undo_manager = buffer.get_undo_manager()
if undo_manager.can_redo():
buffer.redo()

View File

@@ -1,23 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Buffer Undo")
buffer = view.get_buffer()
undo_manager = buffer.get_undo_manager()
if undo_manager.can_undo():
buffer.undo()

View File

@@ -1,20 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from ..command_helpers import update_info_bar_if_focused
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Close File")
view.command.remove_file(view)
update_info_bar_if_focused(view.command, view)

View File

@@ -1,36 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Cut to Temp Buffer")
view.clear_temp_cut_buffer_delayed()
buffer = view.get_buffer()
itr = buffer.get_iter_at_mark( buffer.get_insert() )
start_itr = itr.copy()
end_itr = itr.copy()
start_line = itr.get_line() + 1
start_char = itr.get_line_offset()
start_itr.backward_visible_line()
start_itr.forward_line()
end_itr.forward_line()
line_str = buffer.get_slice(start_itr, end_itr, True)
view._cut_buffer += f"{line_str}"
buffer.delete(start_itr, end_itr)
view.set_temp_cut_buffer_delayed()

View File

@@ -1,34 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
from gi.repository import Gio
# Application imports
from ..command_helpers import update_info_bar_if_focused
def execute(
view: GtkSource.View,
uri: str
):
logger.debug("Command: DnD Load File To Buffer")
file = view.command.get_file(view)
buffer = file.buffer
if not file.ftype == "buffer":
file = view.command.new_file(view)
gfile = Gio.File.new_for_uri(uri)
view.command.exec_with_args(
"load_file",
(view, gfile, file)
)
update_info_bar_if_focused(view.command, view)

View File

@@ -1,26 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
from gi.repository import Gio
# Application imports
def execute(
view: GtkSource.View,
uris: list = []
):
logger.debug("Command: DnD Load Files")
for uri in uris:
try:
gfile = Gio.File.new_for_uri(uri)
except Exception as e:
gfile = Gio.File.new_for_path(uri)
view.command.exec_with_args("load_file", (view, gfile))

View File

@@ -1,53 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Duplicate Line")
buffer = view.get_buffer()
if not buffer.get_has_selection():
had_selection = False
itr = buffer.get_iter_at_mark( buffer.get_insert() )
start_itr = itr.copy()
end_itr = itr.copy()
start_line = itr.get_line() + 1
start_char = itr.get_line_offset()
else:
had_selection = True
start_itr, end_itr = buffer.get_selection_bounds()
sline = start_itr.get_line()
eline = end_itr.get_line()
start_line = eline + 1
start_char = start_itr.get_line_offset()
end_char = end_itr.get_line_offset()
range_line_size = eline - sline
start_itr.backward_visible_line()
start_itr.forward_line()
end_itr.forward_line()
end_itr.backward_char()
line_str = buffer.get_slice(start_itr, end_itr, True)
end_itr.forward_char()
buffer.insert(end_itr, f"{line_str}\n", -1)
if not had_selection:
new_itr = buffer.get_iter_at_line_offset(start_line, start_char)
buffer.place_cursor(new_itr)
else:
new_itr = buffer.get_iter_at_line_offset(start_line, start_char)
new_end_itr = buffer.get_iter_at_line_offset((start_line + range_line_size), end_char)
buffer.select_range(new_itr, new_end_itr)

View File

@@ -1,19 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Focus Left Sibling")
if not view.sibling_left: return
view.sibling_left.grab_focus()

View File

@@ -1,19 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Focus Right Sibling")
if not view.sibling_right: return
view.sibling_right.grab_focus()

View File

@@ -1,21 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Get Current File")
file = view.command.get_file(view)
return file

View File

@@ -1,19 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Get File Type")
file = view.command.get_file(view)
return file.ftype

View File

@@ -1,21 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Get Text")
buffer = view.get_buffer()
start_itr, end_itr = buffer.get_bounds()
return buffer.get_text(start_itr, end_itr, True)

View File

@@ -1,31 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Go-To")
file = view.command.get_file(view)
gfile = file.get_location()
uri = gfile.get_uri()
buffer = view.get_buffer()
iter = buffer.get_iter_at_mark( buffer.get_insert() )
line = iter.get_line()
offset = iter.get_line_offset()
event_system.emit(
"textDocument/definition",
(view, file.ftype, uri, line, offset,)
)

View File

@@ -1,19 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Has Focus")
ctx = view.get_parent().get_style_context()
return ctx.has_class("source-view-focused")

View File

@@ -1,18 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Line Down")
view.emit("move-lines", True)

View File

@@ -1,18 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Line Up")
view.emit("move-lines", False)

View File

@@ -1,28 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
from gi.repository import Gio
# Application imports
from ...source_file import SourceFile
from ..command_helpers import set_language_and_style
def execute(
view: GtkSource.View,
gfile: Gio.File,
file: SourceFile = None,
):
logger.debug("Command: Load File")
if not file:
file = view.command.new_file(view)
file.load_path(gfile)
set_language_and_style(view, file)

View File

@@ -1,40 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
from gi.repository import Gio
# Application imports
def execute(
view: GtkSource.View,
):
logger.debug("Command: Load Start File(s)")
starting_files = settings_manager.get_starting_files()
if len(starting_files) == 0: return
file = starting_files.pop()
file = file.replace("FILE|", "")
gfile = Gio.File.new_for_path(file)
file = view.command.get_file(view)
view.command.exec_with_args(
"load_file",
(view, gfile, file)
)
if len(starting_files) == 0: return
for file in starting_files:
file = file.replace("FILE|", "")
gfile = Gio.File.new_for_path(file)
view.command.exec_with_args("load_file", (view, gfile))

View File

@@ -1,29 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Move To Left Sibling")
if not view.sibling_left: return
buffer = view.get_buffer()
popped_file, next_file = view.command.get_swap_file(view)
view.sibling_left.set_buffer(buffer)
view.sibling_left.grab_focus()
if next_file:
view.set_buffer(next_file.buffer)
else:
view.command.exec("new_file")

View File

@@ -1,29 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Move To Right Sibling")
if not view.sibling_right: return
buffer = view.get_buffer()
popped_file, next_file = view.command.get_swap_file(view)
view.sibling_right.set_buffer(buffer)
view.sibling_right.grab_focus()
if next_file:
view.set_buffer(next_file.buffer)
else:
view.command.exec("new_file")

View File

@@ -1,27 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from ..command_helpers import set_language_and_style, update_info_bar_if_focused
def execute(
view: GtkSource.View = None
):
logger.debug("Command: New File")
file = view.command.new_file(view)
set_language_and_style(view, file)
view.set_buffer(file.buffer)
update_info_bar_if_focused(view.command, view)
return file

View File

@@ -1,30 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from ..command_helpers import update_info_bar_if_focused
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Open File(s)")
gfiles = event_system.emit_and_await("open-files")
if not gfiles: return
file = view.command.get_file(view)
if file.ftype == "buffer":
gfile = gfiles.pop()
view.command.exec_with_args("load_file", (view, gfile, file))
view.set_buffer(file.buffer)
update_info_bar_if_focused(view.command, view)
for i, gfile in enumerate(gfiles):
view.command.exec_with_args("load_file", (view, gfile))

View File

@@ -1,28 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GLib
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Paste Temp Buffer")
view.clear_temp_cut_buffer_delayed()
buffer = view.get_buffer()
itr = buffer.get_iter_at_mark( buffer.get_insert() )
insert_itr = itr.copy()
buffer.insert(insert_itr, view._cut_buffer, -1)
view.set_temp_cut_buffer_delayed()

View File

@@ -1,28 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from ..command_helpers import set_language_and_style
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Save File")
file = view.command.get_file(view)
buffer = file.buffer
if file.ftype == "buffer":
file.save_as()
set_language_and_style(view, file)
return
file.save()

View File

@@ -1,26 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from ..command_helpers import set_language_and_style, update_info_bar_if_focused
def execute(
view: GtkSource.View = None
):
logger.info("Command: Save File As")
file = view.command.get_file(view)
buffer = file.buffer
file.save_as()
set_language_and_style(view, file)
update_info_bar_if_focused(view.command, view)

View File

@@ -1,30 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from ...source_file import SourceFile
from ..command_helpers import update_info_bar_if_focused
def execute(
view: GtkSource.View,
file: SourceFile
):
logger.debug("Command: Set Buffer")
if not file:
view.command.new_file(view)
return
view.set_buffer(file.buffer)
update_info_bar_if_focused(view.command, view)

View File

@@ -1,23 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View,
language: str
):
logger.debug("Command: Set Buffer Language")
buffer = view.get_buffer()
buffer.set_language(
view.language_manager.get_language(language)
)

View File

@@ -1,23 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View,
style: str
):
logger.debug("Command: Set Buffer Style")
buffer = view.get_buffer()
buffer.set_style_scheme(
view.style_scheme_manager.get_scheme(style)
)

View File

@@ -1,26 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Set Focus Border")
ctx = view.get_parent().get_style_context()
ctx.add_class("source-view-focused")
if view.sibling_right:
ctx = view.sibling_right.get_parent().get_style_context()
elif view.sibling_left:
ctx = view.sibling_left.get_parent().get_style_context()
ctx.remove_class("source-view-focused")

View File

@@ -1,18 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View,
):
logger.debug("Command: Set MiniView")
event_system.emit("set-mini-view", (view,))

View File

@@ -1,28 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Show Completion")
completer = view.get_completion()
providers = completer.get_providers()
if not providers:
view.command.request_completion(view)
return
completer.start(
providers,
completer.create_context()
)

View File

@@ -1,31 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View,
):
logger.debug("Command: Update Info Bar")
file = view.command.get_file(view)
buffer = file.buffer
if not file: return
iter = buffer.get_iter_at_mark( buffer.get_insert() )
line = iter.get_line() + 1
column = iter.get_line_offset()
ftype = file.ftype.get_id() if hasattr(file.ftype, "get_id") else file.ftype
event_system.emit(
"set-info-labels",
(file.fpath, f"{line}:{column}", ftype, file.encoding)
)

View File

@@ -1,23 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Zoom In")
ctx = view.get_style_context()
if view.zoom_level < 99:
ctx.remove_class(f"px{view.zoom_level}")
view.zoom_level += 1
ctx.add_class(f"px{view.zoom_level}")

View File

@@ -1,23 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
def execute(
view: GtkSource.View = None
):
logger.debug("Command: Zoom Out")
ctx = view.get_style_context()
if view.zoom_level > 1:
ctx.remove_class(f"px{view.zoom_level}")
view.zoom_level -= 1
ctx.add_class(f"px{view.zoom_level}")

View File

@@ -1,3 +0,0 @@
"""
Code Completion Providers Package
"""

View File

@@ -1,119 +0,0 @@
# Python imports
import re
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GtkSource', '4')
from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import GtkSource
# Application imports
class ProviderResponseCacheException(Exception):
...
class ProviderResponseCacheBase:
def __init__(self):
super(ProviderResponseCacheBase, self).__init__()
self._icon_theme = Gtk.IconTheme.get_default()
def process_file_load(self, buffer: GtkSource.Buffer):
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_load' not implemented...")
def process_file_close(self, buffer: GtkSource.Buffer):
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_close' not implemented...")
def process_file_save(self, buffer: GtkSource.Buffer):
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_save' not implemented...")
def process_file_change(self, buffer: GtkSource.Buffer):
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_change' not implemented...")
def filter(self, word: str) -> list[dict]:
raise ProviderResponseCacheException("ProviderResponseCacheBase 'filter' not implemented...")
def filter_with_context(self, context: GtkSource.CompletionContext) -> list[dict]:
raise ProviderResponseCacheException("ProviderResponseCacheBase 'filter_with_context' not implemented...")
def create_completion_item(
self,
label: str = "",
text: str = "",
info: str = "",
icon: any = None
) -> dict:
if not label or not text: return
comp_item = GtkSource.CompletionItem.new()
comp_item.set_label(label)
comp_item.set_text(text)
if info:
comp_item.set_info(info)
# comp_item.set_markup(f"<h3>{info}</h3>")
if icon:
comp_item.set_icon(
self.get_icon_for_type(icon.type)
)
return comp_item
def get_all_marks(self, buffer) -> list:
marks: list = []
iter_ = buffer.get_start_iter()
while iter_:
marks = iter_.get_marks()
for mark in marks:
if mark and mark not in marks:
marks.append(mark)
if not iter_.forward_char():
break
return marks
def get_all_insert_marks(self, buffer) -> list:
marks: list = []
iter_ = buffer.get_start_iter()
while iter_:
marks = iter_.get_marks()
for mark in marks:
if mark.get_name() and "multi_insert_" in mark.get_name():
marks.append(mark)
if not iter_.forward_char():
break
return marks
def get_word(self, context) -> str:
start_iter = self.get_iter_correctly(context)
end_iter = start_iter.copy()
if not start_iter.starts_word():
start_iter.backward_word_start()
if not end_iter.ends_word():
end_iter.forward_word_end()
buffer = start_iter.get_buffer()
return buffer.get_text(start_iter, end_iter, False)
def get_iter_correctly(self, context) -> Gtk.TextIter:
return context.get_iter()[1] if isinstance(context.get_iter(), tuple) else context.get_iter()

View File

@@ -1,3 +0,0 @@
"""
Code Controllers Package
"""

View File

@@ -1,30 +0,0 @@
# Python imports
# Lib imports
# Application imports
from libs.controllers.controller_base import ControllerBase
from libs.event_factory import Code_Event_Types
from ..command_system import CommandSystem
class CommandsController(ControllerBase, list):
def __init__(self):
super(CommandsController, self).__init__()
def _controller_message(self, event: Code_Event_Types.CodeEvent):
if isinstance(event, Code_Event_Types.GetCommandSystemEvent):
event.response = self.get_command_system()
def get_command_system(self):
command_system = CommandSystem()
command_system.emit = self.emit
command_system.emit_to = self.emit_to
self.append(command_system)
return command_system

View File

@@ -1,89 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GLib
from gi.repository import GtkSource
# Application imports
from libs.controllers.controller_base import ControllerBase
from libs.event_factory import Event_Factory, Code_Event_Types
class CompletionController(ControllerBase):
def __init__(self):
super(CompletionController, self).__init__()
self._completers: list[GtkSource.Completion] = []
self._providers: dict[str, GtkSource.CompletionProvider] = {}
def _controller_message(self, event: Code_Event_Types.CodeEvent):
if isinstance(event, Code_Event_Types.RegisterProviderEvent):
self.register_provider(
event.provider_name,
event.provider,
event.language_ids
)
elif isinstance(event, Code_Event_Types.AddedNewFileEvent):
self.provider_process_file_load(event)
elif isinstance(event, Code_Event_Types.RemovedFileEvent):
self.provider_process_file_close(event)
elif isinstance(event, Code_Event_Types.SavedFileEvent):
self.provider_process_file_save(event)
elif isinstance(event, Code_Event_Types.TextChangedEvent):
self.provider_process_file_change(event)
# elif isinstance(event, Code_Event_Types.RequestCompletionEvent):
# self.request_unbound_completion( event.view.get_completion() )
def register_completer(self, completer: GtkSource.Completion):
self._completers.append(completer)
for provider in self._providers.values():
completer.add_provider(provider)
def unregister_completer(self, completer: GtkSource.Completion):
self._completers.remove(completer)
def register_provider(
self,
provider_name: str,
provider: GtkSource.CompletionProvider,
language_ids: list = []
):
self._providers[provider_name] = provider
for completer in self._completers:
completer.add_provider(provider)
def unregister_provider(self, provider_name: str):
provider = self._providers[provider_name]
del self._providers[provider_name]
for completer in self._completers:
completer.remove_provider(provider)
def provider_process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
for provider in self._providers.values():
provider.response_cache.process_file_load(event)
def provider_process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
for provider in self._providers.values():
provider.response_cache.process_file_close(event)
def provider_process_file_save(self, event: Code_Event_Types.SavedFileEvent):
for provider in self._providers.values():
provider.response_cache.process_file_save(event)
def provider_process_file_change(self, event: Code_Event_Types.TextChangedEvent):
for provider in self._providers.values():
provider.response_cache.process_file_change(event)
def request_unbound_completion(self, completer: GtkSource.Completion):
completer.start(
[ *self._providers.values() ],
completer.create_context()
)

View File

@@ -1,149 +0,0 @@
# Python imports
# Lib imports
# Application imports
from libs.controllers.controller_base import ControllerBase
from libs.event_factory import Event_Factory, Code_Event_Types
from ..source_file import SourceFile
from ..source_buffer import SourceBuffer
class FilesController(ControllerBase, list):
def __init__(self):
super(FilesController, self).__init__()
def _controller_message(self, event: Code_Event_Types.CodeEvent):
if isinstance(event, Code_Event_Types.AddNewFileEvent):
self.new_file(event)
elif isinstance(event, Code_Event_Types.SwapFileEvent):
self.swap_file(event)
elif isinstance(event, Code_Event_Types.PopFileEvent):
self.pop_file(event)
elif isinstance(event, Code_Event_Types.RemoveFileEvent):
self.remove_file(event)
elif isinstance(event, Code_Event_Types.GetFileEvent):
self.get_file(event)
elif isinstance(event, Code_Event_Types.GetSwapFileEvent):
self.get_swap_file(event)
def get_file(self, event: Code_Event_Types.GetFileEvent):
if not event.buffer: return
for file in self:
if not event.buffer == file.buffer: continue
event.response = file
return file
def get_swap_file(self, event: Code_Event_Types.GetSwapFileEvent):
if not event.buffer: return
for i, file in enumerate(self):
if not event.buffer == file.buffer: continue
j = self.next_index(i)
next_file = self[j]
swapped_file = self[j] if not j == -1 else None
event.response = [swapped_file, next_file]
return swapped_file, next_file
def new_file(self, event: Code_Event_Types.AddNewFileEvent):
file = SourceFile()
file.emit = self.emit
file.emit_to = self.emit_to
event.response = file
eve = Event_Factory.create_event(
"added_new_file",
view = event.view,
file = file
)
self.message(eve)
self.append(file)
return file
def swap_file(self, event: Code_Event_Types.GetSwapFileEvent):
if not event.buffer: return
for i, file in enumerate(self):
if not event.buffer == file.buffer: continue
j = self.next_index(i)
next_file = self[j]
swapped_file = self[j] if not j == -1 else None
event.response = [swapped_file, next_file]
return swapped_file, next_file
def pop_file(self, event: Code_Event_Types.PopFileEvent):
if not event.buffer: return
for i, file in enumerate(self):
if not event.buffer == file.buffer: continue
j = self.next_index(i)
next_file = self[j] if not j == -1 else None
popped_file = self.pop(i)
event.response = [popped_file, next_file]
eve = Event_Factory.create_event(
"popped_file",
view = view,
file = popped_file,
next_file = next_file
)
self.message(eve)
return popped_file, next_file
def remove_file(self, event: Code_Event_Types.RemoveFileEvent):
if not event.buffer: return
for i, file in enumerate(self):
if not event.buffer == file.buffer: continue
j = self.next_index(i)
next_file = self[j] if not j == -1 else None
event.response = next_file
eve = Event_Factory.create_event(
"removed_file",
view = event.view,
ignore_focus = True,
file = file,
next_file = next_file
)
self.message(eve)
self.remove(file)
file.close()
return next_file
def next_index(self, i):
size = len(self)
if (i == 0) & (size >= 2):
j = i + 1
elif (i == (size - 1)) & (size >= 2):
j = i - 1
elif (size - 1) == 0:
j = -1
else:
j = i + 1
return j

View File

@@ -1,75 +0,0 @@
# Python imports
# Lib imports
import gi
from gi.repository import Gtk
# Application imports
from libs.controllers.controller_base import ControllerBase
from libs.event_factory import Event_Factory, Code_Event_Types
from ..tabs_widget import TabsWidget
from ..tab_widget import TabWidget
from ..source_view import SourceView
class TabsController(ControllerBase):
def __init__(self):
super(TabsController, self).__init__()
self.active_view: SourceView = None
self.tabs_widget: TabsWidget = TabsWidget()
self.tabs_widget.message = self.message
def _controller_message(self, event: Code_Event_Types.CodeEvent):
if isinstance(event, Code_Event_Types.FocusedViewEvent):
self.active_view = event.view
self.tabs_widget.view_changed(
event.view.get_buffer()
)
elif isinstance(event, Code_Event_Types.FilePathSetEvent):
self.update_tab_label(event)
elif isinstance(event, Code_Event_Types.AddedNewFileEvent):
self.add_tab(event)
elif isinstance(event, Code_Event_Types.PoppedFileEvent):
...
elif isinstance(event, Code_Event_Types.RemovedFileEvent):
self.remove_tab(event)
def get_tabs_widget(self):
return self.tabs_widget
def update_tab_label(self, event: Code_Event_Types.FilePathSetEvent):
for page_widget in self.tabs_widget.get_children():
tab = self.tabs_widget.get_tab_label(page_widget)
if not event.file == tab.file: continue
tab.label.set_label(event.file.fname)
break
def add_tab(self, event: Code_Event_Types.AddedNewFileEvent):
box = Gtk.Separator()
tab = TabWidget()
tab.file = event.file
tab.label.set_label(event.file.fname)
self.tabs_widget.append_page(box, tab)
tab.show_all()
def remove_tab(self, event: Code_Event_Types.RemovedFileEvent):
for page_widget in self.tabs_widget.get_children():
tab = self.tabs_widget.get_tab_label(page_widget)
if not event.file == tab.file: continue
tab.clear_signals_and_data()
self.tabs_widget.remove_page(
self.tabs_widget.page_num(page_widget)
)
break

View File

@@ -1,10 +0,0 @@
"""
Code Controllers Package
"""
from .state_manager import SourceViewStateManager
from .signal_mapper import SourceViewSignalMapper
from .source_views_controller import SourceViewsController
# State imports
from .states import *

View File

@@ -1,63 +0,0 @@
# Python imports
# Lib imports
# Application imports
from ...source_view import SourceView
class SourceViewSignalMapper:
def __init__(self):
self.active_view: SourceView = None
def bind_emit(self, emit: callable):
self.emit = emit
def set_state_manager(self, state_manager):
self.state_manager = state_manager
def connect_signals(self, source_view: SourceView):
signal_mappings = self._get_signal_mappings()
for signal, handler in signal_mappings.items():
source_view.connect(signal, handler)
def disconnect_signals(self, source_view: SourceView):
signal_mappings = self._get_signal_mappings()
for signal, handler in signal_mappings.items():
source_view.disconnect_by_func(handler)
def insert_text(self, file, string: str):
return self.state_manager.handle_insert_text(self.active_view, file, string)
def _get_signal_mappings(self):
return {
"focus-in-event": self._focus_in_event,
"move-cursor": self._move_cursor,
"key-press-event": self._key_press_event,
"key-release-event": self._key_release_event,
"button-press-event": self._button_press_event,
"button-release-event": self._button_release_event
}
def _focus_in_event(self, source_view: SourceView, eve):
self.active_view = source_view
return self.state_manager.handle_focus_in_event(source_view, eve, self.emit)
def _move_cursor(self, source_view: SourceView, step, count, extend_selection):
return self.state_manager.handle_move_cursor(
source_view, step, count, extend_selection, self.emit
)
def _button_press_event(self, source_view: SourceView, eve):
return self.state_manager.handle_button_press_event(source_view, eve)
def _button_release_event(self, source_view: SourceView, eve):
return self.state_manager.handle_button_release_event(source_view, eve)
def _key_press_event(self, source_view: SourceView, eve):
return self.state_manager.handle_key_press_event(source_view, eve)
def _key_release_event(self, source_view: SourceView, eve):
return self.state_manager.handle_key_release_event(source_view, eve)

View File

@@ -1,76 +0,0 @@
# Python imports
# Lib imports
# Application imports
from libs.controllers.controller_base import ControllerBase
from libs.event_factory import Event_Factory, Code_Event_Types
from ...source_view import SourceView
from .state_manager import SourceViewStateManager
from .signal_mapper import SourceViewSignalMapper
class SourceViewsController(ControllerBase, list):
def __init__(self):
super(SourceViewsController, self).__init__()
self.state_manager: SourceViewStateManager = SourceViewStateManager()
self.signal_mapper: SourceViewSignalMapper = SourceViewSignalMapper()
self.signal_mapper.bind_emit(self.emit)
self.signal_mapper.set_state_manager(self.state_manager)
def _controller_message(self, event: Code_Event_Types.CodeEvent):
if isinstance(event, Code_Event_Types.RemovedFileEvent):
self._remove_file(event)
if not self.signal_mapper.active_view: return
if isinstance(event, Code_Event_Types.TextChangedEvent):
if not self.signal_mapper.active_view: return
self.signal_mapper.active_view.command.exec("update_info_bar")
elif isinstance(event, Code_Event_Types.SetActiveFileEvent):
self.signal_mapper.active_view.set_buffer(
event.buffer
)
elif isinstance(event, Code_Event_Types.TextInsertedEvent):
self.signal_mapper.insert_text(event.file, event.text)
def _get_command_system(self):
event = Event_Factory.create_event("get_command_system")
self.message_to("commands", event)
command = event.response
del event
return command
def _remove_file(self, event: Code_Event_Types.RemovedFileEvent):
for source_view in self:
if not event.file.buffer == source_view.get_buffer(): continue
if not event.next_file:
source_view.command.exec("new_file")
continue
source_view.set_buffer(event.next_file.buffer)
def create_source_view(self):
source_view: SourceView = SourceView()
source_view.command = self._get_command_system()
source_view.command.set_data(source_view)
self.signal_mapper.connect_signals(source_view)
self.append(source_view)
return source_view
def first_map_load(self):
for source_view in self:
source_view.command.exec("new_file")
source_view = self[0]
source_view.grab_focus()
source_view.command.exec("load_start_files")

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