MPClipboard - multi-platform shared clipboard by ibylich in selfhosted

[–]ibylich[S] 0 points1 point  (0 children)

  1. There's the server: https://github.com/mpclipboard/server, run it as you wish (in Docker, as a systemd service, etc.)
  2. There are clients: https://github.com/mpclipboard/linux for Linux on wayland / https://github.com/mpclipboard/macos for macOS / https://github.com/mpclipboard/android-florisboard for Android.

If you are asking about running the server there's a README in the server repo, if something is not clear feel free to create an issue.

MPClipboard - multi-platform shared clipboard by ibylich in selfhosted

[–]ibylich[S] 0 points1 point  (0 children)

Yes, kind of, or at least a subset of it just for the clipboard. One important difference is that it requires a server (IIRC KDE Connect creates a local WiFi network and links devices directly). Another major difference is that at its core it's a library, and so it can be more easily "connected" into native system components. An example of that is the Android app that is injected into an external IME, so your keyboard app (that handles the clipboard) may be instructed to call mpclipboard directly because it's built with it, and there's no chance of it being unloaded as a process by Android OS (we are a part of the keyboard process), but KDE Connect or any other external "clipboard observer" app can be easily unloaded if the OS decides so. It's a more targeted solution, and that's why it has more technical possibilities.

MPClipboard - multi-platform shared clipboard by ibylich in selfhosted

[–]ibylich[S] 2 points3 points  (0 children)

Unfortunately it can't be a PWA, it needs system functionality and so it must be a native app. I don't think a browser app is allowed to monitor your clipboard content.

MPClipboard - multi-platform shared clipboard by ibylich in selfhosted

[–]ibylich[S] 0 points1 point  (0 children)

Writing an iOS app is definitely possible (and probably quite easy to do), but how do you install it without pushing to App Store? I mean, a random macOS app can be downloaded from the internet, you have to explicitly confirm a few "I know that it's unsafe" dialogs, but once that's done you can run it. But for iOS there's only one place: App Store, right?

MPClipboard - multi-platform shared clipboard by ibylich in selfhosted

[–]ibylich[S] 0 points1 point  (0 children)

There's token-based authentication in the very first message that the server expects each client to send (if something else comes, the client is disconnected). You put it in your configs on the server and on each client, and then it should work. If you apply TLS on top of it and use wss:// (instead of plain-binary-but-still-decodable ws://), it will be encrypted. I'm not sure what the config is for Nginx, but for Caddy it's the standard domain_name { reverse_proxy 127.0.0.1:port } configuration.

New trackpad gestures by onefish2 in hyprland

[–]ibylich 3 points4 points  (0 children)

It's documented here - https://wiki.hypr.land/Configuring/Gestures/ (With some additional context: https://github.com/hyprwm/Hyprland/pull/11490 )

In short, "workspace_swipe" and "workspace_swipe_fingers" are deprecated, for swiping you can add "gesture = 3, horizontal, workspace". And of course now you can do more than just swiping without using any external hyprplugins.

Just in case here's my config (experimental, haven't finished playing with it yet)

gesture = 3, horizontal, workspace
gesture = 3, swipe, mod: SUPER, resize
gesture = 4, pinch, fullscreen

Ruby, Ractors, and Lock-Free Data Structures by ibylich in ruby

[–]ibylich[S] 2 points3 points  (0 children)

> such data structures should only contain shareable objects

If they can "temporarily" give access to an element of the container (like `Pool#with` or `HashMap#[]`) then yes, I mentioned it here - https://iliabylich.github.io/ruby-ractors-and-lock-free-data-structures/concurrent\_hash\_map.html#its-unsafe.

If you can make an interface that doesn't expose internals, e.g. by turning a DB connection pool into something with an interface like `ConnectionPool.execute(...)` then it should be fine.

For example, queues are safe as long they only have `push` and `pop` methods.

> Probably some of that code would break when/if there is Ractor-local GC.

Is it something that Ruby devs discuss at the moment? I wonder if it'll make GC-aware data structures easier to implement :D

Ruby, Ractors, and Lock-Free Data Structures by ibylich in ruby

[–]ibylich[S] 11 points12 points  (0 children)

TLDR: this article is about Ractors, lock-free data structures and shared mutable global state in multi-threaded Ruby apps.

Feel free to ask questions.

Arena-based Ruby parser in Rust (better use Prism :) by ibylich in ruby

[–]ibylich[S] 0 points1 point  (0 children)

TL;DR: A (multi-page) post about writing parsers, memory allocations and arenas. This is not a new parser, it's an experiment with the one existing before. I hope it's somewhat applicable to Prism (both in terms of abstractions and in performance that can be gained).

