Skip to content

Commit

Permalink
目录结构整理
Browse files Browse the repository at this point in the history
  • Loading branch information
shepherdma committed Nov 29, 2023
1 parent eddebac commit 7ca4398
Show file tree
Hide file tree
Showing 8 changed files with 319 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Compiled files
/target/

# These directories store cache and intermediate files
**/*.rs.bk

# IDE - IntelliJ
.idea/

# Dependency directory
/.cargo/

# Rustup directory
/.rustup/

# Environment variable file
.env

# Ignore .DS_Store files (Mac OS)
.DS_Store
58 changes: 58 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "hecto"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
termion = "1"
20 changes: 20 additions & 0 deletions src/document.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::Row;

#[derive(Default)]
pub struct Document {
rows: Vec<Row>,
}

impl Document {
pub fn open() -> Self{
let mut rows = Vec::new();
rows.push(Row::from("Hello, World!"));
Self { rows }
}
pub fn row(&self, index: usize) -> Option<&Row> {
self.rows.get(index)
}
pub fn is_empty(&self) -> bool {
self.rows.is_empty()
}
}
112 changes: 112 additions & 0 deletions src/editor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use crate::Row;
use crate::Document;
use crate::Terminal;
use termion::event::Key;

const VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Default)]
pub struct Position {
pub x: usize,
pub y: usize,
}
pub struct Editor {
should_quit: bool,
terminal: Terminal,
cursor_position: Position,
document: Document,
}
fn die(e: &std::io::Error) {
Terminal::clear_screen();
panic!("{}", e)
}

impl Editor {
pub fn run(&mut self) {
loop {
if let Err(error) = self.refresh_screen() {
die(&error);
}
if self.should_quit {
println!("Goodbye.\r");
break;
}
if let Err(error) = self.process_keypress() {
die(&error);
}
}
}
pub fn default() -> Self{
Self{
should_quit: false,
terminal: Terminal::default().expect("Failed to initialize terminal"),
cursor_position: Position::default(),
document: Document::open(),
}
}
fn process_keypress(&mut self) -> Result<(), std::io::Error> {
let pressed_key = Terminal::read_key()?;
match pressed_key {
Key::Ctrl('q') => self.should_quit = true,
Key::Up | Key::Down | Key::Left | Key::Right => self.move_cursor(pressed_key),
_ => (),
}
Ok(())
}

fn move_cursor(&mut self, key: Key) {
let Position { mut y, mut x} = self.cursor_position;
match key {
Key::Up => y = y.saturating_sub(1),
Key::Down => y = y.saturating_add(1),
Key::Right => x = x.saturating_add(1),
Key::Left => x = x.saturating_sub(1),
_ => (),
}
self.cursor_position = Position { x, y }
}

fn refresh_screen(&self) -> Result<(), std::io::Error> {
// print!("\x1b[2J");
Terminal::cursor_hide();
Terminal::clear_screen();
Terminal::cursor_position(&Position::default());
if self.should_quit {
println!("Goodbye.\r");
} else {
self.draw_rows();
Terminal::cursor_position(&self.cursor_position);
}
Terminal::cursor_show();
Terminal::flush()
}
fn draw_rows(&self) {
let height = self.terminal.size().height;
for terminal_row in 0..height - 1 {
Terminal::clear_current_line();
if let Some(row) = self.document.row(terminal_row as usize) {
self.draw_row(row)
} else if self.document.is_empty() && terminal_row == height / 3 {
self.draw_welcome_message();
} else {
println!("~\r");
}
}
}
fn draw_welcome_message(&self) {
let mut welcome_message = format!("Hecto editor --version{}", VERSION);
let width = self.terminal.size().width as usize;
let len = welcome_message.len();
let padding = width.saturating_sub(len) / 2;
let spaces = " ".repeat(padding.saturating_sub(1));
welcome_message = format!("~{}{}", spaces, welcome_message);
welcome_message.truncate(width);
println!("{}\r", welcome_message);
}
pub fn draw_row(&self, row: &Row) {
let start = 0;
let end = self.terminal.size().width as usize;
let row = row.render(start, end);
println!("{}\r", row);
}

}
18 changes: 18 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![warn(clippy::all, clippy::pedantic)]
mod row;
mod editor;
mod document;
mod terminal;

use editor::Editor;
pub use terminal::Terminal;
pub use document::Document;
pub use row::Row;


fn main() {
println!("Welcome to Hecto Text editor");
let mut editor = Editor::default();
editor.run();
}

20 changes: 20 additions & 0 deletions src/row.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::cmp;
pub struct Row {
string: String,
}

impl From<&str> for Row {
fn from(slice: &str) -> Self {
Self {
string: String::from(slice),
}
}
}

impl Row {
pub fn render(&self, start: usize, end: usize) -> String {
let end = cmp::min(end, self.string.len());
let start = cmp::min(start, end);
self.string.get(start..end).unwrap_or_default().to_string()
}
}
62 changes: 62 additions & 0 deletions src/terminal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crate::editor::Position;
use std::io::{self, stdout, Write};
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::{IntoRawMode, RawTerminal};

pub struct Size {
pub width: u16,
pub height: u16,
}

pub struct Terminal {
size: Size,
_stdout: RawTerminal<std::io::Stdout>,
}

impl Terminal {
pub fn default() -> Result<Self, std::io::Error> {
let size = termion::terminal_size()?;
Ok(Self {
size: Size {
width: size.0,
height: size.1,
},
_stdout: stdout().into_raw_mode()?,
})
}
pub fn size (&self) -> &Size {
&self.size
}
pub fn clear_screen() {
print!("{}", termion::clear::All);
}
pub fn cursor_position(position: &Position) {
let Position{mut x, mut y} = position;
x = x.saturating_add(1);
y = y.saturating_add(1);
let x = x as u16;
let y = y as u16;
print!("{}", termion::cursor::Goto(x, y));
}
pub fn read_key() -> Result<Key, std::io::Error> {
loop {
if let Some(key) = io::stdin().lock().keys().next() {
return key;
}
}
}
pub fn flush() -> Result<(), std::io::Error> {
io::stdout().flush()
}
pub fn cursor_hide() {
print!("{}", termion::cursor::Hide);
}
pub fn cursor_show() {
print!("{}", termion::cursor::Show);
}
pub fn clear_current_line() {
print!("{}", termion::clear::CurrentLine);
}
}

0 comments on commit 7ca4398

Please sign in to comment.