Merge branch 'main' into editor-fixes
continuous-integration/drone/pr Build is failing
Details
continuous-integration/drone/pr Build is failing
Details
This commit is contained in:
commit
564a243be2
21
.drone.yml
21
.drone.yml
|
@ -1,7 +1,11 @@
|
||||||
|
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: default
|
name: default
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
include:
|
||||||
|
- promote
|
||||||
|
- pull_request
|
||||||
steps:
|
steps:
|
||||||
- name: test
|
- name: test
|
||||||
image: rust:latest
|
image: rust:latest
|
||||||
|
@ -11,6 +15,10 @@ steps:
|
||||||
- rustup component add clippy
|
- rustup component add clippy
|
||||||
- cargo clippy
|
- cargo clippy
|
||||||
- cargo test --all
|
- cargo test --all
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
|
|
||||||
- name: deploy
|
- name: deploy
|
||||||
image: rust:latest
|
image: rust:latest
|
||||||
commands:
|
commands:
|
||||||
|
@ -32,7 +40,6 @@ steps:
|
||||||
- staging
|
- staging
|
||||||
- production
|
- production
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: windows-build
|
name: windows-build
|
||||||
|
@ -40,11 +47,19 @@ type: exec
|
||||||
platform:
|
platform:
|
||||||
os: windows
|
os: windows
|
||||||
arch: amd64
|
arch: amd64
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
include:
|
||||||
|
- promote
|
||||||
|
- pull_request
|
||||||
steps:
|
steps:
|
||||||
- name: test
|
- name: test
|
||||||
commands:
|
commands:
|
||||||
- rustup default stable
|
- rustup default stable
|
||||||
- cargo test
|
- cargo test
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
- name: deploy
|
- name: deploy
|
||||||
commands:
|
commands:
|
||||||
- rustup default stable
|
- rustup default stable
|
||||||
|
|
13
README.org
13
README.org
|
@ -52,9 +52,11 @@ cargo run
|
||||||
|
|
||||||
|
|
||||||
* Project Status
|
* Project Status
|
||||||
|
|
||||||
Abacus is currently in early development. It employs a custom built editor which can be slightly odd at times. A primary focus currently is improving the editing experience and adding additional scripting functionality.
|
Abacus is currently in early development. It employs a custom built editor which can be slightly odd at times. A primary focus currently is improving the editing experience and adding additional scripting functionality.
|
||||||
|
|
||||||
** Road map
|
** The road to 1.0
|
||||||
|
Features actively slated before a non beta release.
|
||||||
|
|
||||||
- +Editor basics+
|
- +Editor basics+
|
||||||
- +Scripting basics - Scripting functionality provided by extending the Rhai scripting language+
|
- +Scripting basics - Scripting functionality provided by extending the Rhai scripting language+
|
||||||
|
@ -63,7 +65,14 @@ Abacus is currently in early development. It employs a custom built editor which
|
||||||
- Editor improvements - Improve editor to mirror basic VIM functionality and fix text/cursor related bugs
|
- Editor improvements - Improve editor to mirror basic VIM functionality and fix text/cursor related bugs
|
||||||
- Math functions - Implement common mathmatical functions and constants into the scripting language
|
- Math functions - Implement common mathmatical functions and constants into the scripting language
|
||||||
- Dataframe performance - Reduce the performance cost of converting from the scripting engine to polars
|
- Dataframe performance - Reduce the performance cost of converting from the scripting engine to polars
|
||||||
- Web/JSON support - Add HTTP requesting functionality and JSON parsing/processing to the scripting engine
|
|
||||||
|
** Beyond
|
||||||
|
Features and improvements that would be nice to implement, but are not being actively persued yet.
|
||||||
|
|
||||||
|
- Web/JSON support - Add HTTP requesting functionality and JSON parsing/processing to the scripting engine
|
||||||
|
- Function plotting implemented in scripting and output rendering
|
||||||
|
- Charts and Graphs implemented in scripting and output rendering
|
||||||
|
- User provided module importing
|
||||||
|
|
||||||
|
|
||||||
* Shoulders of giants
|
* Shoulders of giants
|
||||||
|
|
|
@ -619,7 +619,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
pub fn series_index() {
|
pub fn series_index() {
|
||||||
let s = process(r#"series("ages", [18, 21, 25, 35]).sort(true)[1]"#).into_scalar();
|
let s = process(r#"series("ages", [18, 21, 25, 35]).sort(true)[1]"#).into_scalar();
|
||||||
assert_eq!(s.cast::<i64>(), 25);
|
assert_eq!(s, "25");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::dataframe;
|
use crate::dataframe;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -34,7 +36,7 @@ impl<'a> Engine<'a> {
|
||||||
let series = rhai::Dynamic::cast::<dataframe::Series>(res);
|
let series = rhai::Dynamic::cast::<dataframe::Series>(res);
|
||||||
Output::Series(series)
|
Output::Series(series)
|
||||||
}
|
}
|
||||||
Ok(res) => Output::Scalar(res),
|
Ok(res) => Output::Scalar(res.to_string()),
|
||||||
Err(e) => Output::Error(e.to_string()),
|
Err(e) => Output::Error(e.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +45,7 @@ impl<'a> Engine<'a> {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Output {
|
pub enum Output {
|
||||||
None,
|
None,
|
||||||
Scalar(rhai::Dynamic),
|
Scalar(String),
|
||||||
DataFrame(dataframe::DataFrame),
|
DataFrame(dataframe::DataFrame),
|
||||||
Series(dataframe::Series),
|
Series(dataframe::Series),
|
||||||
Error(String),
|
Error(String),
|
||||||
|
@ -80,7 +82,7 @@ impl Output {
|
||||||
}
|
}
|
||||||
panic!("Not a series");
|
panic!("Not a series");
|
||||||
}
|
}
|
||||||
pub fn into_scalar(self) -> rhai::Dynamic {
|
pub fn into_scalar(self) -> String {
|
||||||
if let Self::Scalar(v) = self {
|
if let Self::Scalar(v) = self {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use druid::AppDelegate;
|
use abacus_core::Engine;
|
||||||
|
use druid::{AppDelegate, Target};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
commands,
|
commands,
|
||||||
|
@ -10,7 +11,7 @@ pub struct Delegate;
|
||||||
impl AppDelegate<AppData> for Delegate {
|
impl AppDelegate<AppData> for Delegate {
|
||||||
fn command(
|
fn command(
|
||||||
&mut self,
|
&mut self,
|
||||||
_ctx: &mut druid::DelegateCtx,
|
ctx: &mut druid::DelegateCtx,
|
||||||
_target: druid::Target,
|
_target: druid::Target,
|
||||||
cmd: &druid::Command,
|
cmd: &druid::Command,
|
||||||
data: &mut AppData,
|
data: &mut AppData,
|
||||||
|
@ -43,13 +44,59 @@ impl AppDelegate<AppData> for Delegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.is(commands::PROCESS_WORKBOOK) {
|
if cmd.is(commands::PROCESS_WORKBOOK) {
|
||||||
data.process();
|
let scripts = data
|
||||||
|
.blocks
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, b)| (idx, b.editor_data.content.to_string()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let sink = ctx.get_external_handle();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
for (idx, script) in scripts.iter() {
|
||||||
|
let mut engine = Engine::default();
|
||||||
|
let output = engine.process_script(script);
|
||||||
|
let _ = sink.submit_command(
|
||||||
|
crate::commands::BLOCK_PROCESSED,
|
||||||
|
(*idx, output),
|
||||||
|
Target::Auto,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return druid::Handled::Yes;
|
return druid::Handled::Yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.is(commands::PROCESS_BLOCK) {
|
if cmd.is(commands::PROCESS_BLOCK) {
|
||||||
if let Some(index) = cmd.get(commands::PROCESS_BLOCK) {
|
if let Some(index) = cmd.get(commands::PROCESS_BLOCK) {
|
||||||
data.process_block(*index);
|
let index = *index;
|
||||||
|
let script = data
|
||||||
|
.blocks
|
||||||
|
.get(index)
|
||||||
|
.map(|b| b.editor_data.content.to_string());
|
||||||
|
|
||||||
|
if let Some(script) = script {
|
||||||
|
let sink = ctx.get_external_handle();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let mut engine = Engine::default();
|
||||||
|
let output = engine.process_script(&script);
|
||||||
|
let _ = sink.submit_command(
|
||||||
|
crate::commands::BLOCK_PROCESSED,
|
||||||
|
(index, output),
|
||||||
|
Target::Auto,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return druid::Handled::Yes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.is(commands::BLOCK_PROCESSED) {
|
||||||
|
if let Some((idx, output)) = cmd.get(commands::BLOCK_PROCESSED) {
|
||||||
|
if let Some(block) = data.blocks.get_mut(*idx) {
|
||||||
|
block.output = output.clone();
|
||||||
|
}
|
||||||
return druid::Handled::Yes;
|
return druid::Handled::Yes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,9 @@ pub fn app_header_ui() -> impl Widget<AppData> {
|
||||||
.with_child(
|
.with_child(
|
||||||
Container::new(Padding::new(10.0, Svg::new(run_svg).fix_width(10.0)))
|
Container::new(Padding::new(10.0, Svg::new(run_svg).fix_width(10.0)))
|
||||||
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
|
.controller(ToolbarButtonController::new(Color::rgb8(50, 50, 50)))
|
||||||
.on_click(|_ctx, data: &mut AppData, _env| data.process()),
|
.on_click(|ctx, _data: &mut AppData, _env| {
|
||||||
|
ctx.submit_command(crate::commands::PROCESS_WORKBOOK);
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.with_spacer(20.0)
|
.with_spacer(20.0)
|
||||||
.expand_width(),
|
.expand_width(),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use abacus_core::Output;
|
||||||
use druid::Selector;
|
use druid::Selector;
|
||||||
|
|
||||||
pub const PROCESS_WORKBOOK: Selector<()> = Selector::new("process-workbook");
|
pub const PROCESS_WORKBOOK: Selector<()> = Selector::new("process-workbook");
|
||||||
|
@ -7,3 +8,5 @@ pub const DELETE_BLOCK: Selector<usize> = Selector::new("delete-block");
|
||||||
pub const RENAME_BLOCK: Selector<usize> = Selector::new("rename-block");
|
pub const RENAME_BLOCK: Selector<usize> = Selector::new("rename-block");
|
||||||
|
|
||||||
pub const CLOSE_MODAL: Selector<()> = Selector::new("close-modal");
|
pub const CLOSE_MODAL: Selector<()> = Selector::new("close-modal");
|
||||||
|
|
||||||
|
pub const BLOCK_PROCESSED: Selector<(usize, Output)> = Selector::new("block-processed");
|
||||||
|
|
|
@ -12,26 +12,18 @@ pub fn output_block() -> impl Widget<Block> {
|
||||||
ViewSwitcher::new(
|
ViewSwitcher::new(
|
||||||
|data: &Block, _env| data.clone(),
|
|data: &Block, _env| data.clone(),
|
||||||
|selector: &Block, _data, _env| match &selector.output {
|
|selector: &Block, _data, _env| match &selector.output {
|
||||||
Output::Scalar(v) => {
|
Output::Scalar(str) => Box::new(Padding::new(
|
||||||
let str = match v {
|
25.0,
|
||||||
_ if v.is::<String>() => v.clone().cast::<String>(),
|
Label::new(str.clone())
|
||||||
_ if v.is::<&str>() => v.clone().cast::<&str>().to_string(),
|
.with_font(
|
||||||
v => v.to_string(),
|
FontDescriptor::new(FontFamily::MONOSPACE).with_weight(FontWeight::BOLD),
|
||||||
};
|
)
|
||||||
Box::new(Padding::new(
|
.with_text_size(OUTPUT_FONT_SIZE)
|
||||||
25.0,
|
.padding(10.0)
|
||||||
Label::new(str)
|
.background(Color::rgb8(30, 30, 30))
|
||||||
.with_font(
|
.rounded(4.0)
|
||||||
FontDescriptor::new(FontFamily::MONOSPACE)
|
.expand_width(),
|
||||||
.with_weight(FontWeight::BOLD),
|
)),
|
||||||
)
|
|
||||||
.with_text_size(OUTPUT_FONT_SIZE)
|
|
||||||
.padding(10.0)
|
|
||||||
.background(Color::rgb8(30, 30, 30))
|
|
||||||
.rounded(4.0)
|
|
||||||
.expand_width(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Output::Error(e) => Box::new(Padding::new(
|
Output::Error(e) => Box::new(Padding::new(
|
||||||
25.0,
|
25.0,
|
||||||
Label::new(e.to_string())
|
Label::new(e.to_string())
|
||||||
|
@ -87,7 +79,7 @@ pub fn output_block() -> impl Widget<Block> {
|
||||||
.background(Color::rgb8(40, 40, 40)),
|
.background(Color::rgb8(40, 40, 40)),
|
||||||
);
|
);
|
||||||
|
|
||||||
for v in series.iter() {
|
for v in series.iter().take(20) {
|
||||||
col.add_child(
|
col.add_child(
|
||||||
Label::new(format_dataframe_value(v))
|
Label::new(format_dataframe_value(v))
|
||||||
.with_font(
|
.with_font(
|
||||||
|
|
Loading…
Reference in New Issue