64 Commits

Author SHA1 Message Date
937b45e3b0 Merged v1.1.6 2023-10-15 11:30:48 -07:00
7726eea34d Updated nix derivation 2023-10-15 11:30:09 -07:00
6fd315a9fe Version bump 2023-10-15 11:29:19 -07:00
0d81d58370 Fixed subtract unit check 2023-10-15 11:26:54 -07:00
2ff42bf62a Added unit checks to temp conversions 2023-10-15 11:26:45 -07:00
b5a23f814f Fixed colors 2023-10-15 11:26:15 -07:00
e3e23a686d Fixed del ans 2023-10-15 11:26:08 -07:00
93c34ca4a4 Updated docs 2023-10-15 11:25:19 -07:00
80f17ac210 Whitespace 2023-10-15 09:30:32 -07:00
3c8ed9f4f3 Added documentation 2023-10-14 09:43:48 -07:00
27ea64e172 Merge branch 'dev' 2023-10-14 09:37:06 -07:00
b7a6378589 Fixed default.nix 2023-10-14 09:36:25 -07:00
d6f1ce0442 Merge minor chagnes from 'dev' 2023-10-14 09:21:01 -07:00
5e34017225 Added nix package 2023-10-14 09:13:54 -07:00
d9730fd699 Added contrib guide 2023-09-29 10:18:10 -07:00
5788ffa085 Updated TODO 2023-09-29 10:17:54 -07:00
a75f6197cd Merge pull request #11 from rm-dr/dev
Version bump to v1.1.5
2023-09-28 13:38:21 -07:00
2f2c005c86 Version bump 2023-09-28 13:32:34 -07:00
ffebcf2e15 Merge branch 'master' into dev 2023-09-28 13:30:08 -07:00
4e1df2399b Merge pull request #10 from bojohnson5/testing
fix electron mass
2023-09-28 13:29:23 -07:00
5a921cfc7b fix electron mass 2023-09-28 14:35:16 -04:00
2531524ffd Updated makefile 2023-09-22 11:22:36 -07:00
e5525adcca Updated todo 2023-09-22 11:05:58 -07:00
a61cbf29e5 Makefile edits 2023-09-22 11:05:30 -07:00
39ab47530e Merge pull request #9 from rm-dr/dev
Merge v1.1.4
2023-09-22 11:01:55 -07:00
be28669416 Sync with master 2023-09-22 11:00:28 -07:00
7658ff76ef Version bump 2023-09-22 10:59:35 -07:00
e9d392b80b Fixed linelocation inside user functions 2023-09-22 10:58:51 -07:00
63d4a01095 Merge pull request #8 from rm-dr/dev
Merge v1.1.3
2023-09-22 10:48:59 -07:00
6a025cbf1a Version bump 2023-09-22 10:47:38 -07:00
8a6c623ef2 Updated TODO 2023-09-22 10:47:25 -07:00
a1db2b6bb0 Fixed space key 2023-09-22 10:46:01 -07:00
c2d3e613d4 Added mobile warning 2023-09-22 10:41:01 -07:00
96a34dc05d Added makefile 2023-09-22 10:26:46 -07:00
42fdcd5853 Minor cleanup 2023-09-22 10:26:37 -07:00
cffb3726cc Character checks, minor cleanup 2023-09-22 10:08:28 -07:00
ef74b67f90 Moved server files to /server 2023-09-22 10:08:10 -07:00
32463ad6aa Updated shell.nix 2023-09-21 20:52:35 -07:00
413c34c440 Merge branch 'dev' of github.com:rm-dr/daisy into dev 2023-09-21 20:47:39 -07:00
a1d190b06e Updated TODO 2023-09-21 19:54:37 -07:00
178708a4ac Updated TODO 2023-09-21 19:52:48 -07:00
5bb8e2c4ce Merge 1.0.2 (#7)
* Fixed page scrolling

* Updated TODO

* Fixed a link

* Minor edits

* Version bump
2023-09-21 19:50:52 -07:00
49b88af2bb Version bump 2023-09-21 19:49:31 -07:00
a0fe0a9385 Minor edits 2023-09-21 19:49:12 -07:00
7215afcc7e Fixed a link 2023-09-21 19:43:40 -07:00
3ab559b240 Updated TODO 2023-09-21 19:43:00 -07:00
810e2a1267 Fixed page scrolling 2023-09-21 19:42:53 -07:00
798c9ceae9 Merge pull request #6 from rm-dr/dev
Merge v1.1.1
2023-09-21 19:37:34 -07:00
572158553c Version bump 2023-09-21 19:35:00 -07:00
f7602a3011 Merge branch 'wasm' into dev 2023-09-21 19:33:01 -07:00
f5b2c5b261 Minor cleanup 2023-09-21 19:32:44 -07:00
0559e84444 Added docker compose 2023-09-21 19:24:00 -07:00
8dea7e2e8c Comments 2023-09-21 19:21:07 -07:00
bcef2c7403 Added basic dockerfile for webserver 2023-09-21 19:16:43 -07:00
fb22243104 Minor cleanup 2023-09-21 19:16:30 -07:00
3fd489dd7e Added doctype 2023-09-21 14:12:10 -07:00
fc2027c657 Enabled wasm optimizations 2023-09-21 14:12:04 -07:00
a70fd5f0e5 Cleaned up site files 2023-09-21 14:07:21 -07:00
161f184437 Updated help text 2023-09-21 13:53:46 -07:00
599c9742d2 Added a few more commands and arguments 2023-09-21 12:50:16 -07:00
9f9cc5d084 Added character limits 2023-09-21 12:35:59 -07:00
c8ebec59ae Renamed --debug to --info 2023-09-20 14:25:10 -07:00
bab305e11d Merge pull request #4 from rm-dr/dev
Merge 1.1.0
2023-09-20 11:19:34 -07:00
a6c3ffa68d Merge v1.0.1 2023-08-17 10:30:26 -07:00
31 changed files with 641 additions and 77 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
/target
/src/target
/pkg
*.pkg.*
/result

36
CONTRIBUTING.MD Normal file
View File

@ -0,0 +1,36 @@
# Contribution guidelines for Daisy
## Pull requests
All PRs should merge to `dev`. See "branching" below.
## Versioning
Daisy uses [semantic versioning](https://semver.org/), which looks like `maj.min.patch`. In short:
- `maj`: Incremented on large, incompatible changes
- `min`: Incremented on new features
- `patch`: Incremented on bugfixes
Whenever one of the above fields is incremented, all sub-fields are reset to zero. When `min` is incremented, `patch` is set to zero.
## Branching
Daisy uses a branch model much like the one described [here](https://nvie.com/posts/a-successful-git-branching-model).
- `master`: 1 commit = 1 release. This is always a merge comit from `dev`, and is always tagged with a version.
- `dev`: main development branch. Never deleted. Most work happens here.
- `features`: temporary branches pulled from `dev` and merged to `dev` for larger features.
- Always merge with git's `--no-ff` option for a more detailed history.
## Releases
What to do
- Merge into `master` (`git merge --no-ff dev`)
- Tag merge commit on `master` (`git tag -a v1.0.0 -m "Version 1.0.0"`)
- `cargo publish`
- Update web demo & pull server (`make docker`)
- Update aur package
Test `default.nix` with
``sh
nix-build -E 'let pkgs = import <nixpkgs> { }; in pkgs.callPackage ./default.nix {}'
``

2
Cargo.lock generated
View File

@ -28,7 +28,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "daisycalc"
version = "1.1.0"
version = "1.1.6"
dependencies = [
"cfg-if",
"num",

View File

@ -1,6 +1,6 @@
[package]
name = "daisycalc"
version = "1.1.0"
version = "1.1.6"
edition = "2021"
build = "buildscript/main.rs"
license = "GPL-3.0-only"
@ -34,8 +34,7 @@ num = "0.4.1"
#astro-float = "0.7.1"
[package.metadata.wasm-pack.profile.release]
# wasm-opt doesn't work, need to figure out why
wasm-opt = false
wasm-opt = true
[target.'cfg(target_family = "unix")'.dependencies]
termion = "2.0.1"

19
Makefile Normal file
View File

@ -0,0 +1,19 @@
release:
cargo build --release
test:
cargo test
run:
cargo run
wasm:
wasm-pack build --release --target web --out-dir server/pkg
publish:
cargo test
cargo publish
docker: wasm
docker build ./server -t git.betalupi.com/mark/daisy --no-cache
docker push git.betalupi.com/mark/daisy

View File

@ -1,17 +1,31 @@
![](./misc/banner.png)
![](./server/site/resources/readme-banner.png)
A high-precision scientific calculator with support for units, derivatives, and more.
Many features are missing, this is still under development.
**Web demo: [here](https://daisy.betalupi.com) (won't work on mobile)**
# 📦 Installation
- **From source:** `cargo build --release`, binary will be at `./target/release/daisy`
- **Cargo:** `cargo install daisycalc`
- **Arch:** `yay -S daisy`
- **Debian:** coming soon
- **Nix:** Use `default.nix`. Daisy isn't in nixpkgs yet, you'll need to add something like the following to `configuration.nix`:
From source: `cargo build --release` \
Binary will be in `target/release/daisy`
```nix
let
daisy = builtins.fetchGit {
url = "https://github.com/rm-dr/daisy.git";
ref = "master";
} + /default.nix;
in
{
environment.systemPackages = with pkgs; [
(callPackage daisy { })
];
}
```
# 📹 Screenshot
@ -20,7 +34,7 @@ Binary will be in `target/release/daisy`
# 🛠️ Features
- Open-source
- Extremely high precision
- Uses a rational datatype when possible, and a high-precision float when not.
- Uses a rational datatype when possible, and a high-precision float when not.
- Pretty printing in prompt (with special substitutions)
- Supports many physical units, with metric and binary prefixes
- Supports exponential notation

36
TODO.md
View File

@ -1,55 +1,33 @@
## Version Bump checklist
- TODO: build and publish script
- update Cargo.toml
- run cargo test
- commit
- push
- merge
- git tag -a v1.0.0 -m "Version 1.0.0" on merge commit
- cargo publish
- Update packages
## Pre-release
- Tuple operations
- we don't need vectors as arguments to operators
- Fix linelocation when evaluating functions
## Parser
- Should functions be operators?
- Binary, hex, octal numbers
## General
- Better tests (assignment, many expressions in one context)
- Optional config file
- Optional history file
- Compile to WASM, publish a webapp
- evaluate straight from command line
- Package for debian, nix
## Internals
- Non-recursive treeify
- Faster factorial function. Maybe use gamma instead?
- Arbitrary precision float (rug doesn't offer arbitrary exponents)
- Arbitrary precision floats
- we don't need vectors as arguments to operators
## Math Features
- Mean, Median, Min
- Arbitrary base logarithm
- Derivatives
- CAS features (trig, roots and powers)
- Complex numbers
- acot/acoth functions
- Sums and products with functional arguments
- Add functions: gcd, inverse mod, dice
- Tuple operations
- Number theory: select a group, inverses, etc
- Negative mod
## Prompt
- Fix terminal color detection
- Live syntax/output (like firefox js terminal)
- Syntax highlighting
- fish-style tab completion
- Numbered expressions, history recall
- Numbered history recall
- Enable/disable unit sets (defaults?)
- Consistent unit ordering
@ -57,5 +35,5 @@
- long prefixes (megatonne, etc)
- HMS for degrees
- Exact radians, using pi constant?
- Weird units: flops, lumen, lux, bel
- Odd units: flops, lumen, lux, bel
- Command to list units

View File

@ -49,7 +49,7 @@ value = "1.602176634e-19 C"
enum_name = "ElectronMass"
pretty_name = "Electron mass"
strings = ["electronmass"]
value = "9.1093837015-31 kg"
value = "9.1093837015e-31 kg"
[[constant]]
enum_name = "ProtonMass"
@ -205,4 +205,4 @@ value = "TW * hour"
[[constant]]
enum_name = "PWH"
strings = "PWh"
value = "PW * hour"
value = "PW * hour"

19
default.nix Normal file
View File

@ -0,0 +1,19 @@
{ lib, fetchgit, rustPlatform }:
rustPlatform.buildRustPackage rec {
pname = "daisy";
version = "1.1.6";
cargoLock.lockFile = src + /Cargo.lock;
src = fetchgit {
url = "https://github.com/rm-dr/daisy.git";
rev = "v${version}";
sha256 = "";
};
meta = with lib; {
description = "A pretty command-line scientific calculator";
homepage = "https://github.com/rm-dr/daisy";
#license = licenses.GPL;
maintainers = [ maintainers.tailhook ];
};
}

2
server/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/site/node_modules
/pkg

14
server/Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM ubuntu AS node
RUN apt-get update
RUN apt-get install cargo npm -y
COPY ./site ./site
RUN cd /site && npm install
FROM ubuntu
RUN apt-get update
RUN apt-get install nginx -y
COPY --from=node /site /var/www/html
COPY ./pkg /var/www/html/pkg
COPY default /etc/nginx/sites-enabled/default
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

31
server/default Normal file
View File

@ -0,0 +1,31 @@
types {
application/wasm wasm;
application/x-font-ttf ttc;
application/x-font-otf otf;
application/font-woff2 woff2;
font/ttf ttf;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location ~* .(js|css|ttf|ttc|otf|eot|woff|woff2)$ {
add_header access-control-allow-origin "*";
expires max;
}
}

18
server/docker-compose.yml Normal file
View File

@ -0,0 +1,18 @@
version: "3"
# You'll need to edit this file if you want to use it.
networks:
reverse_proxy:
external: true
services:
daisy:
build: .
container_name: daisy
restart: unless-stopped
networks:
- reverse_proxy
#ports:
# - "80:80"

View File

@ -1,13 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title>Daisy Web</title>
<link rel="icon" href="resources/daisy-icon-light.svg" sizes="any" type="image/svg+xml">
<link rel="preload" href="resources/Fantasque.ttf" as="font" type="font/ttf" crossorigin>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
<link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
<link rel="stylesheet" href="xterm.css">
<script src="node_modules/xterm/lib/xterm.js"></script>
<style>
@font-face {
font-family: Fantasque;
src: url("FantasqueSansMono/Regular/complete/Fantasque Sans Mono Regular Nerd Font Complete.ttf") format("opentype");
src: url("resources/Fantasque.ttf") format("opentype");
}
html, body {
@ -18,7 +22,6 @@
margin: 0;
padding: 0;
overflow: hidden;
height: 100vh;
}
@ -53,7 +56,7 @@
box-sizing: box;
border: 0mm;
box-shadow: 0px 0px 10px 4px #4d5257;
box-shadow: 0px 0px 10px 4px #3c4044;
}
#header {
@ -82,7 +85,7 @@
<body>
<div id="header">
<img id="banner" src = "misc/daisy-light.svg" alt="Daisy Banner"/>
<img id="banner" src = "resources/daisy-light.svg" alt="Daisy Banner"/>
<p>A high-precision, general-purpose scientific calculator</p>
</div>
@ -97,10 +100,14 @@
<a href="https://aur.archlinux.org/packages/daisy" target="_blank" rel="noopener noreferrer">AUR</a>
</div>
<script>
var mobile = (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase()));
if (mobile) { alert("This site may not work on mobile."); }
</script>
<script type="module">
// See wasm-pack docs
// Build with `wasm-pack build --release --target web`
// Works with wasm-pack 0.9.1. Some other versions give a segfault.
// Build with `wasm-pack build --release --target web --out-dir pkg`
import init, { daisy_init, daisy_free, daisy_char, daisy_prompt } from './pkg/daisycalc.js';
await init();

17
server/site/package-lock.json generated Normal file
View File

@ -0,0 +1,17 @@
{
"name": "site",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"xterm": "^5.3.0"
}
},
"node_modules/xterm": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz",
"integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg=="
}
}
}

