Skip to content

Commit

Permalink
initial split to app and sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
semicontinuity committed Jun 19, 2022
1 parent 9a01cdb commit 07fdb37
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 131 deletions.
137 changes: 137 additions & 0 deletions fsel/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import json
import os
import sys
from typing import Callable, List, Tuple, Dict

from fsel.sdk import FsListFiles, update_recents, run_dialog, ItemSelectionDialog, full_path, item_model, field_or_else, \
FsModel, ListBoxes, SelectPathDialog


def load_settings():
try:
with open(settings_file()) as json_file:
return json.load(json_file)
except:
return {}


def save_settings(settings):
try:
with open(settings_file(), 'w') as f:
json.dump(settings, f, indent=2, sort_keys=True)
except Exception as e:
pass


def settings_file():
return os.getenv("HOME") + "/.fsel_history"


class FsApp:
def __init__(self, root: str):
self.root = root


class AppSelectRecent(FsApp):

def run(self, recent_items):
items_path = run_dialog(
lambda screen_height, screen_width, cursor_y, cursor_x:
ItemSelectionDialog(screen_height, screen_width, 0, 0, cursor_y, recent_items)
)
if items_path is None:
sys.exit(1)
return full_path(self.root, item_model.item_text(items_path[0]))


class AppSelectInPanes(FsApp):

def run(self, folder: str, file_lister: Callable[[List], List[Tuple[str, int]]], root_history):
fs_model = FsModel(self.root, root_history, file_lister)

rel_path = os.path.relpath(folder, self.root)
initial_path = rel_path.split('/') if rel_path != '.' else []
folder_lists = ListBoxes(fs_model, initial_path)
if folder_lists.is_empty():
sys.exit(2)

items_path = run_dialog(
lambda screen_height, screen_width, cursor_y, cursor_x:
SelectPathDialog(folder_lists, screen_width, screen_height, width=1000, height=0, x=0, y=cursor_y)
)
if items_path is None:
sys.exit(1)
return fs_model.full_path(items_path)


def find_root(folder, settings: Dict) -> Tuple[str, str]:
path = folder if not folder.endswith('/') else folder[:len(folder) - 1]

while True:
if path in settings:
return path, folder
if path == os.getenv('HOME') or path == '' or path.startswith('.'):
return path, folder

i = path.rfind('/')
parent_path = path[:i]

try:
contents = os.listdir(path)
if '.svn' in contents or '.git' in contents:
settings[path] = {}
return path
except: # folder may have been deleted
folder = parent_path

path = parent_path


if __name__ == "__main__":
if sys.stdin.isatty():
path_args = [arg for arg in sys.argv[1:] if not arg.startswith('-')]
target_is_file = '-f' in sys.argv[1:]
target_is_executable = '-x' in sys.argv[1:]
if target_is_file:
field_for_recent = 'recent-executables' if target_is_executable else 'recent-files'
else:
field_for_recent = 'recent-folders'

settings = load_settings()
folder = os.getenv('PWD') if len(path_args) != 1 else path_args[0]
root, folder = find_root(folder, settings)
settings_for_root = field_or_else(settings, root, {})
recent = field_or_else(settings_for_root, field_for_recent, [])

if '-e' in sys.argv[1:]:
if len(recent) == 0:
sys.exit(2)

# makes little sense to cd to the current directory...
if recent[0] == os.path.relpath(os.environ["PWD"], root) and len(recent) > 1: # PWD for logical path
recent[0], recent[1] = recent[1], recent[0]

app = AppSelectRecent(root)
path = app.run([(name, False) for name in recent])
else:
app = AppSelectInPanes(root)
path = app.run(folder, FsListFiles(app.root, target_is_file, target_is_executable),
root_history = field_or_else(settings_for_root, 'history', {}))

if path is None:
sys.exit(1)

rel_path_from_root = os.path.relpath(path, start=app.root)
update_recents(recent, rel_path_from_root)
save_settings(settings)
ret_rel_path = '-r' in sys.argv[1:]
ret_rel_path_from_root = '-R' in sys.argv[1:]

if ret_rel_path:
res = os.path.relpath(path)
elif ret_rel_path_from_root:
res = rel_path_from_root
else:
res = path

print(res)
127 changes: 1 addition & 126 deletions fsel/fsel.py → fsel/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from picotui.defs import *
import os
import sys
import json

screen = Screen()

Expand Down Expand Up @@ -677,7 +676,7 @@ def items_path(self):
return [self.focus_w.items[self.focus_w.cur_line]]


def run(dialog_supplier):
def run_dialog(dialog_supplier):
v = None
try:
Screen.init_tty()
Expand Down Expand Up @@ -708,26 +707,6 @@ def full_path(root, rel_path):
return root + rel_path


def load_settings():
try:
with open(settings_file()) as json_file:
return json.load(json_file)
except:
return {}


def save_settings(settings):
try:
with open(settings_file(), 'w') as f:
json.dump(settings, f, indent=2, sort_keys=True)
except Exception as e:
pass


def settings_file():
return os.getenv("HOME") + "/.fsel_history"


