Giter Site home page Giter Site logo

umberwm's Introduction

Hi there ๐Ÿ‘‹

umberwm's People

Contributors

mfdorst avatar yazgoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

umberwm's Issues

do not allow same window in multiple workspaces

in some cases, it is possible that a window appear from one workspace to another (e.g. browser is focused in current workspace while it was in another one)
this should result in a workspace move of the window.

[Feature] plugin system

Hi!

I have an idea, and I would like to join to this development. I like this core functionality.

What do you think about this?

  • The main function is developed like you did. Build a main program which can read the config directory from the user home folder
  • All the config file built as compiled Rust lib (plugin). The plugin system from here: https://github.com/luojia65/plugin-system-example
  • The main program read the plugins and execute them. There are name convention like: 01_layout_exmaple.lib (order_type_anyExtraName)
  • When change the layout as normal, only activate the next plugin
  • Also possible to define key listener plugin, if needed. Like: 01_key_example.lib (order_type_anyExtraName)
  • There have to be 1 core layout, and 1 core key listener if no plugin available.
  • If the one plugin will be updated, the OS detect the file changes and the main program reload the plugin, and if new plugin will be available the main program add to the layout list or to key listener list. The process also same for the deletion, if one plugin will be deleted the main program remove from the plugin list.
  • If no plugin available the core plugins going to be available only

In this case you do not need to restart the main program if something need to be change. The other main feature is fast, because all plugin call are native. Only need to create some injection point for the plugins.

What do you think about this idea? Would you like to add this core feature to your core lib?

Thank you for this tinywm!

Bug: Windows become uncontrollable after restart

I implemented a simple way to restart like so:
main.rs

...
custom_actions: vec![
    // ...
    ("q".to_string(), Box::new(|| std::process::exit(1))),
    ("r".to_string(), Box::new(|| std::process::exit(0))),
]

umberwm-start (the script I use to start umberwm)

while true; do
    # Restart if exit code is zero, otherwise quit
    umberwm || break
done

and what I found is that when restarting, the existing windows just sit where they were to begin with. They are interactable, and if it's a terminal you can still close it by typing exit, but you cannot close it or move it with keybindings, and when making new windows they just cover the old windows like they aren't even there.

I assume there is some list of window handles somewhere, and making a new window will add the handle to the list, but umberwm probably does not check for existing windows on startup, so that's probably what's causing the problem. I'll look into this.

Can't compile

Linking error. I know I need the XCB library installed, but not sure which that is on Ubuntu. It looks like I have libxcb1 installed and libxcb1-dev

โฏ cargo build --release
   Compiling libc v0.2.69
   Compiling memchr v2.3.3
   Compiling log v0.4.8
   Compiling lazy_static v1.4.0
   Compiling cfg-if v0.1.10
   Compiling regex-syntax v0.6.17
   Compiling thread_local v1.0.1
   Compiling aho-corasick v0.7.10
   Compiling xcb v0.9.0
   Compiling regex v1.3.7
   Compiling umberwm v0.0.17
   Compiling myumberwm v0.0.1 (/home/dalton/dev/myumberwm)
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-Wl,--eh-frame-hdr" "-L" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.0.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.1.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.10.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.11.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.12.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.13.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.14.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.15.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.2.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.3.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.4.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.5.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.6.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.7.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.8.rcgu.o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.myumberwm.4jd5ph17-cgu.9.rcgu.o" "-o" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785" "/home/dalton/dev/myumberwm/target/release/deps/myumberwm-543f261b8bd8e785.275em5cn4vgv6nhk.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-L" "/home/dalton/dev/myumberwm/target/release/deps" "-L" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/dalton/dev/myumberwm/target/release/deps/libumberwm-d5eb8012ff3466a6.rlib" "/home/dalton/dev/myumberwm/target/release/deps/libregex-10c524ff798ebf91.rlib" "/home/dalton/dev/myumberwm/target/release/deps/libthread_local-3948ce50dadeb546.rlib" "/home/dalton/dev/myumberwm/target/release/deps/liblazy_static-72fd4c50b9d3882e.rlib" "/home/dalton/dev/myumberwm/target/release/deps/libregex_syntax-420be60029984cc8.rlib" "/home/dalton/dev/myumberwm/target/release/deps/libaho_corasick-4c484a23c2e706ee.rlib" "/home/dalton/dev/myumberwm/target/release/deps/libmemchr-b5ad103136b5cebd.rlib" "/home/dalton/dev/myumberwm/target/release/deps/libxcb-a8458a241519b5ad.rlib" "/home/dalton/dev/myumberwm/target/release/deps/liblog-1997b54758139064.rlib" "/home/dalton/dev/myumberwm/target/release/deps/libcfg_if-e0361196973a0e81.rlib" "/home/dalton/dev/myumberwm/target/release/deps/liblibc-a3e882849b8a9f37.rlib" "-Wl,--start-group" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-25c6acf8063a3802.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-539f13c9442f1597.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-37db28e905edb56b.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-9ef2480568df55af.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-1e0f0992cdbecd66.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-6c8e02b8fedc1e5f.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-807e5ad203594490.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-083fce1bea11612a.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-1af568081add9042.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-1395b54a3b3f45bf.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-caba820045f178d5.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-512eb53291f6de7e.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-5efacc5025f9f3d8.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-9c4002b5f79ba0e1.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-90996f4879673567.rlib" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-9ea09a899c3eda46.rlib" "-Wl,--end-group" "/home/dalton/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-ef2408da76957905.rlib" "-Wl,-Bdynamic" "-lxcb" "-lxcb" "-lxcb" "-lxcb" "-lxcb-randr" "-lxcb-render" "-lutil" "-ldl" "-lutil" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc"
  = note: /usr/bin/ld: cannot find -lxcb-randr
          /usr/bin/ld: cannot find -lxcb-render
          collect2: error: ld returned 1 exit status

