Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • redox-os/sodium
  • stratact/sodium
  • Bujiraso/sodium
  • seodisparate/sodium
  • genuinebyte/sodium
  • fearghasmr/sodium
  • januz/sodium
  • Hwatwasthat/sodium
  • minneelyyyy1/sodium
  • keithp/sodium
  • ccarral/sodium
  • Remi/sodium
  • fransklaver/sodium
  • borkin8r/sodium
  • zak-grumbles/sodium
  • tlaferriere/sodium
  • ktoks/sodium
  • ghazanfari/sodium
18 results
Show changes
Commits on Source (11)
name=Sodium
binary=/ui/bin/sodium
binary=/usr/bin/sodium
icon=/ui/icons/sodium.png
accept=*_REDOX
accept=*.md
......
......@@ -48,7 +48,6 @@ impl Editor {
}
}
}
// }
}
/// Get the position before a given position, i.e. a generalisation .before(). Includes
......@@ -90,7 +89,18 @@ impl Editor {
pub fn right_unbounded(&self, n: usize) -> (isize, isize) {
((self.x() + n) as isize, self.y() as isize)
}
/// Get the position of the first word right of the cursor (horizontally bounded)
#[inline]
pub fn next_word(&self, n: usize, tight: bool) -> (usize, usize) {
let next_n = self.next_word_forward(n);
self.bound_hor((self.x() + (next_n), self.y()), tight)
}
/// Get the position of the first word end right of the cursor (horizontally bounded)
#[inline]
pub fn next_word_end(&self, n: usize, tight: bool) -> (usize, usize) {
let next_n = self.next_word_end_forward(n);
self.bound_hor((self.x() + (next_n), self.y()), tight)
}
/// Get the position of the character left to the cursor (horizontally bounded)
#[inline]
pub fn left(&self, n: usize) -> (usize, usize) {
......@@ -180,27 +190,59 @@ impl Editor {
None
}
/// Get next WORD forward
/// Get end of next WORD forward
/// "A WORD consists of a sequence of non-blank characters, separated with
/// whitespace. An empty line is also considered to be a WORD."
pub fn _next_word_forward(&self, n: usize) -> Option<usize> {
let mut dn = 0;
let mut x = self.x();
pub fn next_word_forward(&self, n_opt: usize) -> usize {
let mut word_count: usize = 0;
let x: usize = self.x();
let mut has_ws = false;
for (i, ch) in self.buffers.current_buffer()[self.y()]
for (i, current_char) in self.buffers.current_buffer()[self.y()]
.chars()
.skip(x)
.enumerate()
{
if ch.is_whitespace() {
dn += 1;
if dn == n {
x += i + 1;
return Some(x);
if current_char.is_whitespace() {
has_ws = true;
} else if has_ws && !current_char.is_whitespace() {
word_count += 1;
if word_count < n_opt - 1 {
has_ws = false;
} else {
return i;
}
}
}
0
}
None
/// Get beginning of next WORD forward
/// "A WORD consists of a sequence of non-blank characters, separated with
/// whitespace. An empty line is also considered to be a WORD."
pub fn next_word_end_forward(&self, n_opt: usize) -> usize {
let mut word_count: usize = 0;
let x: usize = self.x();
let mut word_char: bool = true;
let mut last: usize = 0;
for (i, current_char) in self.buffers.current_buffer()[self.y()]
.chars()
.skip(x)
.enumerate()
{
// if a word_char
if !current_char.is_whitespace() {
word_char = true;
last = i;
word_count += 1;
} else if current_char.is_whitespace() {
if word_char && word_count > n_opt {
return i - 1;
}
word_char = false;
}
}
last
}
}
use state::editor::Editor;
use io::parse::{Inst, Parameter};
use state::mode::{CommandMode, Mode, PrimitiveMode};
use core::prompt::PromptCommand;
use edit::buffer::TextBuffer;
use edit::insert::{InsertMode, InsertOptions};
use io::parse::{Inst, Parameter};
use io::redraw::RedrawTask;
use edit::buffer::TextBuffer;
use core::prompt::PromptCommand;
use state::editor::Editor;
use state::mode::{CommandMode, Mode, PrimitiveMode};
// TODO: Move the command definitions outta here
impl Editor {
/// Execute an instruction
pub fn exec(&mut self, Inst(para, cmd): Inst) {
use io::key::Key::*;
use state::mode::CommandMode::*;
use state::mode::Mode::*;
use state::mode::PrimitiveMode::*;
use state::mode::CommandMode::*;
let n = para.d();
let bef = self.pos();
......@@ -38,9 +38,11 @@ impl Editor {
self.cursor_mut().mode = Mode::Command(CommandMode::Normal)
}
(_, Char(' ')) if self.key_state.alt => self.next_cursor(),
_ if self.key_state.alt => if let Some(m) = self.to_motion(Inst(para, cmd)) {
self.goto(m);
},
_ if self.key_state.alt => {
if let Some(m) = self.to_motion(Inst(para, cmd)) {
self.goto(m);
}
}
(Command(Normal), Char('i')) => {
self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(InsertOptions {
mode: InsertMode::Insert,
......@@ -103,6 +105,16 @@ impl Editor {
self.goto(right);
mov = true;
}
(Command(Normal), Char('w')) => {
let next_word = self.next_word(n, true);
self.goto(next_word);
mov = true;
}
(Command(Normal), Char('e')) => {
let next_word = self.next_word_end(n, true);
self.goto(next_word);
mov = true;
}
(Command(Normal), Char('J')) => {
let down = self.down(15 * n);
self.goto(down);
......@@ -130,7 +142,20 @@ impl Editor {
mov = true;
}
}
(Command(Normal), Char('$')) => {
if self.buffers.current_buffer()[self.y()].len() != 0 {
let ln_end = (self.buffers.current_buffer()[self.y()].len() - 1, self.y());
self.goto(ln_end);
mov = true;
}
}
(Command(Normal), Char('H')) => {
println!("H pressed");
self.cursor_mut().x = 0;
mov = true;
}
(Command(Normal), Char('0')) => {
println!("0 pressed");
self.cursor_mut().x = 0;
mov = true;
}
......@@ -160,9 +185,10 @@ impl Editor {
let ins = self.get_inst();
if let Some(m) = self.to_motion_unbounded(ins) {
self.remove_rb(m);
self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(InsertOptions {
mode: InsertMode::Insert,
}));
self.cursor_mut().mode =
Mode::Primitive(PrimitiveMode::Insert(InsertOptions {
mode: InsertMode::Insert,
}));
}
}
(Command(Normal), Char('G')) => {
......@@ -230,14 +256,14 @@ impl Editor {
mov = true;
}
}
(Command(Normal), Char('W')) => {
let pos = self._next_word_forward(n);
if let Some(p) = pos {
let y = self.y();
self.goto((p, y));
mov = true;
}
}
// (Command(Normal), Char('W')) => {
// let pos = self.next_word_forward(n);
// if let Some(p) = pos {
// let y = self.y();
// self.goto((p, y));
// mov = true;
// }
// }
(Command(Normal), Char(';')) => {
self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Prompt)
}
......@@ -245,10 +271,12 @@ impl Editor {
(Command(Normal), Char('z')) => {
let Inst(param, cmd) = self.get_inst();
match param {
Parameter::Null => if let Some(m) = self.to_motion(Inst(param, cmd)) {
self.buffers.current_buffer_info_mut().scroll_y = m.1;
self.goto(m);
},
Parameter::Null => {
if let Some(m) = self.to_motion(Inst(param, cmd)) {
self.buffers.current_buffer_info_mut().scroll_y = m.1;
self.goto(m);
}
}
Parameter::Int(n) => {
self.buffers.current_buffer_info_mut().scroll_y = n;
}
......@@ -262,12 +290,14 @@ impl Editor {
(Command(Normal), Char('~')) => {
self.invert_chars(n);
}
(Command(Normal), Char('.')) => if let Some(inst) = self.previous_instruction {
self.exec(inst);
} else {
self.status_bar.msg = "No previous command".into();
self.redraw_task = RedrawTask::StatusBar;
},
(Command(Normal), Char('.')) => {
if let Some(inst) = self.previous_instruction {
self.exec(inst);
} else {
self.status_bar.msg = "No previous command".into();
self.redraw_task = RedrawTask::StatusBar;
}
}
(Command(Normal), Char(c)) => {
self.status_bar.msg = format!("Unknown command: {}", c);
self.redraw_task = RedrawTask::StatusBar;
......@@ -279,7 +309,8 @@ impl Editor {
self.invoke(cmd);
self.redraw_task = RedrawTask::StatusBar;
} else {
self.status_bar.msg = format!("Unknown command: {}", self.prompt[self.prompt_index]);
self.status_bar.msg =
format!("Unknown command: {}", self.prompt[self.prompt_index]);
}
// If we use a command we used before, don't add a new line to the vec
......
use edit::buffer::{SplitBuffer, TextBuffer};
use io::file::FileStatus;
use io::redraw::RedrawTask;
use state::editor::{Buffer, BufferManager, Editor};
use edit::buffer::{SplitBuffer, TextBuffer};
use std::process::exit;
......@@ -52,6 +52,8 @@ pub enum PromptCommand<'a> {
Help,
/// Exit Sodium.
Quit,
/// Quit without saving
ForceQuit
}
impl<'a> PromptCommand<'a> {
......@@ -76,6 +78,7 @@ impl<'a> PromptCommand<'a> {
"bd" => DeleteBuffer,
"h" | "help" => Help,
"q" | "quit" => Quit,
"q!" => ForceQuit,
bn if bn.starts_with("b") => {
let rest: String = bn.chars().skip(1).collect();
......@@ -137,14 +140,21 @@ impl Editor {
}
}
Write { path } => {
// TODO: if open multiple files written write the current file
let mut write_path: String = if path.is_empty() {
self.files[0].clone()
} else {
path.to_string()
};
if self.options.get("readonly") == Some(true) {
// TODO: add override (w!)
self.status_bar.msg = format!("File {} is opened in readonly mode", path)
self.status_bar.msg = format!("File {} is opened in readonly mode", write_path)
} else {
self.status_bar.msg = match self.write(path) {
FileStatus::NotFound => format!("File {} could not be opened", path),
FileStatus::Ok => format!("File {} written", path),
FileStatus::Other => format!("Couldn't write {}", path),
self.status_bar.msg = match self.write(&mut write_path) {
FileStatus::NotFound => format!("File {} could not be opened", write_path),
FileStatus::Ok => format!("File {} written", write_path),
FileStatus::Other => format!("Couldn't write {}", write_path),
}
}
}
......@@ -158,15 +168,17 @@ impl Editor {
self.buffers.switch_to(new_buffer_index);
self.redraw_task = RedrawTask::Full;
}
SwitchToBuffer { buffer_index: ix } => if !self.buffers.is_buffer_index_valid(ix) {
self.status_bar.msg = format!("Invalid buffer #{}", ix);
} else if self.buffers.current_buffer_index() == ix{
self.status_bar.msg = format!("Already in buffer #{}", ix);
} else {
self.buffers.switch_to(ix);
self.redraw_task = RedrawTask::Full;
self.status_bar.msg = format!("Switched to buffer #{}", ix);
},
SwitchToBuffer { buffer_index: ix } => {
if !self.buffers.is_buffer_index_valid(ix) {
self.status_bar.msg = format!("Invalid buffer #{}", ix);
} else if self.buffers.current_buffer_index() == ix {
self.status_bar.msg = format!("Already in buffer #{}", ix);
} else {
self.buffers.switch_to(ix);
self.redraw_task = RedrawTask::Full;
self.status_bar.msg = format!("Switched to buffer #{}", ix);
}
}
CreateBuffer => {
let new = self.buffers.new_buffer(Buffer::new());
self.buffers.switch_to(new);
......@@ -182,6 +194,14 @@ impl Editor {
self.open("/apps/sodium/help.txt");
}
Quit => {
let is_buffer_dirty = self.buffers.current_buffer_info().dirty;
if is_buffer_dirty {
self.status_bar.msg = format!("can not quit this file, there are some changes in the file");
} else {
exit(0);
}
}
ForceQuit => {
exit(0);
}
}
......@@ -198,14 +218,14 @@ fn get_buffers_description(buffers: &BufferManager) -> String {
}
let descriptions = buffers
.iter()
// don't include transient buffers like the one
// this is going to be shown in
.filter(|b| !b.is_transient)
.enumerate()
.map(|(i, b)| print_buffer(i, b))
.collect::<Vec<_>>()
.join("\n");
.iter()
// don't include transient buffers like the one
// this is going to be shown in
.filter(|b| !b.is_transient)
.enumerate()
.map(|(i, b)| print_buffer(i, b))
.collect::<Vec<_>>()
.join("\n");
format!(
"Buffers\n=====================================\n\n{}",
......
......@@ -66,7 +66,6 @@ pub trait TextBuffer<'a> {
fn get_indent(&self, n: usize) -> &str;
}
/// The buffer data structure, that Sodium is using.
///
/// This structure consists of two "subbuffers", which are just vectors over lines (defined by
......@@ -78,7 +77,8 @@ pub trait TextBuffer<'a> {
pub struct SplitBuffer {
before: Vec<String>,
after: Vec<String>,
#[cfg(debug)] _hinted_since_edit: bool,
#[cfg(debug)]
_hinted_since_edit: bool,
}
impl SplitBuffer {
......@@ -228,7 +228,6 @@ impl<'a> TextBuffer<'a> for SplitBuffer {
}
}
impl Index<usize> for SplitBuffer {
type Output = String;
......
use edit::buffer::TextBuffer;
use io::redraw::RedrawTask;
use state::cursor::Cursor;
use state::editor::Editor;
use io::redraw::RedrawTask;
impl Editor {
/// Delete a character.
#[inline]
pub fn delete(&mut self) {
let &Cursor { x, y, .. } = self.cursor();
self.buffers.current_buffer_info_mut().dirty = true;
if x == self.buffers.current_buffer()[y].len() {
if y + 1 < self.buffers.current_buffer().len() {
let s = self.buffers.current_buffer_mut().remove_line(y + 1);
......@@ -26,6 +27,7 @@ impl Editor {
#[inline]
pub fn backspace(&mut self) {
let previous = self.previous(1);
self.buffers.current_buffer_info_mut().dirty = true;
if let Some(p) = previous {
self.goto(p);
self.delete();
......
......@@ -12,7 +12,6 @@ pub enum InsertMode {
Replace,
}
#[derive(Clone, PartialEq, Copy)]
/// The insert options
pub struct InsertOptions {
......@@ -24,6 +23,7 @@ impl Editor {
/// Insert text under the current cursor.
pub fn insert(&mut self, k: Key, InsertOptions { mode }: InsertOptions) {
let (mut x, mut y) = self.pos();
self.buffers.current_buffer_info_mut().dirty = true;
match (mode, k) {
(InsertMode::Insert, Key::Char('\n')) => {
let first_part = self.buffers.current_buffer()[y][..x].to_owned();
......
......@@ -46,10 +46,12 @@ pub fn invert(c: char) -> char {
'}' => '{',
'!' => '?',
'?' => '!',
a => if a.is_lowercase() {
a.to_uppercase().next().unwrap_or('?')
} else {
a.to_lowercase().next().unwrap_or('?')
},
a => {
if a.is_lowercase() {
a.to_uppercase().next().unwrap_or('?')
} else {
a.to_lowercase().next().unwrap_or('?')
}
}
}
}
......@@ -37,13 +37,14 @@ impl Editor {
}
/// Write the file.
pub fn write<'a> (&'a mut self, path: &'a str) -> FileStatus {
pub fn write<'a>(&'a mut self, path: &'a str) -> FileStatus {
self.buffers.current_buffer_info_mut().title = Some(path.into());
if path == "" {
return FileStatus::Other;
}
if let Some(mut file) = File::create(path).ok() {
if file.write(self.buffers.current_buffer().to_string().as_bytes())
if file
.write(self.buffers.current_buffer().to_string().as_bytes())
.is_ok()
{
FileStatus::Ok
......
......@@ -31,8 +31,8 @@ impl Editor {
0
};
let max_vert_chars = h/self.char_height - 2 - vert_offset;
let max_horz_chars = w/self.char_width - horz_offset;
let max_vert_chars = h / self.char_height - 2 - vert_offset;
let max_horz_chars = w / self.char_width - horz_offset;
// Redraw window
self.window.set(Color::rgb(25, 25, 25));
......@@ -50,7 +50,8 @@ impl Editor {
let (pos_x, pos_y) = self.pos();
let (window_pos_x, window_pos_y) = self.coords_to_window_coords((pos_x, pos_y), max_horz_chars);
let (window_pos_x, window_pos_y) =
self.coords_to_window_coords((pos_x, pos_y), max_horz_chars);
self.window.set(Color::rgb(25, 25, 25));
......@@ -65,7 +66,7 @@ impl Editor {
}
self.window.rect(
((window_pos_x + horz_offset) * self.char_width) as i32,
((window_pos_x + horz_offset) * self.char_width) as i32,
((window_pos_y + vert_offset) * self.char_height) as i32,
self.char_width as u32,
self.char_height as u32,
......@@ -74,19 +75,24 @@ impl Editor {
let mut string = false;
'outer: for (y, row) in self.buffers.current_buffer().lines_from(scroll_y).enumerate() {
'outer: for (y, row) in self
.buffers
.current_buffer()
.lines_from(scroll_y)
.enumerate()
{
// Print line numbers
if self.options.line_numbers {
let mut line_number = scroll_y + y as usize + 1;
// The amount of digits for this line number
let mut digit_nr: usize = 0;
while line_number >= 10usize.pow(digit_nr as u32) {
digit_nr += 1;
digit_nr += 1;
}
// Print the digits for this line number
for i in 1..digit_nr + 1 {
let digit = ((line_number % 10) as u8 + ('0' as u32) as u8) as char;
line_number = (line_number - line_number % 10)/10 as usize;
line_number = (line_number - line_number % 10) / 10 as usize;
self.window.char(
(self.char_width * (horz_offset - 1 - i)) as i32,
(self.char_height * (scr_lines + vert_offset)) as i32,
......@@ -95,11 +101,17 @@ impl Editor {
);
}
}
for (x, c) in row.chars().flat_map(|c| if c == '\t' {
iter::repeat(' ').take(4)
} else {
iter::repeat(c).take(1)
}).enumerate() {
for (x, c) in row
.chars()
.flat_map(|c| {
if c == '\t' {
iter::repeat(' ').take(4)
} else {
iter::repeat(c).take(1)
}
})
.enumerate()
{
// New screen line
if scr_chars >= max_horz_chars {
scr_chars = 0;
......@@ -117,22 +129,8 @@ impl Editor {
(226, 225, 167) //(167, 222, 156)
}
_ if string => (226, 225, 167), //(167, 222, 156)
'!' |
'@' |
'#' |
'$' |
'%' |
'^' |
'&' |
'|' |
'*' |
'+' |
'-' |
'/' |
':' |
'=' |
'<' |
'>' => (198, 83, 83), //(228, 190, 175), //(194, 106, 71),
'!' | '@' | '#' | '$' | '%' | '^' | '&' | '|' | '*' | '+' | '-' | '/'
| ':' | '=' | '<' | '>' => (198, 83, 83), //(228, 190, 175), //(194, 106, 71),
'.' | ',' => (241, 213, 226),
'(' | ')' | '[' | ']' | '{' | '}' => (164, 212, 125), //(195, 139, 75),
'0'..='9' => (209, 209, 177),
......@@ -170,7 +168,11 @@ impl Editor {
self.window.sync();
}
fn coords_to_window_coords(&mut self, point: (usize, usize), max_horz_chars: usize) -> (usize, usize) {
fn coords_to_window_coords(
&mut self,
point: (usize, usize),
max_horz_chars: usize,
) -> (usize, usize) {
let (_, scroll_y) = {
let current_buffer = self.buffers.current_buffer_info();
......@@ -182,7 +184,12 @@ impl Editor {
let mut ret_y = 0;
let ret_x = point.0 % max_horz_chars;
for (y, row) in self.buffers.current_buffer().lines_from(scroll_y).enumerate() {
for (y, row) in self
.buffers
.current_buffer()
.lines_from(scroll_y)
.enumerate()
{
if to_y > y {
ret_y += row.len() / max_horz_chars + 1;
} else {
......@@ -199,11 +206,8 @@ impl Editor {
if self.buffers.current_buffer_info().scroll_y > 0
&& pos_y <= self.buffers.current_buffer_info().scroll_y
{
self.buffers.current_buffer_info_mut().scroll_y = if pos_y == 0 {
pos_y
} else {
pos_y - 1
};
self.buffers.current_buffer_info_mut().scroll_y =
if pos_y == 0 { pos_y } else { pos_y - 1 };
return;
}
......@@ -211,7 +215,13 @@ impl Editor {
let mut line_counter = 0;
let mut result_y = 0;
for (y, row) in self.buffers.current_buffer().lines_from(pos_y+1).rev().enumerate() {
for (y, row) in self
.buffers
.current_buffer()
.lines_from(pos_y + 1)
.rev()
.enumerate()
{
if pos_y - y < scroll_y {
return;
}
......@@ -264,7 +274,8 @@ impl Editor {
let mode = self.cursor().mode;
let current_title = self.buffers
let current_title = self
.buffers
.current_buffer_info()
.title
.as_ref()
......@@ -286,8 +297,9 @@ impl Editor {
.collect::<Vec<_>>()
} else {
text.chars().collect()
}).into_iter()
.enumerate()
})
.into_iter()
.enumerate()
{
self.window.char(
((w * a) / b) as i32 + (n as i32 * 8),
......
......@@ -3,10 +3,10 @@ use io::key::Key;
#[cfg(feature = "orbital")]
use orbclient::KeyEvent;
#[cfg(feature = "ansi")]
use std::io::Stdin;
#[cfg(feature = "ansi")]
use std::io::prelude::*;
#[cfg(feature = "ansi")]
use std::io::Stdin;
/// Key state
pub struct KeyState {
......
/// Partial redraws.
pub mod redraw;
/// Parsing of input commands.
pub mod parse;
/// Loading and writing files.
pub mod file;
/// Graphics and rendering.
pub mod graphics;
/// Key input and parsing.
pub mod key;
/// The "key state" of the editor.
///
/// The key state contains information about the current state of modifiers.
pub mod key_state;
/// Key input and parsing.
pub mod key;
/// Graphics and rendering.
pub mod graphics;
/// Loading and writing files.
pub mod file;
/// Parsing of input commands.
pub mod parse;
/// Partial redraws.
pub mod redraw;
......@@ -46,11 +46,13 @@ impl Editor {
loop {
for event in self.window.events() {
match event.to_option() {
EventOption::Key(k) => if let Some(Key::Char(c)) = self.key_state.feed(k) {
self.status_bar.cmd.push(c);
self.redraw_task = RedrawTask::StatusBar;
return c;
},
EventOption::Key(k) => {
if let Some(Key::Char(c)) = self.key_state.feed(k) {
self.status_bar.cmd.push(c);
self.redraw_task = RedrawTask::StatusBar;
return c;
}
}
_ => {}
}
}
......@@ -86,10 +88,14 @@ impl Editor {
}
Mode::Command(_) => {
n = match c {
'0'..='9' => {
'0'..='9' => if unset && c == '0' {
key = k;
n
} else {
unset = false;
n * 10 + ((c as u8) - b'0') as usize
}
_ => {
key = k;
n
......
//! Sodium is a next generation Vi-like editor.
#![feature(stmt_expr_attributes)]
#![deny(warnings)]
#![deny(missing_docs)]
#[cfg(feature = "orbital")]
......@@ -19,7 +18,6 @@ pub mod io;
/// State of the editor.
pub mod state;
fn main() {
self::state::editor::Editor::init();
}
use std::slice::Iter;
use edit::buffer::{SplitBuffer, TextBuffer};
use state::cursor::Cursor;
use io::graphics::StatusBar;
use io::key::{Cmd, Key};
use io::key_state::KeyState;
use state::options::Options;
use io::parse::Inst;
use io::redraw::RedrawTask;
use state::cursor::Cursor;
use state::options::Options;
use std::slice::Iter;
#[cfg(feature = "orbital")]
use orbclient::Window;
......@@ -34,6 +34,8 @@ pub struct Buffer {
/// True if the buffer is transient and should be deleted when
/// it is no longer the current buffer.
pub is_transient: bool,
/// True if the buffer has unsaved changes
pub dirty: bool,
}
impl Buffer {
......@@ -47,6 +49,7 @@ impl Buffer {
scroll_y: 0,
title: None,
is_transient: false,
dirty: false,
}
}
}
......
/// The global editor state.
pub mod editor;
/// Cursors.
///
/// A cursor contains various non-global information about the editor state. You can switch between
/// cursor, for reusing older editor states.
pub mod cursor;
/// Options and configuration of the editor.
pub mod options;
/// The global editor state.
pub mod editor;
/// Editor modes.
pub mod mode;
/// Options and configuration of the editor.
pub mod options;
......@@ -17,9 +17,9 @@ pub enum Mode {
impl Mode {
/// Convert the mode to string
pub fn to_string(self) -> &'static str {
use self::CommandMode::*;
use self::Mode::*;
use self::PrimitiveMode::*;
use self::CommandMode::*;
match self {
Command(Normal) => "Normal",
Primitive(Insert(_)) => "Insert",
......