1use std::{ffi::OsString, path::PathBuf};
2
3use crate::{editor_kind::EditorKind, errors::OpenEditorError};
4
5#[derive(Debug, Clone)]
6pub struct Editor {
8 pub(crate) editor_type: EditorKind,
9 pub(crate) binary_path: PathBuf,
10}
11
12impl Editor {
13 #[must_use]
15 pub fn from_bin_path(binary_path: PathBuf) -> Self {
16 Self {
17 editor_type: EditorKind::UnknownEditor,
18 binary_path,
19 }
20 }
21 #[must_use]
23 pub fn from_editor_kind(editor_type: EditorKind) -> Self {
24 let binary_path = Self::get_full_path(editor_type.to_string().into());
25 Self {
26 editor_type,
27 binary_path,
28 }
29 }
30 #[must_use]
32 pub fn new(editor_type: EditorKind, binary_path: PathBuf) -> Self {
33 Self {
34 editor_type,
35 binary_path,
36 }
37 }
38 pub(crate) fn get_full_path(editor_name: OsString) -> PathBuf {
40 match which::which(editor_name.clone()) {
41 Ok(path) => path,
42 Err(_) => PathBuf::from(editor_name), }
44 }
45 pub(crate) fn validate_executable(&self) -> Result<(), OpenEditorError> {
48 if !self.binary_path.exists() || !self.binary_path.is_file() {
49 return Err(OpenEditorError::EditorNotFound {
50 binary_path: self.binary_path.clone(),
51 });
52 }
53 #[cfg(unix)]
54 {
55 use std::os::unix::fs::PermissionsExt;
56 let metadata = std::fs::metadata(&self.binary_path).map_err(|e| {
57 OpenEditorError::EditorNotExecutable {
58 binary_path: self.binary_path.clone(),
59 error: Some(e),
60 }
61 })?;
62 let permissions = metadata.permissions();
63 if permissions.mode() & 0o111 == 0 {
64 return Err(OpenEditorError::EditorNotExecutable {
65 binary_path: self.binary_path.clone(),
66 error: None,
67 });
68 }
69 }
70
71 Ok(())
72 }
73}