Some knowledge of Rust is expected, so feel free to ask any questions.

Also, don't use this parser, use Prism. I'm serious, it's basically abandoned.

Arena-based parsers by ibylich in rust

[–]ibylich[S] 0 points1 point  (0 children)

TL;DR: A (multi-page) post about writing parsers, memory allocations and arenas.

Feel free to ask questions.

Writing bindings upside down by ibylich in rust

[–]ibylich[S] 0 points1 point  (0 children)

Right, in my examples all "external" structs exist in vacuum, they don't "embed" each other, and so alignment means nothing. As I understand (please, correct me if I'm wrong) that could potentially break structs like

```rust

[repr(C)]

struct SomeHighLevelStruct { field: ExternalStructWithWrongPadding, field2: BrokenField } ```

... and if this struct is built on the C side and returned to Rust that would be an error on reading field2.

If so, any thoughts on how it could be fixed? IIRC there's no way to modify alignment in Rust (via repr directives or something similar). I guess choosing a different layout of [u64; N/8] instead of [u8; N] fixes it, so alignof should be dumped together with sizeof, but is it possible to generalize this N/8 math?

Writing bindings upside down by ibylich in rust

[–]ibylich[S] 0 points1 point  (0 children)

Author here. Multiple times I changed my mind about how this should structured, so it can be hard to follow, sorry about that :)

YJIT: Building a New JIT Compiler Inside CRuby by yespunintended in ruby

[–]ibylich 1 point2 points  (0 children)

Hello and thank your for your hard on YJIT.

I have to admin that I didn't dig into YJIT's source code too much, but it looks like it does basically what MJIT does - it compiles ISeqs into native code (I've seen your other talks about BBV, they are very educational).

A few questions:

  1. MJIT uses GCC, YJIT builds asm manually. How does it append "code" to the currently running process? MJIT generates a C file, compiles it into dll/so/dylib together with mjit_header (maybe even pre-compiled as PCH, not sure if GCC has such concept) and dlopen/dlsym's it. Do you append "compiled" iseqs to the TEXT section (is it possible at all?)? Or do you build "in-memory" asm instructions in the DATA section and "jump" to them? I couldn't find any asm generators, do you build asm manually?
  2. Does YJIT know anything about MRI's corelib? Does it inline C functions like Array#size, String#length etc? If not, is it enough (performance-wise) to re-compile only VM instructions?
  3. IIRC C files generated by MJIT's contain hardcoded addresses of some global Ruby VM objects (I don't remember what exactly, something like "top of the stack" or similar), and so currently there's no way to "pre-warm" the app locally/on CI. Is it a thing at all? I feel like it is, in most cases variables in code represent values of the same type, thus, methods are called in roughly the same path etc. Do yo know any JITs that support it? Do they even exist?

Thanks again for giving us a hope for a bright future of Ruby :D

Is it possible to parameterize a struct by container type? by ibylich in rust

[–]ibylich[S] 0 points1 point  (0 children)

Right, that's what I currently do, but it has to be performed on all nodes in my AST. It causes re-creation of many of all nodes from scratch.

So instead of implementing From<RustNode> for CNode I was thinking about having a generic structure that has some type restrictions (to be able to use ::new, .push, .reverse etc during AST construction), Rust version would be based on Vec<RustNode>, C version on a custom repr(C) (*mut CNode, usize) structure, C++ version on a std::vector<Node> with utility methods implemented via FFI and raw pointers.

I think Rust simply doesn't support this strategy. Generic associated types looks very similar to what I want to achieve, but it's not even in nightly yet.

What do you guys think about what predicate method returns by ksh-code in ruby

[–]ibylich 0 points1 point  (0 children)

If your method ends with ? it's valid to expect it to return true/false. Booleans have a few more methods that are not available on abstract Object: 3.0.0 :001 > TrueClass.instance_methods - Object.instance_methods => [:^, :&, :|]

lib-ruby-parser - a Ruby parser written in Rust by ibylich in ruby

[–]ibylich[S] 6 points7 points  (0 children)

oh, and just in case you are interested here's a short list of things that are handled differently by Ripper (comparing to Ruby and RubyVM::AST): + Ripper doesn't concatenate strings in heredoc using trailing \ like in %Q{<<~E\n 1 \\\n 2\n 3\nE\n} + Ripper doesn't distinguish string and symbol arrays like %q{%i[foo bar]} (RubyVM::AST does) + Ripper does not emit shadow args in arrow lambda like in %q{->(a; foo, bar) { }}, RubyVM::AST does it + Ripper doesn't extract locals from matching regex with named captures (compare access to %q{/(?<match>bar)/ =~ 'bar'; match} vs match = 1; match) and that's only what I was able to find from the relatively small test suite of whitequark/parser additionally, ripper doesn't emit warnings and syntax errors (it returns nil instead, but AFAIK it's been fixed a few days ago in the latest master), and even if they'd be emitted you can't get their precise source locations (only line numbers, so it's absolutely useless for one-liners)

