Skip to content

Commit

Permalink
Merge pull request #63 from RedAtman/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
RedAtman authored Aug 3, 2024
2 parents 542b767 + f5e91e6 commit bd485d9
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 95 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,25 @@ The "Packages" directory is located at:
* OS X:

```bash
~/Library/Application Support/Sublime Text/Packages
~/Library/Application Support/Sublime Text/Packages/
# or
~/Library/Application Support/Sublime Text/Installed Packages/
```

* Linux:

```bash
~/.config/sublime-text/Packages/
# or
~/.config/sublime-text/Installed Packages/
```

* Windows:

```bash
%APPDATA%/Sublime Text/Packages/
# or
%APPDATA%/Sublime Text/Installed Packages/
```

## Configuration
Expand Down Expand Up @@ -107,7 +113,7 @@ After setting them it will download the notes.
Hit the shortcut again after the download is done (check the message bar) and it will **show a list of the notes**:
![Alt Notes](assets/images/note_list.png "Note List")

It will download notes every time sublime text is launched and every now and then if the _sync_every_ configuration is enabled (has a positive value), so take a look at the bar to check the status.
It will download notes every time sublime text is launched and every now and then if the _sync_interval_ configuration is enabled (has a positive value), so take a look at the bar to check the status.

If a note gets updated from somewhere else
![Alt External Update](http://i.imgur.com/p9pAY6z.png "External Update")
Expand Down
4 changes: 2 additions & 2 deletions Simplenote.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
// --------------------------------
// Sync when sublime text starts:
,"autostart": true
// Sync automatically (in seconds)
,"sync_every": 30
// Sync automatically interval (in seconds)
,"sync_interval": 30
// Number of notes synchronized each time
,"sync_note_number": 1000
// Conflict resolution (If a file was edited on another client and also here, on sync..)
Expand Down
6 changes: 3 additions & 3 deletions _config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// Sync when sublime text starts:
,"autostart": true
// Sync automatically (in seconds)
,"sync_every": 30
,"sync_interval": 30
// Number of notes synchronized each time
,"sync_note_number": 1000
// Conflict resolution (If a file was edited on another client and also here, on sync..)
Expand Down Expand Up @@ -133,8 +133,8 @@ def __init_subclass__(cls, **kwargs):
SIMPLENOTE_NOTES_DIR = os.path.join(SIMPLENOTE_CACHE_DIR, "notes")
os.makedirs(SIMPLENOTE_NOTES_DIR, exist_ok=True)

# SIMPLENOTE_STARTED: bool = False
# SIMPLENOTE_RELOAD_CALLS: int = -1
SIMPLENOTE_STARTED_KEY: str = "simplenote_started"
SIMPLENOTE_SYNC_TIMES_KEY: str = "simplenote_sync_times"


class Development(_BaseConfig):
Expand Down
77 changes: 26 additions & 51 deletions commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import sublime_plugin

from ._config import CONFIG
from .lib.core import start
from .lib.gui import clear_orphaned_filepaths, close_view, on_note_changed, open_view, show_message
from .lib.core import GlobalStorage, sync_once
from .lib.gui import close_view, on_note_changed, open_view, show_message, show_quick_panel
from .lib.models import Note
from .lib.operations import NoteCreator, NoteDeleter, NotesIndicator, NoteUpdater, OperationManager

Expand All @@ -25,7 +25,7 @@
logger = logging.getLogger()


SIMPLENOTE_STARTED = False
global_storage = GlobalStorage()


class SimplenoteViewCommand(sublime_plugin.EventListener):
Expand All @@ -34,7 +34,6 @@ class SimplenoteViewCommand(sublime_plugin.EventListener):

@cached_property
def autosave_debounce_time(self) -> int:
logger.warning(("CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH", CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH))
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
_autosave_debounce_time = settings.get("autosave_debounce_time", 1)
if not isinstance(_autosave_debounce_time, int):
Expand Down Expand Up @@ -123,53 +122,11 @@ def on_post_save(self, view: sublime.View):

class SimplenoteListCommand(sublime_plugin.ApplicationCommand):

def on_select(self, selected_index: int):
if selected_index == -1:
return
note_id = self.list__modificationDate[selected_index]
selected_note = Note.tree.find(note_id)
if not isinstance(selected_note, Note):
show_message("Note not found: note id(%s), Please restart simplenote or sublime text." % note_id)
return
filepath = selected_note.open()
selected_note.flush()
view = open_view(filepath)

def run(self):
global SIMPLENOTE_STARTED
if not SIMPLENOTE_STARTED:
if not start():
return

if Note.tree.count <= 0:
show_message(
"No notes found. Please wait for the synchronization to complete, or press [super+shift+s, super+shift+c] to create a note."
)
self.list__modificationDate: List[float] = []
self.list__title: List[str] = []
list__filename: List[str] = []
for note in Note.tree.iter(reverse=True):
if not isinstance(note, Note):
raise Exception("note is not a Note: %s" % type(note))
if note.d.deleted == True:
continue
self.list__modificationDate.append(note.d.modificationDate)
self.list__title.append(note.title)
list__filename.append(note.filename)

# TODO: Maybe doesn't need to run every time
clear_orphaned_filepaths(list__filename)

def show_panel():
sublime.active_window().show_quick_panel(
self.list__title,
self.on_select,
flags=sublime.KEEP_OPEN_ON_FOCUS_LOST,
# on_highlight=self.on_select,
placeholder="Select Note press key 'enter' to open",
)

sublime.set_timeout(show_panel, 50)
if Note.tree.count:
show_quick_panel()
if not global_storage.get(CONFIG.SIMPLENOTE_STARTED_KEY):
sync_once()


class SimplenoteSyncCommand(sublime_plugin.ApplicationCommand):
Expand All @@ -179,14 +136,32 @@ def merge_note(self, updated_notes: List[Note]):
if note.need_flush:
on_note_changed(note)

def callback(self, updated_notes: List[Note]):
self.merge_note(updated_notes)

sync_times = global_storage.get(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY)
if not isinstance(sync_times, int):
raise TypeError(
"Value of %s must be type %s, got %s" % (CONFIG.SIMPLENOTE_SYNC_TIMES_KEY, int, type(sync_times))
)
first_sync = sync_times == 0
if first_sync:
show_quick_panel(first_sync)
global_storage.optimistic_update(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY, sync_times + 1)
global_storage.optimistic_update(CONFIG.SIMPLENOTE_STARTED_KEY, False)

def run(self):
if global_storage.get(CONFIG.SIMPLENOTE_STARTED_KEY):
return
global_storage.optimistic_update(CONFIG.SIMPLENOTE_STARTED_KEY, True)

settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
sync_note_number = settings.get("sync_note_number", 1000)
if not isinstance(sync_note_number, int):
show_message("`sync_note_number` must be an integer. Please check settings file.")
return
note_indicator = NotesIndicator(sync_note_number=sync_note_number)
note_indicator.set_callback(self.merge_note)
note_indicator.set_callback(self.callback)
OperationManager().add_operation(note_indicator)


Expand Down
4 changes: 4 additions & 0 deletions dev_deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# local development deploy
zip -r Simplenote.sublime-package . -x ".env*" ".git/*" ".github/*" ".gitignore" ".idea/*" ".vscode/*" ".pytest_cache/*" "pyproject.toml" "package-lock.json" "package.json" "node_modules/*" ".env.*" ".DS_Store" "assets/*" "*__pycache__/*" "tmp/*" "tests/*" "logs/*" "sublime_api.py" "dev_deploy.sh" "package-metadata.json"

mv Simplenote.sublime-package $HOME/Library/Application\ Support/Sublime\ Text/Installed\ Packages/Simplenote.sublime-package
61 changes: 40 additions & 21 deletions lib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,63 @@
import sublime

from .._config import CONFIG
from ..utils.lock.thread import OptimisticLockingDict
from ..utils.patterns.singleton.base import Singleton
from .gui import edit_settings, remove_status, show_message
from .operations import OperationManager


logger = logging.getLogger()
SIMPLENOTE_STARTED = False


def sync():
manager = OperationManager()
class GlobalStorage(Singleton, OptimisticLockingDict):
__mapper_key_type = {CONFIG.SIMPLENOTE_SYNC_TIMES_KEY: int, CONFIG.SIMPLENOTE_STARTED_KEY: bool}

def optimistic_update(self, key, new_value):
_type = self.__mapper_key_type.get(key)
if not _type is None:
if not isinstance(new_value, _type):
raise TypeError("Value of %s must be type %s, got %s" % (key, _type, type(new_value)))

if key == CONFIG.SIMPLENOTE_SYNC_TIMES_KEY:
import time

logger.warning((time.time(), key, new_value))
return super().optimistic_update(key, new_value)


manager = OperationManager()
global_storage = GlobalStorage()


def sync_once():
if not manager.running:
sublime.run_command("simplenote_sync")
else:
logger.debug("Sync omitted")

settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
sync_every = settings.get("sync_every", 0)
logger.debug(("Simplenote sync_every", sync_every))
if not isinstance(sync_every, int):
show_message("`sync_every` must be an integer. Please check settings file.")
return

if sync_every > 0:
sublime.set_timeout(sync, sync_every * 1000)
def sync(sync_interval: int = 30):
sync_once()
sublime.set_timeout(sync, sync_interval * 1000)


def start():
global SIMPLENOTE_STARTED
settings = sublime.load_settings("Simplenote.sublime-settings")
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
username = settings.get("username")
password = settings.get("password")

if username and password:
sync()
SIMPLENOTE_STARTED = True
else:
edit_settings()
show_message("Simplenote: Please configure username/password, Please check settings file.")
sublime.set_timeout(remove_status, 2000)
SIMPLENOTE_STARTED = False
return SIMPLENOTE_STARTED
if global_storage.get(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY) != 0:
return
sync_interval = settings.get("sync_interval", 30)
if not isinstance(sync_interval, int):
show_message("`sync_interval` must be an integer. Please check settings file.")
return
if sync_interval <= 0:
return
sync(sync_interval)
return
show_message("Simplenote: Please configure username/password in settings file.")
edit_settings()
sublime.set_timeout(remove_status, 2000)
50 changes: 50 additions & 0 deletions lib/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"close_view",
"clear_orphaned_filepaths",
"on_note_changed",
"show_quick_panel",
]


