diff --git a/BOARD.txt b/BOARD.txt new file mode 100644 index 0000000..95515f7 --- /dev/null +++ b/BOARD.txt @@ -0,0 +1,25 @@ +TODO DONE +-------------------------------------------------------------------------------- + browsing + links + redirections + web links + history + simple caching + simple text files + encodings + bookmarks + view/edit sources +non shit command-line +home page +downloads +media files +identity management +configuration +-------------------------------------------------------------------------------- +BACKLOG +margins / centering +pre blocks folding +buffers (tabs) +handle soft-hyphens on wrapping +bug: combining chars reduce lengths diff --git a/README.md b/README.md index 10ce335..7db6c3a 100644 --- a/README.md +++ b/README.md @@ -27,16 +27,16 @@ Features ### What works -- Basic browsing: scrolling, follow links, redirections, Web links. +Common basic browsing features work: go to URL, scrolling, follow links, +redirections, page encoding. -### What is planned +Bebop also provide these neat features: -- Handle more content types. -- Great config options. -- Identity management with temporary and managed certificates. -- Buffers (or tabs if you prefer). -- Home page. -- Bookmarks. +- History +- Caching +- Bookmarks: it's just a text file with bindings. + +Check out [this board](BOARD.txt) for what's done and coming next. ### What is not planned for now diff --git a/bebop/browser/browser.py b/bebop/browser/browser.py index 15a127e..5a522b3 100644 --- a/bebop/browser/browser.py +++ b/bebop/browser/browser.py @@ -4,9 +4,13 @@ import curses import curses.ascii import curses.textpad import os +import subprocess +import tempfile from math import inf -from bebop.bookmarks import get_bookmarks_document, save_bookmark +from bebop.bookmarks import ( + get_bookmarks_path, get_bookmarks_document, save_bookmark +) from bebop.colors import ColorPair, init_colors from bebop.command_line import CommandLine from bebop.history import History @@ -131,6 +135,8 @@ class Browser: self.open_bookmarks() elif char == ord("B"): self.add_bookmark() + elif char == ord("e"): + self.edit_page() elif curses.ascii.isdigit(char): self.handle_digit_input(char) elif char == curses.KEY_MOUSE: @@ -421,3 +427,42 @@ class Browser: if title: save_bookmark(self.current_url, title) self.reset_status() + + def open_external_program(self, command): + """Pauses the curses modes to open an external program.""" + curses.nocbreak() + curses.echo() + subprocess.run(command) + curses.noecho() + curses.cbreak() + self.refresh_windows() + + def edit_page(self): + """Open a text editor to edit the page source. + + For external pages, the source is written in a temporary file, opened in + its editor of choice and so it's up to the user to save it where she + needs it, if needed. Internal pages, e.g. the bookmarks page, are loaded + directly from their location on disk. + """ + command = ["vi"] + delete_source_after = False + + special_pages = { + "bebop://bookmarks": str(get_bookmarks_path()) + } + if self.current_url in special_pages: + source_filename = special_pages[self.current_url] + else: + if not self.page_pad.current_page: + return + source = self.page_pad.current_page.source + with tempfile.NamedTemporaryFile("wt", delete=False) as source_file: + source_file.write(source) + source_filename = source_file.name + delete_source_after = True + + command.append(source_filename) + self.open_external_program(command) + if delete_source_after: + os.unlink(source_filename) diff --git a/bebop/page.py b/bebop/page.py index d490373..48a397f 100644 --- a/bebop/page.py +++ b/bebop/page.py @@ -17,6 +17,7 @@ class Page: lookup and disambiguation. - title: optional page title. """ + source: str metalines: list = field(default_factory=list) links: Links = field(default_factory=Links) title: str = "" @@ -26,4 +27,4 @@ class Page: """Produce a Page from a Gemtext file or string.""" elements, links, title = parse_gemtext(gemtext) metalines = generate_metalines(elements, 80) - return Page(metalines, links, title) + return Page(gemtext, metalines, links, title)