Compare commits
53 Commits
shared-mod
...
ce493e016d
| Author | SHA1 | Date | |
|---|---|---|---|
| ce493e016d | |||
| 06c2ca1bb3 | |||
| 01de2390ac | |||
| 784592658a | |||
| 779872b2f6 | |||
| e5f77ef51c | |||
| 8ce92b435b | |||
| bc29502ad4 | |||
| 4622102d81 | |||
| dc680554dd | |||
| 177a4bc432 | |||
| 5f4391cb82 | |||
| 2273c0156e | |||
| 417f01b527 | |||
| d776602fe8 | |||
| e2ddadd952 | |||
| 61c7f59237 | |||
| 1e63eabd46 | |||
| ac83b3e30f | |||
| a42ad73a57 | |||
| 1ec13aa43a | |||
| 0a3f095080 | |||
| 6474c5b6bd | |||
| 717ea70895 | |||
| 8eada4bbee | |||
| 0ebd45ae15 | |||
| 14e7514cc1 | |||
| b3bb13fa33 | |||
| ad95056376 | |||
| 384fa51b6e | |||
| fc2a44740f | |||
| f609aa02db | |||
| fdb4f0db0b | |||
| 2d5e721a79 | |||
| 2e55ba1a4b | |||
| 6b9e3b1b40 | |||
| bdb126cab5 | |||
| a4f6f199ec | |||
| 911a29937e | |||
| 579826d398 | |||
| 3b1f33f055 | |||
| 607dae32fe | |||
| bb032e9daf | |||
| 886a32a9e2 | |||
| 0c58b6c436 | |||
| df3547267b | |||
| a605c4929e | |||
| a40125416d | |||
| 6777a44b3b | |||
| 288298ac18 | |||
| d461a29ff9 | |||
| bc906cd7f3 | |||
| 8ddff3fe9e |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1174,7 +1174,6 @@ dependencies = [
|
||||
"libclide-macros",
|
||||
"log",
|
||||
"strum",
|
||||
"syntect",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
# CLIDE
|
||||
[](https://github.com/shaunrd0/clide)
|
||||
[](https://gitlab.com/shaunrd0/clide)
|
||||
[](https://git.shaunreed.com/shaunrd0/clide)
|
||||
|
||||
[](https://github.com/shaunrd0/clide/actions/workflows/check.yaml)
|
||||
|
||||
@@ -41,7 +38,7 @@ export QMAKE=$HOME/Qt/6.7.3/gcc_64/bin/qmake6
|
||||
export LD_LIBRARY_PATH=$HOME/Qt/6.7.3/gcc_64/lib
|
||||
```
|
||||
|
||||
Though environment variables set using `export` will take precedence, these can also be set in [.cargo/config.toml](./.cargo/config.toml) for convenience
|
||||
Though environment variables set using `export` will take precedence, these can also be set in [.cargo/config.toml](./.cargo/config.toml) for conveinence
|
||||
|
||||
```toml
|
||||
[env]
|
||||
|
||||
@@ -9,4 +9,3 @@ strum = { workspace = true }
|
||||
log = { workspace = true }
|
||||
devicons = { workspace = true }
|
||||
libclide-macros = { path = "../libclide-macros" }
|
||||
syntect = "5.3.0"
|
||||
|
||||
@@ -4,21 +4,4 @@
|
||||
|
||||
pub mod entry_meta;
|
||||
|
||||
use anyhow::Context;
|
||||
pub use entry_meta::icon;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn read_file<P: AsRef<Path>>(p: P) -> anyhow::Result<String> {
|
||||
let path = p.as_ref();
|
||||
let meta =
|
||||
fs::metadata(path).unwrap_or_else(|_| panic!("Failed to get file metadata {path:?}"));
|
||||
if !meta.is_file() {
|
||||
crate::warn!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file");
|
||||
Err(anyhow::anyhow!(
|
||||
"Attempted to open file {path:?} that is not a valid file"
|
||||
))?;
|
||||
}
|
||||
let path_str = path.to_string_lossy().to_string();
|
||||
fs::read_to_string(path_str.as_str()).context(format!("Failed to read file {path:?}"))
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
pub mod macros;
|
||||
|
||||
pub use libclide_macros::Loggable;
|
||||
pub trait Loggable {
|
||||
const ID: &'static str;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
//!
|
||||
//! The Loggable trait can be implemented to automatically associate log messages with a struct.
|
||||
//! ```
|
||||
//! use libclide::log::Loggable;
|
||||
//! use libclide_macros::Loggable;
|
||||
//!
|
||||
//! #[derive(Loggable)]
|
||||
//! struct MyStruct;
|
||||
@@ -35,7 +35,7 @@ macro_rules! info {
|
||||
log::info!(target: $target, $($arg)+)
|
||||
});
|
||||
|
||||
($($arg:tt)+) => (log::info!(target: Self::ID, $($arg)+))
|
||||
($($arg:tt)+) => (log::info!(target: <Self as libclide::log::Loggable>::ID, $($arg)+))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -44,7 +44,7 @@ macro_rules! debug {
|
||||
log::debug!(target: $target, $($arg)+)
|
||||
});
|
||||
|
||||
($($arg:tt)+) => (log::debug!(target: Self::ID, $($arg)+))
|
||||
($($arg:tt)+) => (log::debug!(target: <Self as libclide::log::Loggable>::ID, $($arg)+))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -53,7 +53,7 @@ macro_rules! warn {
|
||||
log::warn!(target: $target, $($arg)+)
|
||||
});
|
||||
|
||||
($($arg:tt)+) => (log::warn!(target: Self::ID, $($arg)+))
|
||||
($($arg:tt)+) => (log::warn!(target: <Self as libclide::log::Loggable>::ID, $($arg)+))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -62,7 +62,7 @@ macro_rules! error {
|
||||
log::error!(target: $target, $($arg)+)
|
||||
});
|
||||
|
||||
($($arg:tt)+) => (log::error!(target: Self::ID, $($arg)+))
|
||||
($($arg:tt)+) => (log::error!(target: <Self as libclide::log::Loggable>::ID, $($arg)+))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -71,5 +71,5 @@ macro_rules! trace {
|
||||
log::trace!(target: $target, $($arg)+)
|
||||
});
|
||||
|
||||
($($arg:tt)+) => (log::trace!(target: Self::ID, $($arg)+))
|
||||
($($arg:tt)+) => (log::trace!(target: <Self as libclide::log::Loggable>::ID, $($arg)+))
|
||||
}
|
||||
|
||||
@@ -3,4 +3,3 @@
|
||||
// SPDX-License-Identifier: GNU General Public License v3.0 or later
|
||||
|
||||
pub mod colors;
|
||||
pub mod highlighter;
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::highlighting::ThemeSet;
|
||||
use syntect::html::{IncludeBackground, append_highlighted_html_for_styled_line};
|
||||
use syntect::parsing::SyntaxSet;
|
||||
use syntect::util::LinesWithEndings;
|
||||
|
||||
pub struct Highlighter {
|
||||
path: String,
|
||||
ss: SyntaxSet,
|
||||
ts: ThemeSet,
|
||||
}
|
||||
|
||||
impl Highlighter {
|
||||
pub fn new<P: AsRef<Path>>(p: P) -> anyhow::Result<Highlighter> {
|
||||
let path = p.as_ref();
|
||||
let meta =
|
||||
fs::metadata(path).unwrap_or_else(|_| panic!("Failed to get file metadata {path:?}"));
|
||||
let ss = SyntaxSet::load_defaults_nonewlines();
|
||||
let ts = ThemeSet::load_defaults();
|
||||
if !meta.is_file() {
|
||||
crate::error!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file");
|
||||
Err(anyhow::anyhow!(
|
||||
"Attempted to open file {path:?} that is not a valid file"
|
||||
))?;
|
||||
}
|
||||
Ok(Highlighter {
|
||||
path: path.to_string_lossy().to_string(),
|
||||
ss,
|
||||
ts,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn syntax_highlight_text<P: AsRef<str>>(&self, p: P) -> String {
|
||||
let text = p.as_ref();
|
||||
let theme = &self.ts.themes["base16-ocean.dark"];
|
||||
let lang = self
|
||||
.ss
|
||||
.find_syntax_by_extension(
|
||||
Path::new(self.path.as_str())
|
||||
.extension()
|
||||
.map(|s| s.to_str())
|
||||
.unwrap_or_else(|| Some("md"))
|
||||
.expect("Failed to get file extension"),
|
||||
)
|
||||
.unwrap_or_else(|| self.ss.find_syntax_plain_text());
|
||||
let mut highlighter = HighlightLines::new(lang, theme);
|
||||
// If you care about the background, see `start_highlighted_html_snippet(theme);`.
|
||||
let mut output = String::from("<pre>\n");
|
||||
for line in LinesWithEndings::from(text) {
|
||||
let regions = highlighter
|
||||
.highlight_line(line, &self.ss)
|
||||
.expect("Failed to highlight");
|
||||
|
||||
append_highlighted_html_for_styled_line(
|
||||
®ions[..],
|
||||
IncludeBackground::No,
|
||||
&mut output,
|
||||
)
|
||||
.expect("Failed to insert highlighted html");
|
||||
}
|
||||
output.push_str("</pre>\n");
|
||||
output
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ Rectangle {
|
||||
|
||||
ListModel {
|
||||
id: model
|
||||
|
||||
}
|
||||
ListView {
|
||||
id: listView
|
||||
@@ -37,10 +38,10 @@ Rectangle {
|
||||
|
||||
anchors.fill: parent
|
||||
model: model
|
||||
verticalLayoutDirection: ListView.BottomToTop
|
||||
|
||||
delegate: Text {
|
||||
color: listView.getLogColor(level)
|
||||
font.family: "monospace"
|
||||
text: `[${level}] ${message}`
|
||||
}
|
||||
|
||||
|
||||
@@ -20,16 +20,25 @@ MenuBar {
|
||||
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionSave
|
||||
id: actionNewProject
|
||||
|
||||
text: qsTr("&Save")
|
||||
text: qsTr("&New Project...")
|
||||
}
|
||||
}
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionReload
|
||||
id: actionOpen
|
||||
|
||||
text: qsTr("&Reload")
|
||||
text: qsTr("&Open...")
|
||||
}
|
||||
|
||||
onTriggered: FileSystem.setDirectory(FileSystem.filePath)
|
||||
}
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionSave
|
||||
|
||||
text: qsTr("&Save")
|
||||
}
|
||||
}
|
||||
MenuSeparator {
|
||||
@@ -58,9 +67,37 @@ MenuBar {
|
||||
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionCloseTab
|
||||
id: actionUndo
|
||||
|
||||
text: qsTr("&Close Tab")
|
||||
text: qsTr("&Undo")
|
||||
}
|
||||
}
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionRedo
|
||||
|
||||
text: qsTr("&Redo")
|
||||
}
|
||||
}
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionCut
|
||||
|
||||
text: qsTr("&Cut")
|
||||
}
|
||||
}
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionCopy
|
||||
|
||||
text: qsTr("&Copy")
|
||||
}
|
||||
}
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionPaste
|
||||
|
||||
text: qsTr("&Paste")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,6 +132,13 @@ MenuBar {
|
||||
ClideMenu {
|
||||
title: qsTr("&Help")
|
||||
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionDocumentation
|
||||
|
||||
text: qsTr("&Documentation")
|
||||
}
|
||||
}
|
||||
ClideMenuItem {
|
||||
action: Action {
|
||||
id: actionAbout
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<file alias="kilroy.png">resources/images/kilroy-256.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/fonts">
|
||||
<file alias="saucecodepro.ttf">resources/SauceCodeProNerdFont-Black.ttf</file>
|
||||
<file alias="saucecodepro-light.ttf">resources/SauceCodeProNerdFont-Light.ttf</file>
|
||||
<file alias="saucecodepro-xlight.ttf">resources/SauceCodeProNerdFont-ExtraLight.ttf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
BIN
resources/SauceCodeProNerdFont-Black.ttf
Normal file
BIN
resources/SauceCodeProNerdFont-Black.ttf
Normal file
Binary file not shown.
BIN
resources/SauceCodeProNerdFont-Light.ttf
Normal file
BIN
resources/SauceCodeProNerdFont-Light.ttf
Normal file
Binary file not shown.
@@ -4,9 +4,13 @@
|
||||
|
||||
use cxx_qt_lib::{QModelIndex, QString};
|
||||
use dirs;
|
||||
use libclide::error;
|
||||
use libclide::theme::highlighter::Highlighter;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use syntect::easy::HighlightLines;
|
||||
use syntect::highlighting::ThemeSet;
|
||||
use syntect::html::{IncludeBackground, append_highlighted_html_for_styled_line};
|
||||
use syntect::parsing::SyntaxSet;
|
||||
use syntect::util::LinesWithEndings;
|
||||
|
||||
#[cxx_qt::bridge]
|
||||
pub mod qobject {
|
||||
@@ -66,15 +70,49 @@ impl Default for FileSystemImpl {
|
||||
|
||||
impl qobject::FileSystem {
|
||||
fn read_file(&self, path: &QString) -> QString {
|
||||
let text = libclide::fs::read_file(path.to_string()).unwrap_or_else(|_| {
|
||||
error!(target: "qobject::FileSystem", "Failed to read file at path {path:?}");
|
||||
String::default()
|
||||
});
|
||||
if let Ok(highlighter) = Highlighter::new(path.to_string()) {
|
||||
QString::from(highlighter.syntax_highlight_text(text))
|
||||
if path.is_empty() {
|
||||
return QString::default();
|
||||
}
|
||||
let meta = fs::metadata(path.to_string())
|
||||
.unwrap_or_else(|_| panic!("Failed to get file metadata {path:?}"));
|
||||
if !meta.is_file() {
|
||||
libclide::warn!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file");
|
||||
return QString::default();
|
||||
}
|
||||
let path_str = path.to_string();
|
||||
if let Ok(lines) = fs::read_to_string(path_str.as_str()) {
|
||||
let ss = SyntaxSet::load_defaults_nonewlines();
|
||||
let ts = ThemeSet::load_defaults();
|
||||
let theme = &ts.themes["base16-ocean.dark"];
|
||||
let lang = ss
|
||||
.find_syntax_by_extension(
|
||||
Path::new(path_str.as_str())
|
||||
.extension()
|
||||
.map(|s| s.to_str())
|
||||
.unwrap_or_else(|| Some("md"))
|
||||
.expect("Failed to get file extension"),
|
||||
)
|
||||
.unwrap_or_else(|| ss.find_syntax_plain_text());
|
||||
let mut highlighter = HighlightLines::new(lang, theme);
|
||||
// If you care about the background, see `start_highlighted_html_snippet(theme);`.
|
||||
let mut output = String::from("<pre>\n");
|
||||
for line in LinesWithEndings::from(lines.as_str()) {
|
||||
let regions = highlighter
|
||||
.highlight_line(line, &ss)
|
||||
.expect("Failed to highlight");
|
||||
|
||||
append_highlighted_html_for_styled_line(
|
||||
®ions[..],
|
||||
IncludeBackground::No,
|
||||
&mut output,
|
||||
)
|
||||
.expect("Failed to insert highlighted html");
|
||||
}
|
||||
|
||||
output.push_str("</pre>\n");
|
||||
QString::from(output)
|
||||
} else {
|
||||
error!(target: "qobject::FileSystem", "Failed to create highlighter");
|
||||
QString::from(text)
|
||||
QString::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ mod menu_bar;
|
||||
|
||||
use crate::AppContext;
|
||||
use anyhow::{Context, Result};
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use log::LevelFilter;
|
||||
use ratatui::Terminal;
|
||||
use ratatui::backend::CrosstermBackend;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: GNU General Public License v3.0 or later
|
||||
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::{Constraint, Direction, Layout, Rect};
|
||||
use ratatui::text::{Line, Span};
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::tui::logger::Logger;
|
||||
use crate::tui::menu_bar::MenuBar;
|
||||
use anyhow::{Context, Result};
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use ratatui::DefaultTerminal;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::crossterm::event;
|
||||
@@ -42,7 +43,7 @@ pub struct App<'a> {
|
||||
|
||||
impl<'a> App<'a> {
|
||||
pub fn new(root_path: PathBuf) -> Result<Self> {
|
||||
libclide::trace!("Building {}", Self::ID);
|
||||
libclide::trace!("Building {}", <Self as Loggable>::ID);
|
||||
let app = Self {
|
||||
editor_tab: EditorTab::new(),
|
||||
explorer: Explorer::new(&root_path)?,
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
use crate::tui::component::Focus::Inactive;
|
||||
use Focus::Active;
|
||||
use anyhow::Result;
|
||||
use libclide::log::Loggable;
|
||||
use libclide::theme::colors::Colors;
|
||||
use libclide_macros::Loggable;
|
||||
use ratatui::crossterm::event::{Event, KeyEvent, MouseEvent};
|
||||
use ratatui::style::Color;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use edtui::{
|
||||
EditorEventHandler, EditorState, EditorTheme, EditorView, LineNumbers, Lines, SyntaxHighlighter,
|
||||
};
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
|
||||
use ratatui::layout::{Alignment, Rect};
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::tui::component::{Action, Component, Focus, FocusState};
|
||||
use crate::tui::editor::Editor;
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
|
||||
use ratatui::layout::Rect;
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::tui::component::{Action, Component, ComponentState, Focus, FocusState
|
||||
use anyhow::{Context, Result, bail};
|
||||
use libclide::fs::entry_meta::EntryMeta;
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, MouseEvent, MouseEventKind};
|
||||
use ratatui::layout::{Alignment, Position, Rect};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use crate::tui::component::{Action, Component, ComponentState, Focus, FocusState};
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use log::LevelFilter;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::crossterm::event::{Event, KeyCode, KeyEvent};
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::tui::menu_bar::MenuBarItemOption::{
|
||||
About, CloseTab, Exit, Reload, Save, ShowHideExplorer, ShowHideLogger,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use libclide::log::Loggable;
|
||||
use libclide_macros::Loggable;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::crossterm::event::{KeyCode, KeyEvent};
|
||||
use ratatui::layout::Rect;
|
||||
@@ -21,7 +21,6 @@ use strum::{EnumIter, FromRepr, IntoEnumIterator};
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr, EnumIter)]
|
||||
enum MenuBarItem {
|
||||
File,
|
||||
Edit,
|
||||
View,
|
||||
Help,
|
||||
}
|
||||
@@ -69,14 +68,12 @@ impl MenuBarItem {
|
||||
MenuBarItem::File => "File",
|
||||
MenuBarItem::View => "View",
|
||||
MenuBarItem::Help => "Help",
|
||||
MenuBarItem::Edit => "Edit",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn options(&self) -> &[MenuBarItemOption] {
|
||||
match self {
|
||||
MenuBarItem::File => &[Save, Reload, Exit],
|
||||
MenuBarItem::Edit => &[CloseTab],
|
||||
MenuBarItem::File => &[Save, CloseTab, Reload, Exit],
|
||||
MenuBarItem::View => &[ShowHideExplorer, ShowHideLogger],
|
||||
MenuBarItem::Help => &[About],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user