leftiness / lingo Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Separate from secret.toml.
I'll want a default config that gets read if the provided config path doesn't exist. config.default.toml? Don't commit someone's personal config.toml to git.
I kind of half-assed the message passing actor concept. It's supposed to be concurrent with references to a parent. Like nobody knows if you're actually going to get a response or not. If your child actor does eventually respond with the hello world, then you act upon that by ending the process. Maybe you also decide that you'll end the process without a hello world if there isn't a response in a certain amount of time, but it's not like tell() synchronously returns a response like I made it.
Pseudo code:
Main {
&parent
greeter
}
Main::init(&parent) {
self.parent = parent
self.greeter = Greeter::init(&self)
self.greeter.tell(Greeter::Greet)
}
Main::tell(request) {
match request {
Greeter::Done => parent.tell(Main::Done)
}
}
Greeter {
&parent
}
Greeter::init(&parent) {
self.parent = parent
}
Greeter::tell(request) {
match request {
Greeter::Greet => {
println!("hello world")
self.parent.tell(Greeter::Done)
}
}
}
After main tells his parent that he's done, that means that the process should end. Ofc that means main needs a parent somehow.
Then there's this state machine stuff. I like the idea of saying view.update(&oldState, &newState) and having him decide whether to update the UI, but I feel like I don't have a very good implementation right now.
I should definitely have one separate "thing" which handles all of the state. Maybe that's an actor. Idk right now. Then there would be an entirely separate thing which handles drawing the UI. The parent "thing" would start them both up. So if the state tells the main parent that he updated, the main parent would pass that down to the ui. The ui would then be able to ask the parent for state properties, and the parent would ask the state for those properties, and those would be returned to the ui.
I like the idea of having a state machine which says that you can't go to chat until you've gone through the configuration loading state, but I feel like I haven't done a good job of mixing it with actors.
Kind of rambling... time for breakfast...
Haven't done the Hipchat API stuff yet.
Hipchat has a polling API. I'll have a thread running in the background asking Hipchat if there are new messages. When it finds some, it'll send a message to any registered listeners.
The state machine would be a registered listener if it is in a listening state. Then it'll handle updating the UI etc from there.
So the chat and the API polling are separate.
Instead of saying Response::Balderdash, maybe I could somehow enforce that tell() should only receive certain messages for a particular state.
One that writes to a file instead of stdout. Put the log somewhere that XDG standard wants it.
state::State.error could be a stack. Then I'd show one error at a time at the top of the screen or something. When they close the error, show the next. If there isn't another, hide the error text box.
Reading a secret file imports a function from a library. Inserting into a database for example would need an external system. Not pure.
I had an idea for a structure where I would receive an impure request, take immediate preparatory steps (like a spinning clock to show that I'm async loading), send off the request to an actor, and then call state machine's work done. Forget about it. The actor may or may not eventually call back, telling the state machine about the result of the request. If he doesn't call back, the app could say "it's been thirty seconds since that request. Something seems wrong." If he calls back, it would be with a message sent to the top of the state machine. Then that message would be handled like any other.
Maybe I want to take this approach whenever the state machine needs to do something that isn't pure and immediately effective.
Example is the secret_path property of the Start state being passed to the Load state. I want to pass &str instead of cloning the string, but then Response needs a lifetime, and these lifetimes need to be specified, and I'm not sure how it'll work... I have to figure this out because eventually I'll have a state full of hipchat messages, and I don't want to clone all of those...
In the actor pattern, a parent knows when his child panics, and he just restarts him. With what I have now, I remove an offline_listener from the dispatcher's subscribers if the tx.send() fails... So I'm just ignoring it...
It might work.
The State struct is Messageable, too. If I sent a Request::TransitionToLoading (or better name lol), I could handle it on the top level State struct and not send it down to the lower level state handler.
The response would be... Response::NewState(State) or something? Can a struct call its own From() implementation and return the result?
For example, I moved some config stuff into a config actor. I have a chat state now. Maybe I should also move all chat functionality into a chat actor.
I was originally thinking that an actor would be used when a piece of functionality needed to be shared among states, but maybe all functionality in general should be in an actor, and a state should just be a collection of actors. Transitioning between some states could mean getting some values from an actor and giving it to another. Maybe discarding some actors. Maybe making some new ones.
Lots of notes in #3.
When I close vim, I can see the terminal state up to and including the latest vim command.
Apparently they worked on this for Termion, but it was rejected because it was a breaking change. https://github.com/ticki/termion/pull/66/files
Thoughts:
Entering the Initialization state should require providing a struct. The struct would contain two strings (at least) which would point to config.toml and secret.toml. Then transitioning to the LoadConfiguration state would involve loading those files and parsing them.
They're state structs. They're stored on the state::State.
inject dependencies, can rust do default arguments for that pattern of injection?
Let's see if I can do tests without the idea of mocks and stubs. Those don't translate well to Rust. Message driven should help. Maybe I'll wrap libraries in a messenger to isolate the need to inject dependencies, too.
state::State struct should implement its own clone. Inside, it will only clone relevant state. For example, if it has 3000 messages, and it can only display 10 on the UI, it will only clone the 10 that it can display.
Don't do this:
errors::load::LoadError
states::load::LoadState
Do this instead:
errors::load::Error
states::load::State
The importer can rename things if he needs to.
Both states::Load and states::Chat need the config stuff. Read configs. Ask for the values in the config. Maybe even write to the config. I'm going to do that stuff in an actors::Config.
Need some structs, states, etc. Properties like messages_received, active_rooms, etc. Receive requests like Request::AcceptNewMessage
Don't do this:
lingo::errors::load::Error
lingo::structs::config::Config
lingo::actors::config::Config
lingo::states::Load
Do this instead:
lingo::load::Error
lingo::config::Container // previously structs::config::Config
lingo::config::Actor // previously actors::config::Config
lingo::load::State // previously states::load::Load
This structure makes it so that the path leading up to the struct name can be used as a qualifier without redundancy.
I'm not entirely sure about putting errors, states, structs, etc under one lingo::load module. It kind of makes sense to put pieces of functionality together by purpose (load) instead of sorting them by type (struct, actor, etc).
I was thinking about this because I wrote that actors::config::Config struct, and it required me to reference the structs::config::Config struct as a structs::Config instead of something that might be better like config::Container.
At the same time, I've got some files that are named the same thing that... maybe shouldn't be. The actors::Config and the structs::Config are kind of related, but they should maybe have different names.
If I ctrl+c once, it doesn't actually bring the brandon@melody: $ back. If I ctrl+c again, I get that brandon@melody. If I try to write a command before doing another ctrl+c, rust panics. Why? Rust should have closed completely already.
Docs: https://doc.rust-lang.org/std/sync/mpsc/
I've been writing and rewriting this concept for some time now. I've tried observers in a few different ways. I don't think that's the right way to do it. I'm not happy with it.
I want to try a different approach. I've got several types of events in mind.
I'll have one event receiver. Every event broadcaster will be given a transmitter at construction which will send events to that receiver. He'll also be given a reference to the event receiver at construction. He won't keep that reference. He'll just create a new (tx, rx). He'll register a tx with the receiver reference and then start a loop listening for events on his rx. When he receives an event on his rx, he'll broadcast to the receiver on the tx provided at construction. He'll also provide a fn(&self, m: &Message) -> bool
function pointer when he registers with the receiver. That function would filter messages so he only receives the ones he wants.
Examples of broadcasters:
What if I don't have a secret property but a secret actor? Or a database actor? Or something. I feel like I would want to transfer ownership of that actor on state transition. Can I send the owned actor in a message? It'll be a moved property because I'll still have an owned reference on my struct... How do I solve this?
Maybe just the State { state } should be private and the FooState { property } should be public. The state machine would then be able to get the properties from itself when it transitions, but anybody outside of the machine who wants access to its properties would have to tell(Request).
In state machine, refer to states as logged messageables. This function would just log the current state with the request, call the tell function, log the response with the altered state. This way I can track the state and actions of the application from a debug log.
I feel like the component itself should be able to handle events.
I could pass the Event::KeyPress events in from the view::Container. Suppose I should.
I plan to have views, which are collections of components. A view should be the one who keeps track of the component event handlers.
I should store something better than what io::Error.description() gives me. "entity not found" isn't enough. I at least want to make it clear that a secret toml wasn't found.
aKeyPress('a')
StateUpdate(State { error: [], preference: Preference, secret: None, last_key_press: Some('a') })
bKeyPress('b')
StateUpdate(State { error: [], preference: Preference, secret: None, last_key_press: Some('b') })
lLoadPreference
LoadPreferenceErr(FailedToLoadFile("entity not found"))
StateUpdate(State { error: [Config(FailedToLoadFile("entity not found"))], preference: Preference, secret: None, last_key_press: Some('b') })
vKeyPress('v')
StateUpdate(State { error: [Config(FailedToLoadFile("entity not found"))], preference: Preference, secret: None, last_key_press: Some('v') })
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.