5
server/site/package.json Normal file
View File

@ -0,0 +1,5 @@
{
"dependencies": {
"xterm": "^5.3.0"
}
}

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="391.21191"
height="383.02271"
viewBox="0 0 103.50814 101.34143"
version="1.1"
id="svg3246"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
sodipodi:docname="daisy-icon-dark.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview3248"
pagecolor="#9e9e9e"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="true"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="false"
showborder="true"
borderlayer="false"
shape-rendering="auto"
inkscape:zoom="0.19458888"
inkscape:cx="881.34533"
inkscape:cy="-418.83174"
inkscape:window-width="1280"
inkscape:window-height="1384"
inkscape:window-x="1280"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" /><defs
id="defs3243"><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-9-6" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-0" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-9" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-0-3" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-9" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-2" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-2-2" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-8" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-3" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-27" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-7" /></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-18.308946,-133.59209)"><g
id="g1657-2-9"
transform="matrix(4.4337012,0,0,4.4337012,-486.12826,763.96674)"
style="stroke:#a60d66;stroke-opacity:1"><g
id="g2349-6-0-3"
style="stroke:#ea004d;stroke-opacity:1"
transform="translate(102.69737,-168.67264)"><path
style="fill:none;fill-opacity:1;stroke:#ea004d;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 26.115101,47.660493 c 1.853776,0.96137 4.1474,0.53544 5.680504,-1.05487 1.410359,-1.46298 1.804214,-3.05883 1.179203,-4.77799 -0.966718,-2.6591 -3.720953,-3.9058 -8.552213,-3.87115 l -1.673694,0.012 0.11351,2.11848 c 0.142919,2.66699 0.428255,4.15648 1.018046,5.31437 0.567689,1.11447 1.136825,1.68985 2.234644,2.25917 z"
id="path302-3-1-7-2-9-7-6-6"
sodipodi:nodetypes="sssscsss" /><path
style="fill:none;fill-opacity:1;stroke:#ea004d;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 12.940109,34.959413 c -1.028597,-1.81733 -0.686937,-4.12501 0.846167,-5.71532 1.410353,-1.46298 2.990719,-1.915 4.731608,-1.35336 2.692707,0.86871 4.039427,3.57545 4.181707,8.40473 l 0.04931,1.67302 -2.121224,-0.0359 c -2.670426,-0.0452 -4.169372,-0.27577 -5.348089,-0.82278 -1.134496,-0.5265 -1.730333,-1.07418 -2.339471,-2.15042 z"
id="path302-3-1-2-0-0-8-5-8-0"
sodipodi:nodetypes="sssscsss" /></g><g
id="g1649-9-62"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1"
transform="translate(-22.721851,-0.67464498)"><path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 144.80192,-120.3375 c -1.85377,0.96136 -4.1474,0.53544 -5.6805,-1.05487 -1.41036,-1.46298 -1.80422,-3.05883 -1.1792,-4.77799 0.96671,-2.6591 3.72095,-3.9058 8.55221,-3.87116 l 1.67369,0.012 -0.11351,2.11849 c -0.14291,2.66698 -0.42825,4.15648 -1.01805,5.31437 -0.56768,1.11446 -1.13682,1.68985 -2.23464,2.25917 z"
id="path302-3-1-7-6-6-8-3-2-6"
sodipodi:nodetypes="sssscsss" /><path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 157.9769,-133.03859 c 1.0286,-1.81733 0.68693,-4.12501 -0.84616,-5.71532 -1.41036,-1.46298 -2.99072,-1.915 -4.73161,-1.35336 -2.69271,0.86871 -4.03943,3.57545 -4.18171,8.40473 l -0.0493,1.67302 2.12122,-0.0359 c 2.67043,-0.0452 4.16938,-0.27577 5.34809,-0.82278 1.1345,-0.5265 1.73033,-1.07418 2.33947,-2.15042 z"
id="path302-3-1-2-0-2-8-0-5-6-1"
sodipodi:nodetypes="sssscsss" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="391.21191"
height="383.02271"
viewBox="0 0 103.50814 101.34143"
version="1.1"
id="svg3246"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
sodipodi:docname="daisy-icon-light.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview3248"
pagecolor="#9e9e9e"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="true"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="false"
showborder="true"
borderlayer="false"
shape-rendering="auto"
inkscape:zoom="1.3137864"
inkscape:cx="280.48699"
inkscape:cy="34.632722"
inkscape:window-width="1280"
inkscape:window-height="1384"
inkscape:window-x="1280"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="g1649-9-62" /><defs
id="defs3243"><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-9-6" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-0" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-9" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-0-3" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-9" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-2" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-2-2" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-8" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-3" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-27" /><rect
x="567.45734"
y="347.68021"
width="408.88004"
height="160.23911"
id="rect2101-9-8-3-8-7" /></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-18.308946,-133.59209)"><g
id="g1657-2-9"
transform="matrix(4.4337012,0,0,4.4337012,-486.12826,763.96674)"
style="stroke:#a60d66;stroke-opacity:1"><g
id="g2349-6-0-3"
style="stroke:#ea004d;stroke-opacity:1"
transform="translate(102.69737,-168.67264)"><path
style="fill:none;fill-opacity:1;stroke:#ea004d;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 26.115101,47.660493 c 1.853776,0.96137 4.1474,0.53544 5.680504,-1.05487 1.410359,-1.46298 1.804214,-3.05883 1.179203,-4.77799 -0.966718,-2.6591 -3.720953,-3.9058 -8.552213,-3.87115 l -1.673694,0.012 0.11351,2.11848 c 0.142919,2.66699 0.428255,4.15648 1.018046,5.31437 0.567689,1.11447 1.136825,1.68985 2.234644,2.25917 z"
id="path302-3-1-7-2-9-7-6-6"
sodipodi:nodetypes="sssscsss" /><path
style="fill:none;fill-opacity:1;stroke:#ea004d;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 12.940109,34.959413 c -1.028597,-1.81733 -0.686937,-4.12501 0.846167,-5.71532 1.410353,-1.46298 2.990719,-1.915 4.731608,-1.35336 2.692707,0.86871 4.039427,3.57545 4.181707,8.40473 l 0.04931,1.67302 -2.121224,-0.0359 c -2.670426,-0.0452 -4.169372,-0.27577 -5.348089,-0.82278 -1.134496,-0.5265 -1.730333,-1.07418 -2.339471,-2.15042 z"
id="path302-3-1-2-0-0-8-5-8-0"
sodipodi:nodetypes="sssscsss" /></g><g
id="g1649-9-62"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1"
transform="translate(-22.721851,-0.67464498)"><path
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 144.80192,-120.3375 c -1.85377,0.96136 -4.1474,0.53544 -5.6805,-1.05487 -1.41036,-1.46298 -1.80422,-3.05883 -1.1792,-4.77799 0.96671,-2.6591 3.72095,-3.9058 8.55221,-3.87116 l 1.67369,0.012 -0.11351,2.11849 c -0.14291,2.66698 -0.42825,4.15648 -1.01805,5.31437 -0.56768,1.11446 -1.13682,1.68985 -2.23464,2.25917 z"
id="path302-3-1-7-6-6-8-3-2-6"
sodipodi:nodetypes="sssscsss" /><path
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.37083;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1"
d="m 157.9769,-133.03859 c 1.0286,-1.81733 0.68693,-4.12501 -0.84616,-5.71532 -1.41036,-1.46298 -2.99072,-1.915 -4.73161,-1.35336 -2.69271,0.86871 -4.03943,3.57545 -4.18171,8.40473 l -0.0493,1.67302 2.12122,-0.0359 c 2.67043,-0.0452 4.16938,-0.27577 5.34809,-0.82278 1.1345,-0.5265 1.73033,-1.07418 2.33947,-2.15042 z"
id="path302-3-1-2-0-2-8-0-5-6-1"
sodipodi:nodetypes="sssscsss" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -1,11 +1,22 @@
{ nixpkgs ? import <nixpkgs> { }}:
let
pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/f155f0cf4ea43c4e3c8918d2d327d44777b6cad4.tar.gz") {};
# If you set hash to an empty string, you'll get
# an error with the correct hash.
pinnedPkgs = nixpkgs.fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
rev = "4ecab3273592f27479a583fb6d975d4aba3486fe";
sha256 = "btHN1czJ6rzteeCuE/PNrdssqYD2nIA4w48miQAFloM=";
};
pkgs = import pinnedPkgs {};
in pkgs.mkShell {
buildInputs = with pkgs; [
cargo
rustc
rustfmt
m4
rust-analyzer
wasm-pack
];
}