CI is failing

We're getting

Error: fatal: unable to access 'https://github.com/yazgoo/umberwm/': The requested URL returned error: 500

I have no idea why that would happen. I tried re-running the jobs and they failed again with the same error. It was working just a few hours ago, not sure what changed.

hotkeys not working

I've tried umberwm in the past and just updated following the new README. My hotkeys would not work. After awhile i realized it needed a "mod4" parameter to select the right modifier. I added "mod4" after umberwm in umberwm-start, as shown below and all seems to be working fine now.

umberwm mod4 &>> "$HOME"/.local/share/umberwm/umberwm.log

firefox crashes on drag'n drop

when doing drag n drop within firefox, sometime the app crashes
firefox inner drag'n drop windows should be ignored by umberwm

Move main.rs into this repo

I think I get why you separated main.rs into its own repo - it kinda makes sense if you expect people to leave the main crate untouched and only modify things in the config (main.rs), but I don't think that's a likely use case. Certainly for me I want to treat this repo basically like it's DWM and customize it myself. Given that use case, having this crate as a cargo dependency of the actual binary doesn't really work, since the Cargo.toml of myumberwm just references this repo, not my personal one.

Furthermore, adding a main.rs to this crate actually wouldn't damage that use case. You could still pull this crate in as a dependency in myumberwm and only the library parts would get compiled.

