@@ -185,6 +185,8 @@ pub struct Document {
185185
186186 // when document was used for most-recent-used buffer picker
187187 pub focused_at: std::time::Instant,
188+
189+ pub readonly: bool,
188190}
189191
190192/// Inlay hints for a single `(Document, View)` combo.
@@ -673,6 +675,7 @@ impl Document {
673675 config,
674676 version_control_head: None,
675677 focused_at: std::time::Instant::now(),
678+ readonly: false,
676679 }
677680 }
678681
@@ -955,6 +958,33 @@ impl Document {
955958 }
956959 }
957960
961+ #[cfg(unix)]
962+ // Detect if the file is readonly and change the readonly field if necessary (unix only)
963+ pub fn detect_readonly(&mut self) {
964+ use rustix::fs::{access, Access};
965+ // Allows setting the flag for files the user cannot modify, like root files
966+ self.readonly = match &self.path {
967+ None => false,
968+ Some(p) => access(p, Access::WRITE_OK).is_err(),
969+ };
970+ }
971+
972+ #[cfg(not(unix))]
973+ // Detect if the file is readonly and change the readonly field if necessary (non-unix os)
974+ pub fn detect_readonly(&mut self) {
975+ // TODO Use the Windows' function `CreateFileW` to check if a file is readonly
976+ // Discussion: https://github.com/helix-editor/helix/pull/7740#issuecomment-1656806459
977+ // Vim implementation: https://github.com/vim/vim/blob/4c0089d696b8d1d5dc40568f25ea5738fa5bbffb/src/os_win32.c#L7665
978+ // Windows binding: https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Storage/FileSystem/fn.CreateFileW.html
979+ self.readonly = match &self.path {
980+ None => false,
981+ Some(p) => match std::fs::metadata(p) {
982+ Err(_) => false,
983+ Ok(metadata) => metadata.permissions().readonly(),
984+ },
985+ };
986+ }
987+
958988 /// Reload the document from its path.
959989 pub fn reload(
960990 &mut self,
@@ -969,6 +999,9 @@ impl Document {
969999 .ok_or_else(|| anyhow!("can't find file to reload from {:?}", self.display_name()))?
9701000 .to_owned();
9711001
1002+ // Once we have a valid path we check if its readonly status has changed
1003+ self.detect_readonly();
1004+
9721005 let mut file = std::fs::File::open(&path)?;
9731006 let (rope, ..) = from_reader(&mut file, Some(encoding))?;
9741007
@@ -1018,6 +1051,8 @@ impl Document {
10181051 // and error out when document is saved
10191052 self.path = path;
10201053
1054+ self.detect_readonly();
1055+
10211056 Ok(())
10221057 }
10231058