View File

@ -16,6 +16,7 @@ pub fn is_command(
| "vars"
| "consts" | "constants"
| "del" | "delete"
| "flags"
=> true,
_ => false
}
@ -66,6 +67,7 @@ pub fn do_command(
"\n",
"╞═══════════════ [t]Commands[n] ═══════════════╡\n",
" [c]help[n] Show this help\n",
" [c]flags[n] Show command-line options\n",
" [c]clear[n] Clear the terminal\n",
" [c]quit[n] Exit daisy\n",
//" [c]units[n] List available units\n",
@ -81,6 +83,27 @@ pub fn do_command(
return t;
},
"flags" => {
return FormattedText::new(
concat!(
"\n",
"A list of command-line arguments is below\n",
"\n",
"╞════ [t]Flag[n] ════╪════════════════ [t]Function[n] ════════════════╡\n",
" [c]--help[n] Show help\n",
" [c]--version[n] Show version\n",
" [c]--info[n] Show system information\n",
" [c]--256color[n] Use full color support (default)\n",
" [c]--8color[n] Use reduced colors (ANSI, no styling)\n",
" [c]--nocolor[n] Do not use colors and styling\n",
" [c]--nosub[n] Disable inline substitution\n",
" [c]--nosuper[n] Disable superscript powers\n",
" [c]--nooneover[n] Disable \"one-over\" fractions as -1 power\n",
"\n\n"
).to_string()
);
},
"clear" => {
return FormattedText::new("[clear]".to_string());
},
@ -224,7 +247,7 @@ pub fn do_command(
if args.len() != 2 {
return FormattedText::new(
format!(
"[c]{first}[n] [t]takes exactly one argument.[n]\n\n",
"[c]{first}[n] [e]takes exactly one argument.[n]\n\n",
)
);
}
@ -238,7 +261,7 @@ pub fn do_command(
Err(()) => {
FormattedText::new(
format!(
"[c]{v}[n] [t]isn't a variable.[n]\n\n",
"[c]{v}[n] [e]isn't a variable.[n]\n\n",
)
)
}

View File

@ -90,6 +90,7 @@ impl Context {
pub fn delete(&mut self, s: &String) -> Result<(), ()> {
if !(self.is_varible(s) || self.is_function(s)) { return Err(()) };
if s == "ans" { return Err(()) };
if self.is_varible(s) { self.variables.remove(s); }
if self.is_function(s) { self.functions.remove(s); }
return Ok(());

View File

@ -63,7 +63,7 @@ pub fn evaluate(
context.get_variable(&s)
},
Expression::Operator(_, Operator::Function(_), _) => { eval_function(g)? },
Expression::Operator(_, Operator::Function(_), _) => { eval_function(context, g)? },
Expression::Operator(_, _, _) => { eval_operator(context, g)? },
};

View File

@ -3,11 +3,12 @@ use crate::parser::Function;
use crate::parser::Operator;
use crate::parser::LineLocation;
use crate::quantity::FreeUnit;
use crate::quantity::Unit;
use crate::quantity::WholeUnit;
use crate::quantity::Quantity;
use crate::quantity::Scalar;
use crate::errors::DaisyError;
use crate::context::Context;
// If unitless, do nothing
// If compatible with radians, convert to radians and return unitless
@ -26,7 +27,7 @@ fn to_radians(q: Quantity) -> Result<Quantity, ()> {
pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation, DaisyError)> {
pub fn eval_function(context: &mut Context, g: &Expression) -> Result<Option<Expression>, (LineLocation, DaisyError)> {
let Expression::Operator(loc, Operator::Function(f), args) = g else {unreachable!()};
@ -154,17 +155,51 @@ pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation
Function::ToCelsius => {
let mut k = Quantity::new_rational(1f64).unwrap();
k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
let Some(q) = q.convert_to(k) else { return Err((*loc + *l, DaisyError::IncompatibleUnit)) };
let q_s: String;
if q.unitless() {
q_s = String::from("scalar");
} else {
q_s = q.convert_to_base().unit().display(context);
}
let Some(q) = q.convert_to(k) else {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q_s,
Unit::from_free(FreeUnit::from_whole(WholeUnit::Kelvin)).display(context)
)
))
};
let mut r = q.without_unit();
r += Quantity::new_rational(-273.15f64).unwrap();
return Ok(Some(Expression::Quantity(*loc + *l, r)));
},
Function::ToFahrenheit => {
let mut k = Quantity::new_rational(1f64).unwrap();
k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
let Some(q) = q.convert_to(k) else { return Err((*loc + *l, DaisyError::IncompatibleUnit)) };
let q_s: String;
if q.unitless() {
q_s = String::from("scalar");
} else {
q_s = q.convert_to_base().unit().display(context);
}
let Some(q) = q.convert_to(k) else {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q_s,
Unit::from_free(FreeUnit::from_whole(WholeUnit::Kelvin)).display(context)
)
))
};
let mut r = q.without_unit();
r *= Quantity::new_rational_from_frac(9i64, 5i64).unwrap();
@ -173,8 +208,18 @@ pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation
return Ok(Some(Expression::Quantity(*loc + *l, r)));
},
Function::FromCelsius => {
if !q.unitless() { return Err((*loc + *l, DaisyError::IncompatibleUnit));}
if !q.unitless() {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q.convert_to_base().unit().display(context),
"scalar".to_string()
)
));
}
let mut r = Quantity::new_rational(273.15f64).unwrap();
r += q.clone();
@ -182,8 +227,18 @@ pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation
return Ok(Some(Expression::Quantity(*loc + *l, r)));
},
Function::FromFahrenheit => {
if !q.unitless() { return Err((*loc + *l, DaisyError::IncompatibleUnit));}
if !q.unitless() {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q.convert_to_base().unit().display(context),
"scalar".to_string()
)
));
}
let mut r = q.clone();
r += Quantity::new_rational(459.67).unwrap();