Expand Down Expand Up @@ -121,3 +122,52 @@ def on_note_changed(note: Note):
old_window.focus_view(old_active_view)

sublime.set_timeout(partial(new_view.run_command, "revert"), 0)


def on_select(list__modificationDate: List[float], selected_index: int):
if selected_index == -1:
return
note_id = list__modificationDate[selected_index]
selected_note = Note.tree.find(note_id)
if not isinstance(selected_note, Note):
show_message("Note not found: note id(%s), Please restart simplenote or sublime text." % note_id)
return
filepath = selected_note.open()
selected_note.flush()
view = open_view(filepath)


def show_quick_panel(first_sync: bool = False):
if Note.tree.count <= 0:
show_message(
"No notes found. Please wait for the synchronization to complete, or press [super+shift+s, super+shift+c] to create a note."
)
list__modificationDate: List[float] = []
list__title: List[str] = []
list__filename: List[str] = []
for note in Note.tree.iter(reverse=True):
if not isinstance(note, Note):
raise Exception("note is not a Note: %s" % type(note))
if note.d.deleted == True:
continue
list__modificationDate.append(note.d.modificationDate)
list__title.append(note.title)
list__filename.append(note.filename)

# TODO: Maybe doesn't need to run every time
clear_orphaned_filepaths(list__filename)