def field_or_else(d: Dict, name, default):
result = d.get(name)
if result is None:
Expand All @@ -743,74 +722,6 @@ def update_recents(recent, rel_path_from_root):
del recent[RECENT_COUNT:]


class App:
def __init__(self, folder: str, field_for_recent: str):
self.folder = folder
self.settings = load_settings()
vcs_root_detected, self.root = self.find_root()
if vcs_root_detected:
self.settings[self.root] = {}
self.settings_for_root = field_or_else(self.settings, self.root, {})
self.recent = field_or_else(self.settings_for_root, field_for_recent, [])

def find_root(self):
path = self.folder if not self.folder.endswith('/') else self.folder[:len(self.folder) - 1]

while True:
if path in self.settings:
return False, str(path)
if path == os.getenv('HOME') or path == '' or path.startswith('.'):
return False, path


i = path.rfind('/')
parent_path = path[:i]

try:
contents = os.listdir(path)
if '.svn' in contents or '.git' in contents:
return True, path
except: # folder may have been deleted
self.folder = parent_path

path = parent_path

def select_in_panes(self, file_lister: Callable[[List], List[Tuple[str, int]]]):
root_history = field_or_else(self.settings_for_root, 'history', {})
fs_model = FsModel(self.root, root_history, file_lister)

rel_path = os.path.relpath(self.folder, self.root)
initial_path = rel_path.split('/') if rel_path != '.' else []
folder_lists = ListBoxes(fs_model, initial_path)
if folder_lists.is_empty():
sys.exit(2)

items_path = run(
lambda screen_height, screen_width, cursor_y, cursor_x:
SelectPathDialog(folder_lists, screen_width, screen_height, width=1000, height=0, x=0, y=cursor_y)
)
if items_path is None:
sys.exit(1)
return fs_model.full_path(items_path)

def select_recent(self):
if len(self.recent) == 0:
sys.exit(2)

# makes little sense to cd to the current directory...
if self.recent[0] == os.path.relpath(os.environ["PWD"], self.root) and len(self.recent) > 1: # PWD for logical path
self.recent[0], self.recent[1] = self.recent[1], self.recent[0]

recent_items = [(name, False) for name in self.recent]
items_path = run(
lambda screen_height, screen_width, cursor_y, cursor_x:
ItemSelectionDialog(screen_height, screen_width, 0, 0, cursor_y, recent_items)
)
if items_path is None:
sys.exit(1)
return full_path(self.root, item_model.item_text(items_path[0]))


class Colorizer:
C_IDX_BG = 0
C_IDX_REG_FG = 1
Expand Down Expand Up @@ -878,39 +789,3 @@ def palette(attrs: int, focused_list: bool, focused_entry: bool) -> List[int]:

colors = Colorizer()
item_model = ItemModel()


if __name__ == "__main__":
if sys.stdin.isatty():
path_args = [arg for arg in sys.argv[1:] if not arg.startswith('-')]
target_is_file = '-f' in sys.argv[1:]
target_is_executable = '-x' in sys.argv[1:]
if target_is_file:
field_for_recent = 'recent-executables' if target_is_executable else 'recent-files'
else:
field_for_recent = 'recent-folders'

app = App(os.getenv('PWD') if len(path_args) != 1 else path_args[0], field_for_recent)

if '-e' in sys.argv[1:]:
path = app.select_recent()
else:
path = app.select_in_panes(FsListFiles(app.root, target_is_file, target_is_executable))

if path is None:
sys.exit(1)

rel_path_from_root = os.path.relpath(path, start=app.root)
update_recents(app.recent, rel_path_from_root)
save_settings(app.settings)
ret_rel_path = '-r' in sys.argv[1:]
ret_rel_path_from_root = '-R' in sys.argv[1:]

if ret_rel_path:
res = os.path.relpath(path)
elif ret_rel_path_from_root:
res = rel_path_from_root
else:
res = path

print(res)
10 changes: 5 additions & 5 deletions key_bindings.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@

__fsel_cat__() {
local file
file=$(python3 -m fsel.fsel -r -f "$@") && printf "${PAGER:-less} $file"
file=$(python3 -m fsel.app -r -f "$@") && printf "${PAGER:-less} $file"
}

__fsel_edit__() {
local file
file=$(python3 -m fsel.fsel -r -f "$@") && printf "${EDITOR:-nano} $file"
file=$(python3 -m fsel.app -r -f "$@") && printf "${EDITOR:-nano} $file"
}

__fsel_cd__() {
local dir
dir=$(python3 -m fsel.fsel "$@") && printf 'cd %q' "$dir"
dir=$(python3 -m fsel.app "$@") && printf 'cd %q' "$dir"
}

__fsel_run__() {
local file
file=$(python3 -m fsel.fsel -f -x "$@") && printf '%q' "$file"
file=$(python3 -m fsel.app -f -x "$@") && printf '%q' "$file"
}

__fsel_widget__() {
local selected=$(python3 -m fsel.fsel "$@")
local selected=$(python3 -m fsel.app "$@")
READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
READLINE_POINT=$(( READLINE_POINT + ${#selected} ))
}
Expand Down

0 comments on commit 07fdb37

Please sign in to comment.