aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2023-12-27 09:37:47 -0800
committerRose Hogenson <rosehogenson@posteo.net>2023-12-27 09:37:47 -0800
commit4fdf430f66dd97b52529f9e23a67c67c272f2406 (patch)
tree6f6c0bd6040f87596a018fa24fe9749554c52552 /src
parentb0aaa173bdd2137d7cdd7aa55f5aa7d7222b4c03 (diff)
downloadeditor-4fdf430f66dd97b52529f9e23a67c67c272f2406.tar.zst
Print the first n lines of the file.
Diffstat (limited to 'src')
-rw-r--r--src/main.rs6
-rw-r--r--src/rope.rs85
2 files changed, 85 insertions, 6 deletions
diff --git a/src/main.rs b/src/main.rs
index 10d7647..711f920 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -12,14 +12,16 @@ fn edit(file: &OsStr) -> Result<(), String> {
return Err(format!("open file {}: {}", file.to_string_lossy(), err));
}
};
- println!("{}", r);
let size = match tiocgwinsz::size() {
Some(size) => size,
None => {
return Err(String::from("cannot get terminal size"));
}
};
- println!("{}, {}", size.ws_row, size.ws_col);
+ let mut stdout = std::io::stdout();
+ if let Err(err) = r.print_lines(&mut stdout, 0, usize::from(size.ws_row)) {
+ return Err(format!("write: {}", err));
+ }
return Ok(());
}
diff --git a/src/rope.rs b/src/rope.rs
index 320cd14..b1b5831 100644
--- a/src/rope.rs
+++ b/src/rope.rs
@@ -1,6 +1,6 @@
-use std::fmt::{Display, Error, Formatter};
+use std::fmt::{Display, Formatter};
use std::fs::File;
-use std::io::{ErrorKind, Read};
+use std::io::{ErrorKind, Read, Write};
use std::path::Path;
use std::rc::Rc;
@@ -10,6 +10,8 @@ const MAX_NODE_SIZE: usize = 4;
struct Branch {
left: Rc<Node>,
right: Rc<Node>,
+ // Number of newline characters under this branch.
+ lines: usize,
}
enum Node {
@@ -36,10 +38,73 @@ impl Node {
_ => false,
};
}
+
+ fn lines(&self) -> usize {
+ match self {
+ Node::Leaf(v) => {
+ let mut count = 0;
+ for &c in v {
+ if c == b'\n' {
+ count += 1;
+ }
+ }
+ return count;
+ }
+ Node::Branch(b) => {
+ return b.lines;
+ }
+ }
+ }
+
+ fn print_lines(
+ &self,
+ out: &mut dyn Write,
+ start: usize,
+ end: usize,
+ ) -> Result<(), std::io::Error> {
+ match self {
+ Node::Leaf(v) => {
+ let mut nl_count = 0;
+ let mut start_pos = 0;
+ let mut end_pos = v.len();
+ for (i, &c) in v.iter().enumerate() {
+ if c != b'\n' {
+ continue;
+ }
+ nl_count += 1;
+ if nl_count == start {
+ start_pos = i;
+ }
+ if nl_count == end {
+ end_pos = i + 1;
+ }
+ }
+ if let Err(err) = out.write(&v[start_pos..end_pos]) {
+ return Err(err);
+ }
+ return Ok(());
+ }
+ Node::Branch(b) => {
+ let right_start;
+ if start <= b.left.lines() {
+ if let Err(err) = b.left.print_lines(out, start, end) {
+ return Err(err);
+ }
+ right_start = 0;
+ } else {
+ right_start = start - b.left.lines();
+ }
+ if end <= b.left.lines() {
+ return Ok(());
+ }
+ return b.right.print_lines(out, right_start, end - b.left.lines());
+ }
+ }
+ }
}
impl Display for Node {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
let mut buf = Vec::new();
self.write(&mut buf);
return write!(f, "{}", String::from_utf8_lossy(&buf));
@@ -57,9 +122,11 @@ impl Rope {
if other.empty() {
return Rope(me);
}
+ let lines = me.lines() + other.lines();
return Rope(Rc::new(Node::Branch(Branch {
left: me,
right: other,
+ lines: lines,
})));
}
@@ -89,10 +156,20 @@ impl Rope {
}
return Ok(rope);
}
+
+ pub fn print_lines(
+ &self,
+ out: &mut dyn Write,
+ start: usize,
+ end: usize,
+ ) -> Result<(), std::io::Error> {
+ let Rope(me) = self;
+ return me.print_lines(out, start, end);
+ }
}
impl Display for Rope {
- fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let Rope(n) = self;
return write!(f, "{}", n);
}