placeholder = "Select Note press key 'enter' to open"
if first_sync:
placeholder = "Sync complete. Press [super+shift+s] [super+shift+l] to display the note list again."

def show_panel():
sublime.active_window().show_quick_panel(
list__title,
partial(on_select, list__modificationDate),
flags=sublime.MONOSPACE_FONT,
# on_highlight=self.on_select,
placeholder=placeholder,
)

sublime.set_timeout(show_panel, 500)
27 changes: 15 additions & 12 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,46 @@
import sublime

from ._config import CONFIG
from .lib.core import start
from .lib.core import GlobalStorage, start
from .lib.gui import show_message
from .lib.models import Note


logger = logging.getLogger()

SIMPLENOTE_RELOAD_CALLS = -1

global_storage = GlobalStorage()
global_storage.optimistic_update(CONFIG.SIMPLENOTE_STARTED_KEY, False)
global_storage.optimistic_update(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY, 0)


def reload_if_needed():
# global SIMPLENOTE_RELOAD_CALLS

# # Sublime calls this twice for some reason :(
# SIMPLENOTE_RELOAD_CALLS += 1
# logger.warning((SIMPLENOTE_RELOAD_CALLS, SIMPLENOTE_RELOAD_CALLS % 2))
# if SIMPLENOTE_RELOAD_CALLS % 2 != 0:
# logger.debug("Simplenote Reload call %s" % SIMPLENOTE_RELOAD_CALLS)
# return

logger.warning(("CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH", CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH))
settings = sublime.load_settings("Simplenote.sublime-settings")
autostart = settings.get("autostart")
if bool(autostart):
autostart = True
logger.debug(("Simplenote Reloading", autostart))
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
autostart = settings.get("autostart", True)
if not isinstance(autostart, bool):
show_message("`autostart` must be a boolean. Please check settings file.")
return
if autostart:
sublime.set_timeout(start, 2000)
logger.debug("Auto Starting")
start()


def plugin_loaded():
# load_notes()
logger.debug(("Loaded notes number: ", Note.tree.count))

logger.warning(("CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH", CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH))
settings = sublime.load_settings("Simplenote.sublime-settings")
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
# logger.debug(("SETTINGS.__dict__: ", SETTINGS.__dict__))
# logger.debug(("SETTINGS.username: ", SETTINGS.get("username")))

settings.clear_on_change("username")
settings.clear_on_change("password")
settings.add_on_change("username", reload_if_needed)
Expand Down
Loading

0 comments on commit bd485d9

Please sign in to comment.