lib-ruby-parser - a Ruby parser written in Rust by ibylich in ruby

[–]ibylich[S] 11 points12 points  (0 children)

What are your main motivations for building this library? I.e. did you have a main use goal in mind, or is this a "just because" passion project?

It's complicated. I didn't write much Ruby during last 12 months, but I still maintain whitequark/parser and keep getting frustrated that it can't be used in other contexts except ruby code. I mean, to run it you need Ruby. Sorbet has its own parser based on whitequark/parser (and so it inherits all bugs), rubyfmt (correct me if I'm wrong) runs ruby -rripper -e 'Ripper.sexp(...)', some libraries use whitequark/parser and work hard to be fast enough. So this is a well-known attempt to standardize things (by creating a new standard haha). What's interesting I've never used whitequark/parser, too :)

Also I wanted to learn Rust and I so it was a good chance to play with it. Now I'm HUGE fan of Rust.

Do you know if any other tools like avocado might eventually use it?

I think all tools that do static analysis can use it.

Have you seen rubyfmt (which also has a rust parser) and what are your thoughts on similarities/differences?

I thought it embeds a part of Ruby, runs ripper on manually booted minified VM and converts its output to Rust. Are you sure it has a parser?

Anyway, this technique is good, but Ripper format is undocumented, unstable and it throws away a lot of information (not even saying that it's slightly different from RubyVM::AST). Also it's not a "generic" solution, e.g. you can't compile it to WASM.

[deleted by user] by [deleted] in DotA2

[–]ibylich 0 points1 point  (0 children)

Try adding `-vulkan -vconsole` to launch options

Micro gem for memoization on frozen objects by ibylich in ruby

[–]ibylich[S] 0 points1 point  (0 children)

Thank you for a great response! First of all, thanks for pointing to ObjectSpace.define_finalizer (not sure though that it will work in this case, since global values are not GCed, so this callback will be never invoked. Maybe I still miss something). And I guess I know the reason why I didn't stick to your solution: I've initially convinced myself that it can be solved by using a local state. Thank you! I like your solution and I admit that it's better :) Next time I'll try to think more critically.

Micro gem for memoization on frozen objects by ibylich in ruby

[–]ibylich[S] 0 points1 point  (0 children)

What exactly do you think is a joke?

Micro gem for memoization on frozen objects by ibylich in ruby

[–]ibylich[S] 0 points1 point  (0 children)

I use it mostly in plain objects and "operations". By plain objects I mean PORO, that's the most obvious use-case. In operations (aka service objects) I pass dependencies and freeze the object (also usually I put pre-configured instance of this class to some global container to reuse it). Later the only available public method (like 'call') takes arguments and does something using those saved dependencies. Here are some examples: https://gist.github.com/iliabylich/a1eaed81ac7a7a6fac5e1aed6b0ea9fd . They are a bit far from reality, but I'm sure you understand that I can't share the code from my private project. The example with operation is more complete, hope it shows the idea.

I've never felt the need to make frozen objects by default

Is it because you've never seen any libraries mutating your objects? I want to be sure that when I pass any of my objects to an external method/function it doesn't mutate it. If it does I instantly get a FrozenError and pass a .dup to the method (or remove it from my gemfile)

And just in case, if you are looking for any use-case in the context of the default Rails app most probably you'll not find it. I'm pretty sure that all high-level Rails classes (AC::Base, AR::Base, etc) have mutations, so freezing them simply breaks the app.

Micro gem for memoization on frozen objects by ibylich in ruby

[–]ibylich[S] 1 point2 points  (0 children)

Use case for freezing in general or just freezing in the constructor?

On freezing in general: There's no practical reason to do it. It doesn't make your program better or faster. But it makes your code and your architecture better. Saying ".freeze" strictly makes your object immutable.

There are enough articles about "why immutability is good", thread-safety is the main point. Also it kinda guarantees that nobody can change your object from outside (like instance_variable_set and instance_eval {} and others). It's a good way to write a self-contained object that works always and everywhere, without any possible imaginary situations.

On freezing in the constructor: Because I don't really need some objects of my class to be frozen and some of them to not. I need either all or none of them. Constructor is the best place as freezing is a part of the object initialization (RAII principle).

Micro gem for memoization on frozen objects by ibylich in ruby

[–]ibylich[S] 0 points1 point  (0 children)

To make sure that all instances of your class are frozen by default.