That change would also enable my installer script to work (see #18). I'm not sure if that's something you want as part of this repo, but I think it improves both utility and usability quite a bit.

Is this a change you are open to?

borders / gaps per monitor

currently, border + gap config is used for all monitors
it should be optionnaly configurable per monitor

Workspace window rotations

Is there any interest in implementing workspace window rotations (90 degrees, flip x, flip y) for umberwm?

I am also developing a twm (for Windows) in Rust and using a Vec to hold workspace window state and ordering instead of a tree. I modified the geometries_bsp fn in this repo for my own use but I am struggling to understand / failing to implement a solution where I would be able to at the very least flip the positions generated so that the windows tile from the top right to the bottom left in addition to the default top left to bottom right.

Thanks in advance, this project has been a huge inspiration to me!

[Feature request] Expose keyboard keys as enum

I have to say that your project looks fastastic, small clean and also "full feature" minimalistic wm, I have only one critisism, I hate strings (error prone), so will be cool to expose Keyboard keys as an enum like winit does

umbrewm v0.0.34 installed successfully, but failed to launch on Alpine Linux (v3.16)

Installed umbrewm successfully on Alpine Linux 3.16 using cargo 1.60.0 as seen from output below...

$ cargo install umberwm

	Updating crates.io index
  Installing umberwm v0.0.34
   Compiling proc-macro2 v1.0.43
   Compiling unicode-ident v1.0.3
   Compiling quote v1.0.21
   Compiling syn v1.0.99
   Compiling libc v0.2.127
   Compiling ident_case v1.0.1
   Compiling fnv v1.0.7
   Compiling strsim v0.10.0
   Compiling serde_derive v1.0.142
   Compiling pkg-config v0.3.25
   Compiling serde v1.0.142
   Compiling log v0.4.17
   Compiling anyhow v1.0.59
   Compiling cfg-if v1.0.0
   Compiling xmodmap-pke-umberwm v0.0.1
   Compiling bitflags v1.3.2
   Compiling base64 v0.13.0
   Compiling x11 v2.19.1
   Compiling dirs-sys v0.3.7
   Compiling xcb v0.9.0
   Compiling dirs v3.0.2
   Compiling darling_core v0.13.4
   Compiling thiserror-impl v1.0.32
   Compiling darling_macro v0.13.4
   Compiling thiserror v1.0.32
   Compiling darling v0.13.4
   Compiling ron v0.6.6
   Compiling serde_with_macros v1.5.2
   Compiling serde_with v1.14.0
   Compiling umberwm v0.0.34
	Finished release [optimized] target(s) in 4m 14s
  Installing /home/teqnaz/.cargo/bin/umberwm
   Installed package `umberwm v0.0.34` (executable `umberwm`)

Full Rust Backtrace shown below...
$ RUST_BACKTRACE=full umberwm

serializing conf...
thread 'main' panicked at 'called Result::unwrap() on an Err value: Io(Os { code: 2, kind: NotFound, message: "No such file or directory" })', /home/teqnaz/.cargo/registry/src/github.com-1ecc6299db9ec823/umberwm-0.0.34/src/main.rs:161:29
stack backtrace:
0: 0x55f24959e00c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hd7af80eb76a6998a
1: 0x55f2495c40ac - core::fmt::write::h6939a8fd5b3a5e3a
2: 0x55f24959af01 - std::io::Write::write_fmt::hb5900ee4441529e9
3: 0x55f2495a0085 - std::panicking::default_hook::{{closure}}::h58a8be54ae947ef4
4: 0x55f24959fd44 - std::panicking::default_hook::h9fe353962e877b53
5: 0x55f2495a07b8 - std::panicking::rust_panic_with_hook::h0bc9d5d0acf73848
6: 0x55f2495a04c7 - std::panicking::begin_panic_handler::{{closure}}::h076ddf9c3777574c
7: 0x55f24959e4a4 - std::sys_common::backtrace::__rust_end_short_backtrace::hdbbfbc78db18e8d2
8: 0x55f2495a01e9 - rust_begin_unwind
9: 0x55f249546d13 - core::panicking::panic_fmt::h6df85570a7d78752
10: 0x55f249546e03 - core::result::unwrap_failed::h7d332eb6dadc6c7c
11: 0x55f24954cf68 - umberwm::main::hcac728d811cdd674
12: 0x55f249549943 - std::sys_common::backtrace::__rust_begin_short_backtrace::h014fa535c25ac036
13: 0x55f249549979 - std::rt::lang_start::{{closure}}::h00e782856a7b25dd
14: 0x55f24959d878 - std::rt::lang_start_internal::hddd786883f88af74
15: 0x55f24954d2d2 - main
16: 0x7f40d669aa22 -

Old windows sometimes ignore input after restart

Specifically with alacritty windows, if I have some open, then restart, then make new ones, the old ones won't receive keyboard input anymore. Strangely brave (my browser) does not have this problem.

Allowing more complicated key bindings

I spent a lot of yesterday trying to figure out how to add more flexible keybindings. For instance, I want to make the keybinding for quitting Shift+Alt+Q, because I'm much less likely to hit that by accident.

I'm writing this issue because it's proving a little more complicated than I thought it would be, so I don't have it working yet. This issue will help me track my research efforts, and if anyone wants to chime in with their expertise, that would be most welcome.

Currently umberwm does keybindings quite differently than other window managers. It reads in xmodmap -pke to generate a map of strings to keycodes. LeftWM uses x11_dl::keysym, and a really long match statement (LeftWM src: xkeysym_lookup.rs) to convert strings to keysyms. Here is the X documentation for keyboard utility functions, which let you convert between keysyms, keycodes and strings. Presumably these functions are available through xcb. I wonder if LeftWM could make use of XStringToKeysym() to avoid that long match statement. I'll try to do that here to avoid adding over 1300 lines worth of match statement to this repo lol.

In dwm, each keybinding has a mod mask (mod), a keysym (keysym), and an action (func and arg) (src).

An XKeyEvent has members state and keycode (among other things). To my understanding, keycode will be the non-mod key, while state will be the mod mask. Possibly keycode events get generated where keycode is a mod key, but those get ignored by the key handler because there won't be any keybindings set where the keycode is a mod key. I could be totally wrong about this.

In dwm, the keypress handler just loops over the keybindings and finds one where the event keycode (converted using XKeycodeToKeysym() matches the keybinding's keysym, and event's state matches the keybinding's mod (mod mask). Both the event state and the keybinding's mod mask are run through the CLEANMASK() macro, which appears to strip out any set bits other than the ones we care about, including numlock and capslock. While I've found documentation for caps lock, I can't seem to find any documentation on numlock in X. There is this baffling function updatenumlockmask() which I can't make heads nor tails of.

I think my missing knowledge of numlock will probably be my biggest obstacle right now. Other than that I think I have the knowledge to get this done. I'll try to implement it ignoring numlock, and if it becomes a problem I'll do more research.

'main' panicked at 'called `Result::unwrap()` on an `Err` value: ClosedParseErr' ../umberwm-0.0.34/src/lib.rs:28:52

RUST_BACKTRACE=full umberwm

thread 'main' panicked at 'called Result::unwrap() on an Err value: ClosedParseErr', /home/teqnaz/.cargo/registry/src/github.com-1ecc6299db9ec823/umberwm-0.0.34/src/lib.rs:28:52
stack backtrace:
0: 0x55e07e55100c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hd7af80eb76a6998a
1: 0x55e07e5770ac - core::fmt::write::h6939a8fd5b3a5e3a
2: 0x55e07e54df01 - std::io::Write::write_fmt::hb5900ee4441529e9
3: 0x55e07e553085 - std::panicking::default_hook::{{closure}}::h58a8be54ae947ef4
4: 0x55e07e552d44 - std::panicking::default_hook::h9fe353962e877b53
5: 0x55e07e5537b8 - std::panicking::rust_panic_with_hook::h0bc9d5d0acf73848
6: 0x55e07e5534c7 - std::panicking::begin_panic_handler::{{closure}}::h076ddf9c3777574c
7: 0x55e07e5514a4 - std::sys_common::backtrace::__rust_end_short_backtrace::hdbbfbc78db18e8d2
8: 0x55e07e5531e9 - rust_begin_unwind
9: 0x55e07e4f9d13 - core::panicking::panic_fmt::h6df85570a7d78752
10: 0x55e07e4f9e03 - core::result::unwrap_failed::h7d332eb6dadc6c7c
11: 0x55e07e50df13 - umberwm::umberwm::h1c9c7a6c1f2739d7
12: 0x55e07e4ffc09 - umberwm::main::hcac728d811cdd674
13: 0x55e07e4fc943 - std::sys_common::backtrace::__rust_begin_short_backtrace::h014fa535c25ac036
14: 0x55e07e4fc979 - std::rt::lang_start::{{closure}}::h00e782856a7b25dd
15: 0x55e07e550878 - std::rt::lang_start_internal::hddd786883f88af74
16: 0x55e07e5002d2 - main
17: 0x7feff230da22 -

output of uberwm.ron config:

$ cat ~/.config/umberwm.ron

(
meta: 8,
border: (
width: 1,
focus_color: 9465087,
normal_color: 0,
),
display_borders: [
(
left: 0,
right: 0,
bottom: 0,
top: 0,
gap: 10,
),
(
left: 0,
right: 0,
bottom: 0,
top: 0,
gap: 10,
),
],
workspaces_names: [
[
"1",
"2",
"3",
"4",
"5",
],
[
"6",
"7",
"8",
"9",
],
],
wm_actions: {
(
mod_mask: 12,
key: "h",
): SwapPreviousWindow,
(
mod_mask: 12,
key: "l",
): SwapNextWindow,
(
mod_mask: 8,
key: "f",
): ChangeLayout,
(
mod_mask: 12,
key: "q",
): Quit,
(
mod_mask: 8,
key: "space",
): SwitchWindow,
(
mod_mask: 8,
key: "w",
): CloseWindow,
(
mod_mask: 8,
key: "g",
): ToggleGap,
(
mod_mask: 12,
key: "r",
): SerializeAndQuit,
},
ignore_classes: [
"xscreensaver",
"Discover-overlay",
],
float_classes: [
"confirm",
"dialog",
"error",
"splash",
"toolbar",
"screenkey",
"audacious",
"Download",
"dropbox",
"file_progress",
"file-roller",
"Komodo_confirm_repl",
"Komodo_find2",
"pidgin",
"skype",
"Transmission",
"Update",
"Xephyr",
"obs",
"rofi",
"xscreensaver",
"quickmarks",
],
overlay_classes: [
"discover-overlay",
"Discover-overlay",
],
sticky_classes: {},
with_gap: false,
custom_commands: {
(
mod_mask: 9,
key: "Return",
): [
"alacritty",
],
(
mod_mask: 8,
key: "r",
): [
"rofi",
"-show",
"run",
],
(
mod_mask: 9,
key: "l",
): [
"lxlock",
],
},
command_callbacks: {
OnChangeWorkspace: [
"echo",
"change workspace",
],
},
)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.