added rudementary page turning. Updated description. Previous pages unavailable, next goal in mind.
This commit is contained in:
parent
bdb41ccbd2
commit
7e29e89a78
1
Dracula_bookmark
Normal file
1
Dracula_bookmark
Normal file
@ -0,0 +1 @@
|
|||||||
|
10
|
76
README.md
76
README.md
@ -1,8 +1,76 @@
|
|||||||
# Bibliofile
|
# Bibliofile
|
||||||
### A TUI-based ebook reader that hopefully doesn't suck!
|
### A TUI-based ebook reader inspired by NCurses-era programs!
|
||||||
|
|
||||||
A long long time ago, I was in college. I frequently bought the ebook versions of my textbooks, but to my dismay...most ebook readers sucked. The user interface was complicated, dark mode was unavailable for most readers until I neared graduation, dark mode usually looked terrible even if it was available, etc. I hope to change that. What better dark mode that running it on the TUI? What better way to make a simple UI than to design one myself that *I* like?
|
Bibliofile is a simplified epub reader with automatic bookmarking!
|
||||||
|
|
||||||
This is very much a personal project. Rust isn't exactly used for big companies besides Mozilla just yet, and progress is slow-going due to my personal and work commitments. Still, when it is done, I will attempt to release it on several popular repositories such as Flatpack so that others can use it.
|
Instructions:
|
||||||
|
|
||||||
Feel free to check up on progress on my blog, www.whoisthisjoker.com. I post there periodically to talk about what direction I want the project to go.
|
- installation
|
||||||
|
- use
|
||||||
|
- feedback
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## installation
|
||||||
|
|
||||||
|
At the moment, Bibliofile is a work-in-progress, so it is not part of any package manager, and no binaries are available at the moment. However to run this while in alpha, you can follow the Instructions down below.
|
||||||
|
|
||||||
|
### 1
|
||||||
|
|
||||||
|
Install Rust. The full Instructions on how to do this are here: https://www.rust-lang.org/tools/install
|
||||||
|
|
||||||
|
The easiest way of installing Rust is with the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### 2
|
||||||
|
|
||||||
|
Clone the repository to the directory of your choice
|
||||||
|
|
||||||
|
```git
|
||||||
|
git clone https://git.whoisthisjoker.com/daniel/bibliofile
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3
|
||||||
|
|
||||||
|
cd into the directory *bibliofile*. Compile the program. This is best done with cargo.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
cargo build
|
||||||
|
```
|
||||||
|
|
||||||
|
The executable will be in target/debug.
|
||||||
|
|
||||||
|
Please keep in mind, at this point in development compilation success is not guaranteed.
|
||||||
|
|
||||||
|
## running
|
||||||
|
|
||||||
|
Running the program is simple, as at this point there is not many features. Simply run
|
||||||
|
|
||||||
|
```bibliofile [booknamehere.epub]```
|
||||||
|
|
||||||
|
There will be buttons at the bottom of each page that allow you to turn pages. Simply press "last" or "next" to turn the page.
|
||||||
|
|
||||||
|
|
||||||
|
## disclamers
|
||||||
|
|
||||||
|
This program is in alpha, and I am trying to get base functionality working. It will be lacking features, and can currently only read epub files. Mobi and PDF are not supported.
|
||||||
|
|
||||||
|
## license
|
||||||
|
|
||||||
|
Bibliofile: A TUI epub reader inspired by DOS-era programs
|
||||||
|
|
||||||
|
Copyright (C) 2023 Daniel Redd joes
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
131
src/main.rs
131
src/main.rs
@ -4,7 +4,7 @@ Language: Rustc 1.71.0
|
|||||||
ide: CLion
|
ide: CLion
|
||||||
Operating system: POP_OS
|
Operating system: POP_OS
|
||||||
Purpose: TUI-based ereader and library manager for Linux terminal environments.
|
Purpose: TUI-based ereader and library manager for Linux terminal environments.
|
||||||
Last edited: 11/14/23
|
Last edited: 11/18/23
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mod html_module;
|
mod html_module;
|
||||||
@ -15,7 +15,9 @@ use epub::doc::EpubDoc; //library for navigating epubs
|
|||||||
use std::*;
|
use std::*;
|
||||||
use std::i32;
|
use std::i32;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This function will determine if Bibliofile has been opened before. If it has not, it will create a library folder under /opt/bibliofile.
|
This function will determine if Bibliofile has been opened before. If it has not, it will create a library folder under /opt/bibliofile.
|
||||||
@ -24,6 +26,9 @@ Function: library_Exists
|
|||||||
param: none
|
param: none
|
||||||
Return Type: void
|
Return Type: void
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//temporarily commented out until I implement the library functionality
|
||||||
|
/*
|
||||||
fn library_exists(){
|
fn library_exists(){
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +41,10 @@ fn library_exists(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
initial function. Reads the ebook passed by argument, and checks if library directory exists in Linux.
|
initial function. Reads the ebook passed by argument, and checks if library directory exists in Linux.
|
||||||
@ -68,28 +77,23 @@ Return type: none
|
|||||||
*/
|
*/
|
||||||
fn screen_func(epub_file: &str){
|
fn screen_func(epub_file: &str){
|
||||||
|
|
||||||
let mut page_num = 1;
|
|
||||||
let mut siv = cursive::default();
|
let mut siv = cursive::default();
|
||||||
let textinfo = get_init_text(epub_file, &page_num, "next");
|
|
||||||
let text = textinfo.0;
|
|
||||||
let title = textinfo.1;
|
|
||||||
page_num = textinfo.2;
|
|
||||||
|
|
||||||
|
|
||||||
// Creates the cursive root - required for every application.
|
|
||||||
let mut siv = cursive::default();
|
|
||||||
siv.add_global_callback('q', |s| s.quit());
|
siv.add_global_callback('q', |s| s.quit());
|
||||||
siv.add_global_callback('d', move |s| { get_text(s); });
|
let text = "Welcome to Bibliofile! Press begin to read your book.";
|
||||||
|
|
||||||
// Creates a dialog with a single "Quit" button
|
// Creates a dialog with a single "Quit" button
|
||||||
siv.add_layer(Dialog::around(TextView::new(text))
|
siv.add_layer(Dialog::around(TextView::new(text))
|
||||||
.title(title + " page: " + &page_num.to_string())
|
.title("Bibliofile")
|
||||||
.scrollable()
|
.button("begin", |s| {get_text(s);}),
|
||||||
.scroll_x(true),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Starts the event loop.
|
// Starts the event loop.
|
||||||
siv.run();
|
siv.run();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -102,73 +106,66 @@ params: Cursive session
|
|||||||
Returns type: void
|
Returns type: void
|
||||||
*/
|
*/
|
||||||
fn get_text(s: &mut Cursive) {
|
fn get_text(s: &mut Cursive) {
|
||||||
|
|
||||||
|
//removes old layer, builds new one
|
||||||
s.pop_layer();
|
s.pop_layer();
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let filename = &args[1];
|
let filename = &args[1];
|
||||||
let doc = EpubDoc::new(filename);
|
let doc = EpubDoc::new(filename);
|
||||||
let mut doc = doc.unwrap();
|
let mut doc = doc.unwrap();
|
||||||
let page_num = 1;
|
|
||||||
let mut usize_num = page_num as usize;
|
//gets page number/bookmark
|
||||||
usize_num = usize_num + 1;
|
|
||||||
|
|
||||||
let title = doc.mdata("title");
|
let title = doc.mdata("title");
|
||||||
s.add_global_callback('d', move |s| { get_text(s); });
|
let bookmark_file_name = title.clone().unwrap() + "_bookmark";
|
||||||
doc.set_current_page(usize_num);
|
|
||||||
let content = doc.get_current_str();
|
|
||||||
let str_content = content.unwrap();
|
|
||||||
let text = html_module::main(str_content.0);
|
|
||||||
|
|
||||||
//refreshed screen layout
|
|
||||||
s.add_layer(Dialog::around(TextView::new(text))
|
//if bookmark for file exists, continue to open. If not, create the file and try again.
|
||||||
.title(title.unwrap() + " page: " + &usize_num.to_string())
|
if Path::exists(bookmark_file_name.as_ref()){
|
||||||
.scrollable()
|
|
||||||
.scroll_x(true),
|
let bookmark = fs::read_to_string(bookmark_file_name.clone()).expect("no file found! You kidding me?");
|
||||||
|
|
||||||
|
let mut page_num: usize = bookmark
|
||||||
|
.trim()
|
||||||
|
.parse()
|
||||||
|
.expect("not a number");// converts from string to usize
|
||||||
|
|
||||||
|
|
||||||
|
let usize_num = page_num as usize; //set_current_page must be usize, not int. This line converts.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
doc.set_current_page(usize_num);
|
||||||
|
let content = doc.get_current_str();
|
||||||
|
let str_content = content.unwrap();
|
||||||
|
let text = html_module::main(str_content.0);
|
||||||
|
page_num = page_num + 1;
|
||||||
|
|
||||||
|
//let mut bookmark_write = File::open(bookmark_file_name).expect("could not write to file.");
|
||||||
|
let page_string = page_num.to_string();
|
||||||
|
//bookmark_write.write_all(page_string.as_bytes()).expect("oops, couldn't write.");
|
||||||
|
|
||||||
|
fs::write(bookmark_file_name, page_string.as_bytes()).expect("Unable to write file");
|
||||||
|
|
||||||
|
//refreshed screen layout
|
||||||
|
s.add_layer(Dialog::around(TextView::new(text))
|
||||||
|
.title(title.unwrap() + " page: " + &usize_num.to_string())
|
||||||
|
.button("last", |s| {get_text(s);})
|
||||||
|
.button("quit", |s| s.quit())
|
||||||
|
.button("next", |s| {get_text(s);})
|
||||||
|
.scrollable()
|
||||||
|
.scroll_x(true),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
fs::write(bookmark_file_name, "1").expect("Unable to write file");
|
||||||
|
get_text(s);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Function called
|
|
||||||
*/
|
|
||||||
fn get_init_text(epub_file: &str, mut page_num: &i32, direction: &str) -> (String, String, i32){
|
|
||||||
let doc = EpubDoc::new(&epub_file);
|
|
||||||
assert!(doc.is_ok());
|
|
||||||
let mut doc = doc.unwrap();
|
|
||||||
let mut usize_num = *page_num as usize;
|
|
||||||
|
|
||||||
return if direction == "next" {
|
|
||||||
usize_num = usize_num + 1;
|
|
||||||
let title = doc.mdata("title");
|
|
||||||
|
|
||||||
doc.set_current_page(usize_num);
|
|
||||||
let content = doc.get_current_str();
|
|
||||||
let str_content = content.unwrap();
|
|
||||||
let text = html_module::main(str_content.0);
|
|
||||||
|
|
||||||
(text, title.unwrap(), usize_num as i32)
|
|
||||||
} else if direction == "last" {
|
|
||||||
usize_num = usize_num - 1;
|
|
||||||
let title = doc.mdata("title");
|
|
||||||
|
|
||||||
doc.set_current_page(usize_num);
|
|
||||||
let content = doc.get_current_str();
|
|
||||||
let str_content = content.unwrap();
|
|
||||||
let text = html_module::main(str_content.0);
|
|
||||||
|
|
||||||
(text, title.unwrap(), usize_num as i32)
|
|
||||||
} else {
|
|
||||||
let title = doc.mdata("title");
|
|
||||||
|
|
||||||
doc.set_current_page(usize_num);
|
|
||||||
let content = doc.get_current_str();
|
|
||||||
let str_content = content.unwrap();
|
|
||||||
let text = html_module::main(str_content.0);
|
|
||||||
|
|
||||||
(text, title.unwrap(), usize_num as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user