Show HN: I made a web-based notepad with a built in unit calculator
numpad.io
It also supports percentages, dates and variables.
I've been working on this alone for a few years now, so would love to get some feedback.
numpad.io
It also supports percentages, dates and variables.
I've been working on this alone for a few years now, so would love to get some feedback.
One small criticism: In my opinion, no web-based writing app is useful unless the tab key inserts a tab. The default behavior of most browsers to move focus to the next field is tremendously infuriating in this context. Unfortunately, that's what happens here, at least for Firefox.
(Related: key combinations that normally perform cursor movements but which are often used by browser for navigation.)
(ducks) (but srsly)
First import things you need:
import { indentMore, indentLess } from "@codemirror/commands"
Then create a command: export const insertTab: StateCommand = ({state, dispatch}) => {
if (state.selection.ranges.some(r => !r.empty)) return indentMore({state, dispatch})
dispatch(state.update(state.replaceSelection(" "), {scrollIntoView: true, userEvent: "input"}))
return true
}
and then add it to the keymap in your extensions array: const extensions: Extension[] = [
...other extensions here...,
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...searchKeymap,
...historyKeymap,
...completionKeymap,
{key: "Tab", run: insertTab, shift: indentLess}
]),
]
and then pass the extensions array into where you setup your editor view, eg: const view = new EditorView({
state: EditorState.create({
doc: textarea.value,
extensions
}),
parent: editor
})Yours looks great. Well done on the release.
Line 100 might have an error though? It isn’t recognising `30th Sept`, does it not like the final `t`?
Well that's pretty neat. I've seen it in fancier setups, but not something Soulver-like. It seems a lot more usable here, since practically any equation can show it.
https://github.com/filipesabella/calcpad
It's electron though, if that's important to you.
You can use the web version, it's all offline and saved in localStorage. Works well in mobile too and can be "installed" as an app from there.
If you wanna see this in a little executable that you can pass around to your friends, check out this repo I threw up: https://github.com/shmup/redbean-calcpad
This is now essentially an offline CalcPad that still leverages LocalStorage, since the UI is your browser. I've configured this specific build to automatically launch your default browser when you run it.
There should likely be an explicit override of accessibility so the visitor knows what they're getting into.
Example: I (who am not a programmer) once wrote a tangled mess of HTML and JavaScript to accept, and tabulate data entry for rebar (reinforcing steel) estimates. I was inordinately proud of it, bird's nest of bad programming practice that it was. I could TAB or ENTER-key my way through all fields, the up and down arrows performed the same tasks as the TAB-key, just like on a desktop program.
So why was it important to do things this way, and break the conventions so dear to the heart of the standard's purist? Because this is how I (and many others) estimated rebar in the 1990's:
You sat at a wide desk or table with a set of plans 30" to 48"-wide spread out to your left (if you were lucky) and another 30"-48" of table was needed to catch the plan pages turned to reveal the one you were working on. You right hand rested on the keyboard's ten-key pad some 3-5 feet away. You didn't look at your right hand -- you looked at your left hand index finger which was glued to (and rarely left) the large page at precisely the item you wanted to enter into your tabulation program, as you entered the SAC code, the qty per unit, the number of units, the bar size number, the bend category, the grade of steel, and the total length. Your eyes never left the drawing as you did this, and immediately upon completing that line item, your left hand picked up a yellow highlighter and highlighted that item -- one of many hundreds or thousands that would be necessary in a materials take-off of any appreciable size. To force the use of the TAB-key, or the mouse to move through data-entry fields would simply guarantee that no one would use your program. Ever.
But the purist says, "Someone may stumble." Aunt Loreen said, "Sometimes the 'You shoulds' are the sh-ts."
One related app that I absolutely love is Qalculate![1] (yes, it has a built-in exclamation for default enthusiasm :) )
It can do cool stuff like converting N (newtons) to kg.m/s^2 when you specify units as ?kg. It also converts units like 1kW x 1year = 31.55... GJ
It's fantastic for engineering and specially back-of-envelope calculations. This notepad aspect does seem useful though. One alternative is to use Jupyter notebooks, sometimes I work problems with Sage[2]+Jupyter. Sage is extremely powerful (you can do calculus, linear algebra, and more) but doesn't support units (that I know of), it's more geared toward advanced maths.
[1] https://qalculate.github.io/
[2] https://www.sagemath.org/ It's a bit on the heavy side although it's definitely worth it if you're doing a lot of math. I think the flatpak is preferred due to its significant size.
> 1 metre + 8 chain = 161.9344 m
> 1 tonne + 1 short ton = 1.90718474 t
> 1 tonne + 1 long ton = 2.0160469 t
and give it a pass for not supporting pre 1963 UK | US historic weights and measures .. that's getting into a pretty specific use case where Standards nerds like to have a clear display of what conversion factors are in play and what provenance those factors have.
Time Zone support (on your About ToDo) will be interesting, historic computations with daytime savings support will be a quagmnire :-)
The SHARE DOC URLs seem a bit long - something like "base64 full text of doc as an URL" I guess.
Will this hit a URL length limit if widespread use becomes a thing?
jq play : https://jqplay.org/s/f1r-BZ5xYd2
regex101 : https://regex101.com/r/OqojJl/1
do server side storage and doc hash .. which has issues of its own.
there are so many reference ellipsoids and datums used in different parts of the world at different times .. and then there are the many variations on curved surface to flat map projections to deal with.
But yes - Time and date is an iceberg domain :-)
> 14 furlongs / 2 weeks in mph [0.0052083333 mph]
Even includes error handling :)
At the bottom you can see some test examples of what it can do. Obviously it is a basic calculator.
But to give you an idea of what that all looks like this is the code for the parser that parses the "as a % of" operator:
append(
string("as"),
oneOrMore(space),
optional(append(string("a"), oneOrMore(space))),
percentSymbol,
oneOrMore(space),
string("of")
)
[0] https://github.com/bodil/eulalieI wasn't familiar with Eulalie, that's a really interesting approach. I built functionality [0] similar to numpad into a larger record-keeping system, Tap [1]. Precedence rules kindof scramble my brain so I ended up implementing s-expression syntax for Tap formulas.
I ended up writing the parser myself, called sowhat, but used a library for tokenization, moo.js [2]. You can see a demo of just the sowhat editor here [3].
0. https://www.tatatap.com/formulas 1. https://www.tatatap.com 2. https://github.com/no-context/moo 3. https://tatatap-com.github.io/sowhat-editor/
This reminds me of the open source NoteCalc: https://bbodi.github.io/notecalc3/
It was discussed on HN, you might look there for inspiration: https://news.ycombinator.com/item?id=25495393
As a sidenote I would like to mention that NoteCalc is still in active (but slow) development, though I do it privately, and the next big release will be definitely this year.
1. the copyright notice
2. the text itself that explains that you/others have this permission/obligation
Currently, it looks like NumPad isn't doing either.
From comments here, NumPad is evidently also using decimal.js, which has similar terms.
There's a reason why everyone who has their ducks in a row (in other words, people with competent legal counsel along with something to lose, e.g. Mozilla, Google, Apple, Microsoft, etc) will bake something like about:license into the stuff they work on, even if it's buried in some "open source licenses" entry of an About screen reachable by the last menu item in the system settings. Spoiler alert: it's because they have to—in order to comply with the terms of the license. It's not because they just think it's the nice thing to do. (And definitely not because it's fun and easy to do, because it's not.)
That's simply not true. Please don't do stuff like this—to go off and make these kind of proclamations in public. It's negligent at best.
The repeated distinction between source code and "artifacts" in this context is pure make-believe. The license doesn't even have those words in it, let alone say something like "Redistribution and use in source form requires inclusion of this permission notice and the above copyright notice, but if you're just building a product and publishing it as non-source code artifacts instead of distributing source, then lol don't worry about it bro" (or whatever it is the people here seem to think).
The CodeMirror maintainer definitely expects people who build closed source stuff to include the notices that are in the CodeMirror LICENSE file. And anyone telling you the license doesn't require this (and e.g. this is a peculiarity of CodeMirror itself) is delusional.
And this was my understanding of how it works for artifacts. You don't have to attribute in the software itself, just the code.
Not sure if you were referring directly to me, but I don't think my comment was harmful. Others may have also been led astray and an exchange like this might be educational for them to read.
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
I think that second part is relevant to the discussion.
I wrote my own little calculator, much less general than this, to answer running time questions like "to run an 18 minute 5k, what would my mile pace be"? and it would be neat if that were cleanly solvable in a tool like this
I was intrigued what you had used to build it, and if you had built your own solver (which you have), and what editor you used (Code Mirror) so went looking at the code. Interesting to see you left the source maps for production, made it easy for my sleuthing...
I experimented with a similar idea last year, but used ProseMirror/TipTap as the editor to enable rich text editing, and the MathJS (https://mathjs.org) solver. I also combined it with PouchDB and Yjs for offline editing and syncing between devices. Never finished it though, you have kept your nice and simple!
Your project sounds really interesting, I'm following you on twitter now, so tweet about it if you ever finish it and hopefully I'll see.
Having CRDT-based syncing/collaboration is a direction I'd like to take NumPad in eventually, and if I have time. But I definitely think that ignoring that part completely has allowed me to get it to an MVP state.
> 100 eur to usd $-100.63 > 100 usd to eur Incompatible units
But it seems the parser is breaking when trying to do the inverse, anyway: "100 usd in eur" seems to do "e*ur" and gives "Values must be converted to units."
In reality, months/years are simply not convertible to days/weeks arithmetically, and you can’t sensibly add months to certain dates, and sometimes also not years (for February 29th). The former should give “Incompatible units”, and the latter should result in something like “Undefined” for incompatible dates.
> 1111111111111111111111111111111*9
> 10,000,000,000,000,000,000,000,000,000,000Some feedback: I tried to convert m/s in km/h and it wouldn't works, finally found how to do it, you need to specify `hour` in full letters
I assumed it was something like an etherpad that you could edit collaboratively but apparently not
I'll have to think some more about this one.
min(a, b) = (a + b - abs(a − b)) / 2
max(a, b) = (a + b + abs(a − b)) / 2
I’ve had some issues when using it though: - on mobile, moving the cursor in a calculation doesn’t work very well; - More important, multiplying “200 * 10%” results in “2000%”, I believe the result should be “20”; https://www.wolframalpha.com/input?i=200+*+10%25
I agree formatting should probably go with the first factor, but I wouldn't say current behavior is incorrect
https://github.com/seligman/human_calc
I find it surprisingly useful. It's probably one of those things that has an audience of one, but I find it useful.
So
3.3 KW * 3.1 miles per KWh
Says "3.3". The math is wrong and the units are gone.Actually, it doesn't seem to understand the concept of a KW. I'll try "kilowatt" and "kilowatt-hour" respectively.
3.3 kilowatt * 3.1 miles per kilowatt-hour
Says "Incompatible units".The closest I got was
3.3 kilowatt * 3.1 miles per kiloWh
Says "10.23 kW mi".insect.sh is able to do that last one.
3.3 kilowatt * 3.1 miles per kiloWh
3.3 kW × (3.1 mi / kW·h)
= 10.23 mi/hGives "10.23 kW mi / kWh" as you expected
I guess ideally you would want it to factor out the kW.
This way writing "and here is a little example of 9^9^9" and simply copy paste that to next line would allow me to not have it evaluate on text, but only on next line. OF course, a little more complicated to implement would be next step of actually select the text and within the pop-up have "Don't evaluate". This way writing a documentation without having always calculation be in your way would be very easy.
Other than that, this looks great ma' dude. Keep it up!
I noticed that it doesn't handle remainder/modulo (%) equations:
"10 % 2" results in: "Left hand side of addition cannot be a percentage."
It does look like decimal.js can handle that: https://mikemcl.github.io/decimal.js/#mod
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Looks like there's a mod operator, so "2303 mod 10" gives 3.
> Frink is a practical calculating tool and programming language designed to make physical calculations simple, to help ensure that answers come out right, and to make a tool that's really useful in the real world. It tracks units of measure (feet, meters, kilograms, watts, etc.) through all calculations, allowing you to mix units of measure transparently, and helps you easily verify that your answers make sense. It also contains a large data file of physical quantities...
Looks much like the original idea behind lighttable IDE which is basically a REPL plugin that allows to evaluate certain lines within it. There are several similar projects around.
I was a big fan of Light Table when it first came out and the developers behind it have gone on to do some really interesting things, but I want to keep this project more limited in scope for now.
That can be an issue if you provide a limitless cloud instance, but you can roll the ball to user’s roof with client a side engine, either JS or a local instance, depending your vision for such an app.
This is impressively close to what I have in my desired spec (but already more future proof). Congratz!
Just a little bug: I found that if I click a number to copy, then click it again, I'll get the original string in my clipboard concatenated with " Copied!"
1. Doesn't seem to support area conversions (tried 400 square meters, 400 m^2, and abbreviations in between).
2. If I only give a time, it would be more useful if it gave a time-only result rather than defaulting to the current date - unless it rolls over to a different date. (E.g. in Soulver, "2:30pm + 20hr" gives "Tomorrow at 10:30".)
3. It would be nice to support multiple abbreviations for minutes (mn/min are both used in various countries).
... works for me.
Re dateless times, yes, I think the Soulver way is unambiguous but still human-friendly.
1. "square" before a unit I probably will implement that in the future. I'm not sure why "400 m^2" isn't working for you, I've just tried it and it works as expected for me?
2. It's a little bit clunky, but I decided to always specify the time and date being shown because there's so much potential for ambiguity. I might revisit this if I can think of a better way of doing it that's still unambiguous (the Soulver way isn't bad tbh)
3. "min" is supported, I've never come across "mn", do you know where it's used?
I found a small bug: `5 hours 20 minutes` will give you `5 hr 19 min 60 s`. This only happens with some numbers in the minutes slot.
One bit of very minor feedback:
`x^y tonnes` errors 'exponent must be unitless'. The more expected (IMO) grouping `(x^y) tonnes` works, so why not have the non-error grouping be the implied one, when no parens given?
Getting operator precedence right has been pretty fraught tbh. For example "1km / 3 hours" is evaluated as "(1km) / (3 hours)", but "1 / 3 hours" is evaluated as "(1 / 3) hours", which is odd from a PL perspective, but I think it's more intuitive from a user perspective for this sort of thing.
" Alice's food = £30 Bob's food = £25 VAT = 20% Alice's food + Bob's food + VAT "
Rather than just punch (30+25)*1.2 straight into a calculator?
[†]: http://calca.io
It's particularly suited to calculations I'm doing by fetching various numbers from websites, and for the most part it 'composes' by just copypasting a calca into another one.
Basically where the numbers mean something, aren't stable / I don't know them all when I start, but there's no tabular data or significant aggregation going into the question.
I can see myself using this a lot as a scratch pad to hash out ideas while implementing stuff. The ability to define custom functions would be very helpful for that.
So if you had: Alice's food + Bob's foood = £30 then I think there should be more to highlight the typo.
P.S. This is an awesome thing
MonthlyRepayment(principle, annual_interest, term_in_years)
3 ^ 1 * 2 6
3 ^ 1 / 2 1.73205
3 ^ 1 + 2 5
3 ^ 1 - 2 19 - 3 ^ 2 = 0
9 -3 ^ 2 = 18 ???
pi = 3.1415926536
2 pi = 5.1415926536 ???
sin(3.1415926536 radians) = -0
sin(pi radians) = Incompatible units ???
It would be nice if "1 mm / inch" would be returned as a unitless number. I know that you can enter "1 mm in inch" but there are cases where it would help to have the calculator reduce the units for you.
It's still in development. I built a proof-of-concept from scratch almost a year ago, which I just open-sourced at the following link.
https://github.com/nonoesp/note-parser
I intend to develop it a bit more and host it online.
A previous prototype, really barebones, is at https://expensed.me.
The idea is to drag and drop (or type) a plain-text note and visualize the data as a scatterplot or other charts.
I've been thinking of ways to parser phone screenshots with payment data or use bank APIs to add data to my expense tracker, as opposed to adding everything manually, which is the best way I've found for consistency and to make sure everything is properly formatted.
I didn't know about PSD2. Do you have any links or references for me to look at?
I was trying to divide an area by a smaller area to get the number of widgets, and it insists on making that into a percentage. Is there a way to make it report a raw number instead of percentages when the two quantities are the same unit?
Base 10 (GB for example) and base 2 (GiB) would be very handy. Full words as an alias as well, so GB -> gigabyte, and GiB -> gibibyte.
That way you can do something like:
1GB / 40MB/s in minutes
1GB to Gib
1GB to bits
50 bits to bytes
* https://github.com/cescript/MarkdownFormula
Its totally awesome, although it needs some more work.
Minor bug report -
* 5 feet 8 inches to centimeters -> -171.72 cm
* 5 feet 8 inches to meters -> -0.7272 m
* 5 feet 8 inches to cms -> doesn't work
The conversion seems wrong in the case of cms, and I'm not sure why it's always negative.
As in (distance from) 30 to 50 (is 20 == 50 - 30 )
[0] https://jasper.monster/sharex/firefox_eXIffwiyBq.png
//EDIT
Ah yeah, replace "to" with "in" and you're good! [1]
> * 5 feet 8 inches to centimeters -> -171.72 cm
As @defrost said, the 'to' operator instructs NumPad to calculate the distance from the unit before 'to' and the unit after 'to'.
To the nearest mm, 5 feet 8 inches = 172.72cm
It appears that NumPad is defaulting to a value of '1' where no value is specified, so it is calcuating the distance BACK from '5 feet 8 inches' TO '1 centimeters'.
It correctly responds with -171.72, which is 1cm less than 172.72.
> * 5 feet 8 inches to meters -> -0.7272 m
Same as above, except the calucation is the distance back from '5 feet 8 inches' TO '1 metres'.*
If you use the operator 'in', NumPad calculates the answer correctly:
5 feet 8 inches in metres -> 1.7272 m
When starting a new line, and the first character is 'e', it gets evaluated to the euler constant. Would be cool if you could find a way to prevent that. :)
2 + 3 (=4)
Ans * 2 (=8)
x * 2
Anyone knows if there's a way to have this feature in Joplin[0] ?
(I'm European too and I thought it was always in front, everywhere)
NumPad currently accepts numbers in the "9,999.9" format, which is the default in the anglosphere, but "9.999,9" is common elsewhere. So that's another thing I'd like to address in the future.
e2foo 4.7182818285
pi-hole 3.14159265368:00pm 24 Aug Toronto time in Dubai time
And have the conversion show up.
Now we need to port to Obsidian.md! haha.
23 USD to CAD = -28.875332087 CAD
$23 USD to CAD = -30.174259569 CAD
It does not appear to like the USD/CAD stuff
20mm * 30mm * 7mm in m^3 -> incompatible unitsgreat work, bookmarked.
"Share doc" is not clear imo. Why not "Save & Share"?
No, you're right. I thought I'd prevented it from parsing numbers as variables, but apparently not. It's on my todo list now.
10^900=∞ :)
Similar tool for people who prefer to use the terminal.
Emacs' calc is also pretty much the same thing.
I wish it could be something lightweight and launched as a native app.