View File

@ -19,6 +19,7 @@ pub fn eval_operator(context: &mut Context, g: &Expression) -> Result<Option<Exp
if args.len() != 1 {panic!()};
let a = &args[0];
let mut args_ll = op_loc.clone();
if sh_vars.len() == 1 {
if let Expression::Tuple(l, v) = a {
@ -28,6 +29,7 @@ pub fn eval_operator(context: &mut Context, g: &Expression) -> Result<Option<Exp
))
};
args_ll += a.get_linelocation();
context.add_shadow(sh_vars[0].clone(), Some(a.clone()));
} else {
let Expression::Tuple(l, v) = a else {
@ -46,16 +48,26 @@ pub fn eval_operator(context: &mut Context, g: &Expression) -> Result<Option<Exp
let mut i = 0;
while i < sh_vars.len() {
args_ll += v[i].get_linelocation();
context.add_shadow(sh_vars[i].clone(), Some(v[i].clone()));
i += 1;
}
}
let r = evaluate(context, &exp)?;
let r = evaluate(context, &exp);
context.clear_shadow();
return Ok(Some(r));
match r {
Ok(mut r) => {
r.set_linelocation(&args_ll);
return Ok(Some(r));
},
Err( (_, err) ) => {
return Err((args_ll, err));
}
}
},
Operator::Negative => {
@ -112,6 +124,8 @@ pub fn eval_operator(context: &mut Context, g: &Expression) -> Result<Option<Exp
if let Expression::Quantity(la, a) = a {
if let Expression::Quantity(lb, b) = b {
if !a.unit.compatible_with(&b.unit) {
let a = a.convert_to_base().unit;
let b = b.convert_to_base().unit;
let a_s: String;
let b_s: String;

View File

@ -68,15 +68,12 @@ cfg_if::cfg_if! {
return format!("\r\n{}", daisy_prompt(state));
}
if in_str.trim() == "quit" {
return "[quit]".to_string();
} else {
let r = crate::do_string( unsafe { &mut (*state).context }, &in_str);
match r {
Ok(t) | Err(t) => {
out += t;
}
let r = crate::do_string( unsafe { &mut (*state).context }, &in_str);
match r {
Ok(t) | Err(t) => {
out += t;
}
}
},
@ -91,7 +88,20 @@ cfg_if::cfg_if! {
//'\x04' | '\x03'
//=> { break 'outer; },
_ => { unsafe { (*state).promptbuffer.add_char(s.chars().next().unwrap()); } },
// Only process sane characters
_ => {
let c = s.chars().next().unwrap();
match c {
'a'..='z' | 'A'..='Z' | '0'..='9'
|'!'|'@'|'#'|'$'|'%'|'^'|'&'|'*'|'('|')'
|'?'|'~'|','|'.'|'['|']'|' '
|'<'|'>'|'/'|'_'|'-'|':'|'|'|'='|'+'|';'
=> { unsafe { (*state).promptbuffer.add_char(c); } },
_ => {}
}
},
};
let t = unsafe { (*state).promptbuffer.write_prompt(&mut (*state).context) };

View File

@ -26,7 +26,9 @@ pub fn main() -> Result<(), std::io::Error> {
let mut pb: PromptBuffer = PromptBuffer::new(64);
let mut context = Context::new();
// Set color compatibilty
// Detect color compatibilty
// Currently unused, this is slow.
/*
let term_colors = stdout.available_colors().unwrap_or(0);
if term_colors >= 256 {
context.config.term_color_type = 2;
@ -35,9 +37,7 @@ pub fn main() -> Result<(), std::io::Error> {
} else {
context.config.term_color_type = 0;
}
context.config.check();
*/
// Handle command-line arguments
@ -45,6 +45,8 @@ pub fn main() -> Result<(), std::io::Error> {
if args.iter().any(|s| s == "--help") {
let t = command::do_command(&mut context, &String::from("help"));
t.write(&context, &mut stdout)?;
let t = command::do_command(&mut context, &String::from("flags"));
t.write(&context, &mut stdout)?;
return Ok(());
} else if args.iter().any(|s| s == "--version") {
let t = FormattedText::new(format!(
@ -52,19 +54,34 @@ pub fn main() -> Result<(), std::io::Error> {
));
t.write(&context, &mut stdout)?;
return Ok(());
} else if args.iter().any(|s| s == "--debug") {
} else if args.iter().any(|s| s == "--info") {
let t = FormattedText::new(format!(
concat!(
"Daisy v{}\n",
"Your terminal supports {} colors.\n"
),
env!("CARGO_PKG_VERSION"),
term_colors
stdout.available_colors().unwrap_or(0)
));
t.write(&context, &mut stdout)?;
return Ok(());
} else if args.iter().any(|s| s == "--256color") {
context.config.term_color_type = 2;
} else if args.iter().any(|s| s == "--8color") {
context.config.term_color_type = 1;
} else if args.iter().any(|s| s == "--0color") {
context.config.term_color_type = 0;
} else if args.iter().any(|s| s == "--nosub") {
context.config.enable_substituion = false;
} else if args.iter().any(|s| s == "--nosuper") {
context.config.enable_super_powers = false;
} else if args.iter().any(|s| s == "--nooneover") {
context.config.enable_one_over_power = false;
}
context.config.check();
'outer: loop {
let t = pb.write_prompt(&mut context);
@ -99,7 +116,15 @@ pub fn main() -> Result<(), std::io::Error> {
break;
},
_ => { pb.add_char(*q); }
// Only process sane characters
'a'..='z' | 'A'..='Z' | '0'..='9'
|'!'|'@'|'#'|'$'|'%'|'^'|'&'|'*'|'('|')'
|'?'|'~'|','|'.'|'['|']'|' '
|'<'|'>'|'/'|'_'|'-'|':'|'|'|'='|'+'|';'
=> { pb.add_char(*q); },
_ => {}
};
} else {
match c.unwrap() {