Skip to content

Commit 18d0ee2

Browse files
authored
Merge branch 'main' into main
2 parents b647c0b + c031f22 commit 18d0ee2

File tree

12 files changed

+81
-38
lines changed

12 files changed

+81
-38
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ debug = "full" # No one needs an undebuggable release binary
2424
lto = true # reduces binary size by ~14%
2525
opt-level = "s" # reduces binary size by ~25%
2626
panic = "abort" # reduces binary size by ~50% in combination with -Zbuild-std-features=panic_immediate_abort
27-
split-debuginfo = "packed" # generates a seperate *.dwp/*.dSYM so the binary can get stripped
27+
split-debuginfo = "packed" # generates a separate *.dwp/*.dSYM so the binary can get stripped
2828
strip = "symbols" # See split-debuginfo - allows us to drop the size by ~65%
2929
incremental = true # Improves re-compile times
3030

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ This editor pays homage to the classic [MS-DOS Editor](https://en.wikipedia.org/
1313
* Copy the `edit` binary to a directory in your `PATH`
1414
* You may delete any other files in the archive if you don't need them
1515

16+
### WinGet (Windows)
17+
18+
* Open up a terminal of your choice and run the following command:
19+
```powershell
20+
winget install Microsoft.Edit
21+
```
22+
* `edit` will be automatically added to your `PATH`. If typing `edit` doesn't work, open a new terminal.
23+
1624
## Build Instructions
1725

1826
* [Install Rust](https://www.rust-lang.org/tools/install)

src/bin/edit/documents.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl Document {
3232
tb.write_file(&mut file)?;
3333
}
3434

35-
if let Ok(id) = sys::file_id(&file) {
35+
if let Ok(id) = sys::file_id(None, path) {
3636
self.file_id = Some(id);
3737
}
3838

@@ -52,7 +52,7 @@ impl Document {
5252
tb.read_file(&mut file, encoding)?;
5353
}
5454

55-
if let Ok(id) = sys::file_id(&file) {
55+
if let Ok(id) = sys::file_id(None, path) {
5656
self.file_id = Some(id);
5757
}
5858

@@ -156,10 +156,7 @@ impl DocumentManager {
156156
Err(err) => return Err(err),
157157
};
158158

159-
let file_id = match &file {
160-
Some(file) => Some(sys::file_id(file)?),
161-
None => None,
162-
};
159+
let file_id = if file.is_some() { Some(sys::file_id(file.as_ref(), &path)?) } else { None };
163160

164161
// Check if the file is already open.
165162
if file_id.is_some() && self.update_active(|doc| doc.file_id == file_id) {

src/bin/edit/draw_filepicker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ pub fn draw_file_picker(ctx: &mut Context, state: &mut State) {
116116
&& let Some(path) = doit.as_deref()
117117
&& let Some(doc) = state.documents.active()
118118
&& let Some(file_id) = &doc.file_id
119-
&& sys::file_id_at(path).is_ok_and(|id| &id == file_id)
119+
&& sys::file_id(None, path).is_ok_and(|id| &id == file_id)
120120
{
121121
state.file_picker_overwrite_warning = doit.take();
122122
}

src/bin/edit/draw_menubar.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ pub fn draw_menubar(ctx: &mut Context, state: &mut State) {
1414
ctx.attr_background_rgba(state.menubar_color_bg);
1515
ctx.attr_foreground_rgba(state.menubar_color_fg);
1616
{
17+
let contains_focus = ctx.contains_focus();
18+
1719
if ctx.menubar_menu_begin(loc(LocId::File), 'F') {
1820
draw_menu_file(ctx, state);
1921
}
22+
if !contains_focus && ctx.consume_shortcut(vk::F10) {
23+
ctx.steal_focus();
24+
}
2025
if state.documents.active().is_some() && ctx.menubar_menu_begin(loc(LocId::Edit), 'E') {
2126
draw_menu_edit(ctx, state);
2227
}

src/bin/edit/localization.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,22 @@ impl<'a> TryFrom<ArenaString<'a>> for LangId {
905905
}
906906

907907
pub fn init() {
908+
const LANG_MAP: &[(&str, LangId)] = &[
909+
("en", LangId::en),
910+
// ----------------
911+
("de", LangId::de),
912+
("es", LangId::es),
913+
("fr", LangId::fr),
914+
("it", LangId::it),
915+
("ja", LangId::ja),
916+
("ko", LangId::ko),
917+
("pt-br", LangId::pt_br),
918+
("ru", LangId::ru),
919+
("zh-hant", LangId::zh_hant),
920+
("zh-tw", LangId::zh_hant),
921+
("zh", LangId::zh_hans),
922+
];
923+
908924
let scratch = scratch_arena(None);
909925
let lang_strs = sys::preferred_languages(&scratch);
910926

src/bin/edit/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ impl Drop for RestoreModes {
497497
fn drop(&mut self) {
498498
// Same as in the beginning but in the reverse order.
499499
// It also includes DECSCUSR 0 to reset the cursor style and DECTCEM to show the cursor.
500-
sys::write_stdout("\x1b[0 q\x1b[?25h\x1b]0;\x07\x1b[?1002;1006;2004l\x1b[?1049l");
500+
sys::write_stdout("\x1b[0 q\x1b[?25h\x1b]0;\x07\x1b[?1036l\x1b[?1002;1006;2004l\x1b[?1049l");
501501
}
502502
}
503503

@@ -509,7 +509,8 @@ fn setup_terminal(tui: &mut Tui, vt_parser: &mut vt::Parser) -> RestoreModes {
509509
// 1002: Cell Motion Mouse Tracking
510510
// 1006: SGR Mouse Mode
511511
// 2004: Bracketed Paste Mode
512-
"\x1b[?1049h\x1b[?1002;1006;2004h",
512+
// 1036: Xterm: "meta sends escape" (Alt keypresses should be encoded with ESC + char)
513+
"\x1b[?1049h\x1b[?1002;1006;2004h\x1b[?1036h",
513514
// OSC 4 color table requests for indices 0 through 15 (base colors).
514515
"\x1b]4;0;?;1;?;2;?;3;?;4;?;5;?;6;?;7;?\x07",
515516
"\x1b]4;8;?;9;?;10;?;11;?;12;?;13;?;14;?;15;?\x07",

src/sys/mod.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@
33

44
//! Platform abstractions.
55
6-
use std::fs::File;
7-
use std::path::Path;
8-
9-
use crate::apperr;
10-
116
#[cfg(unix)]
127
mod unix;
138
#[cfg(windows)]
@@ -20,9 +15,3 @@ pub use std::fs::canonicalize;
2015
pub use unix::*;
2116
#[cfg(windows)]
2217
pub use windows::*;
23-
24-
pub fn file_id_at(path: &Path) -> apperr::Result<FileId> {
25-
let file = File::open(path)?;
26-
let file_id = file_id(&file)?;
27-
Ok(file_id)
28-
}

src/sys/unix.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::ffi::{CStr, c_int, c_void};
1010
use std::fs::{self, File};
1111
use std::mem::{self, ManuallyDrop, MaybeUninit};
1212
use std::os::fd::{AsRawFd as _, FromRawFd as _};
13+
use std::path::Path;
1314
use std::ptr::{self, NonNull, null_mut};
1415
use std::{thread, time};
1516

@@ -350,8 +351,13 @@ pub struct FileId {
350351
st_ino: libc::ino_t,
351352
}
352353

353-
/// Returns a unique identifier for the given file.
354-
pub fn file_id(file: &File) -> apperr::Result<FileId> {
354+
/// Returns a unique identifier for the given file by handle or path.
355+
pub fn file_id(file: Option<&File>, path: &Path) -> apperr::Result<FileId> {
356+
let file = match file {
357+
Some(f) => f,
358+
None => &File::open(path)?,
359+
};
360+
355361
unsafe {
356362
let mut stat = MaybeUninit::<libc::stat>::uninit();
357363
check_int_return(libc::fstat(file.as_raw_fd(), stat.as_mut_ptr()))?;

src/sys/windows.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -398,24 +398,40 @@ pub fn open_stdin_if_redirected() -> Option<File> {
398398
}
399399

400400
/// A unique identifier for a file.
401-
#[derive(Clone)]
402-
#[repr(transparent)]
403-
pub struct FileId(FileSystem::FILE_ID_INFO);
401+
pub enum FileId {
402+
Id(FileSystem::FILE_ID_INFO),
403+
Path(PathBuf),
404+
}
404405

405406
impl PartialEq for FileId {
406407
fn eq(&self, other: &Self) -> bool {
407-
// Lowers to an efficient word-wise comparison.
408-
const SIZE: usize = std::mem::size_of::<FileSystem::FILE_ID_INFO>();
409-
let a: &[u8; SIZE] = unsafe { mem::transmute(&self.0) };
410-
let b: &[u8; SIZE] = unsafe { mem::transmute(&other.0) };
411-
a == b
408+
match (self, other) {
409+
(FileId::Id(left), FileId::Id(right)) => {
410+
// Lowers to an efficient word-wise comparison.
411+
const SIZE: usize = std::mem::size_of::<FileSystem::FILE_ID_INFO>();
412+
let a: &[u8; SIZE] = unsafe { mem::transmute(left) };
413+
let b: &[u8; SIZE] = unsafe { mem::transmute(right) };
414+
a == b
415+
}
416+
(FileId::Path(left), FileId::Path(right)) => left == right,
417+
_ => false,
418+
}
412419
}
413420
}
414421

415422
impl Eq for FileId {}
416423

417-
/// Returns a unique identifier for the given file.
418-
pub fn file_id(file: &File) -> apperr::Result<FileId> {
424+
/// Returns a unique identifier for the given file by handle or path.
425+
pub fn file_id(file: Option<&File>, path: &Path) -> apperr::Result<FileId> {
426+
let file = match file {
427+
Some(f) => f,
428+
None => &File::open(path)?,
429+
};
430+
431+
file_id_from_handle(file).or_else(|_| Ok(FileId::Path(std::fs::canonicalize(path)?)))
432+
}
433+
434+
fn file_id_from_handle(file: &File) -> apperr::Result<FileId> {
419435
unsafe {
420436
let mut info = MaybeUninit::<FileSystem::FILE_ID_INFO>::uninit();
421437
check_bool_return(FileSystem::GetFileInformationByHandleEx(
@@ -424,7 +440,7 @@ pub fn file_id(file: &File) -> apperr::Result<FileId> {
424440
info.as_mut_ptr() as *mut _,
425441
mem::size_of::<FileSystem::FILE_ID_INFO>() as u32,
426442
))?;
427-
Ok(FileId(info.assume_init()))
443+
Ok(FileId::Id(info.assume_init()))
428444
}
429445
}
430446

src/tui.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! set up callbacks for when it is clicked, and then stop worrying about it.
1717
//!
1818
//! The downside of immediate mode is that your UI code _may_ become cluttered.
19-
//! The upside however is that that you cannot leak UI elements, you don't need to
19+
//! The upside however is that you cannot leak UI elements, you don't need to
2020
//! worry about lifetimes nor callbacks, and that simple UIs are simple to write.
2121
//!
2222
//! More importantly though, the primary reason for this is that the
@@ -2410,8 +2410,13 @@ impl<'a> Context<'a, '_> {
24102410
// If the line has some indentation and the user pressed Home,
24112411
// the first time it'll stop at the indentation. The second time
24122412
// they press it, it'll move to the true start of the line.
2413-
let indent_end = tb.indent_end_logical_pos();
2414-
if logical_after.x == 0 && logical_before > indent_end {
2413+
//
2414+
// If the cursor is already at the start of the line,
2415+
// we move it back to the end of the indentation.
2416+
if logical_after.x == 0
2417+
&& let indent_end = tb.indent_end_logical_pos()
2418+
&& (logical_before > indent_end || logical_before.x == 0)
2419+
{
24152420
if modifiers == kbmod::SHIFT {
24162421
tb.selection_update_logical(indent_end);
24172422
} else {

src/unicode/measurement.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ impl<'doc> MeasurementConfig<'doc> {
486486
}
487487
}
488488

489-
/// Seeks forward to to the given line start.
489+
/// Seeks forward to the given line start.
490490
///
491491
/// If given a piece of `text`, and assuming you're currently at `offset` which
492492
/// is on the logical line `line`, this will seek forward until the logical line

0 commit comments

Comments
 (0)