TimUntersberger / nog

A tiling window manager for Windows
MIT License
697 stars 20 forks source link

Luajit Integration #259

Closed TimUntersberger closed 3 years ago

TimUntersberger commented 3 years ago

This PR will change the config language from our custom solution to lua.

TODO:

Documentation Todo:

TimUntersberger commented 3 years ago

I would like to hear some thoughts/ideas about the following points:

cc @ramirezmike

TimUntersberger commented 3 years ago

Regarding Moving modes to lua side:

It is now possible to unmap and map keybindings on the lua side so a prototype could look like this

local modes = {}
local old_kbs = {}
local current_mode = nil

function mode(name, cb)
  modes[name] = cb
end

function enter_mode(name)
  old_kbs = state.config.keybindings

  for _, kb in ipairs(old_kbs) do
    nog.unbind(kb.key)
  end

  modes[name]()
end

function leave_mode()
  for _, kb in ipairs(state.config.keybindings) do
    nog.unbind(kb.key)
  end

  for _, kb in ipairs(old_kbs) do
    nog.bind(kb.mode, kb.key, kb.callback)
  end

  old_kbs = {}
end

mode("resize", function()
  nog.bind("Escape", leave_mode)
end)
ramirezmike commented 3 years ago

I'll check this out more tomorrow but for this

Should we have a small lua guide in our documentation or just reference to third party documentation?

I definitely think reference third party documentation. No need to add more documentation work for us hah

ramirezmike commented 3 years ago

Moving modes to lua side

this is neat, but the amount of code feels like a lot to add to user configs. Would all that be added to the nog api in such a way that a user just needs do have this part in the config?

mode("resize", function()
  nog.bind("Escape", leave_mode)
end)

because if so, I'm cool with that. If not, would that be possible?

TimUntersberger commented 3 years ago

This PR executes a runtime.lua file on startup, before running the user config, where we can more easily introduce complex stuff to the global nog object.

Right now the file looks like this:

local function create_bind_tbl_fn(mode)
  return function(modifier, cb, tbl)
    for key, val in pairs(tbl) do
      local key = string.format("%s+%s", modifier, key)
      nog[mode .. "bind"](key, function()
        cb(val)
      end)
    end
  end
end

local function create_bind_fn(mode)
  return function(key, cb)
    nog.bind(mode, key, cb)
  end
end

nog.nbind = create_bind_fn("n")
nog.nbind_tbl = create_bind_tbl_fn("n")

nog.gbind = create_bind_fn("g")
nog.gbind_tbl = create_bind_tbl_fn("g")

nog.wbind = create_bind_fn("w")
nog.wbind_tbl = create_bind_tbl_fn("w")

nog.components = {}
nog.components.workspaces = function()
  return {
    name = "Workspaces",
    render = function(display_id)
      local c = nog.config
      local ws_ids = nog.get_active_ws_of_display(display_id)
      local result = {}
      local factor

      for _, ws_id in ipairs(ws_ids) do
        if c.light_theme then
          factor = nog.is_ws_focused(ws_id) and 0.75 or 0.9
        else
          factor = nog.is_ws_focused(ws_id) and 2.0 or 1.5
        end

        local bg = nog.scale_color(c.bar.color, factor)

        table.insert(result, {
          text = nog.get_ws_text(ws_id),
          value = ws_id,
          bg = bg
        })
      end

      return result
    end,
    on_click = function(display_id, payload)
      nog.ws_change(payload)
    end
  }
end

nog.components.datetime = function(format)
  return {
    name = "Datetime",
    render = function()
      return {{
        text = nog.fmt_datetime(format),
      }}
    end
  }
end

nog.components.padding = function(amount)
  return {
    name = "Padding",
    render = function()
      return {{
        text = string.rep(" ", amount),
      }}
    end
  }
end

nog.components.active_mode = function()
  return {
    name = "ActiveMode",
    render = function()
      local mode = nog.get_kb_mode()
      if mode ~= nil then
        mode = mode .. " is active"
      end
      return {{
        text = mode or "",
      }}
    end
  }
end

nog.components.current_window = function()
  return {
    name = "CurrentWindow",
    render = function()
      local win_id = nog.get_current_win()
      local title = win_id and nog.get_win_title(win_id) or ""

      return {{
        text = title,
      }}
    end
  }
end

nog.components.split_direction = function(values)
  return {
    name = "SplitDirection",
    render = function()
      local ws_id = nog.get_current_ws()
      local info = nog.get_ws_info(ws_id)

      return {{
        text = info.split_direction == "Vertical" and values[1] or values[2],
      }}
    end
  }
end

nog.components.fullscreen_indicator = function(indicator)
  return {
    name = "FullscreenIndicator",
    render = function()
      local ws_id = nog.get_current_ws()
      local info = nog.get_ws_info(ws_id)

      return {{
        text = info.is_fullscreen and indicator or "",
      }}
    end
  }
end

nog.config.bar.components = {
  left = {
    nog.components.workspaces()
  },
  center = {
    nog.components.datetime("%T")
  },
  right = {
    nog.components.active_mode(),
    nog.components.padding(5),
    nog.components.split_direction("V", "H"),
    nog.components.padding(5),
    nog.components.datetime("%e %b %Y"),
    nog.components.padding(1),
  }
}

The mode implementation would then live inside this file and be accesible via nog.mode.

TimUntersberger commented 3 years ago

I managed to add support for c dlls and lua runtime files.

Any file that is inside the twm/runtime file gets copied into the release zip (like in neovim). I will add a powershell command which you just have to execute to install the zip locally for ease of use.

Right now we only have luv as an external c lib.

I just built the project and copied the resulting dll inside the twm/runtime/dll folder as luv.dll. Executing require "luv" now loads the dll correctly.

The structure of the release now looks like the following:

runtime.lua get executed automatically.

TimUntersberger commented 3 years ago

If possible please give me some feedback for the documentation I recently pushed whenever you have time.

cc @ramirezmike @keepitsane @frek818

Also @ramirezmike I know the PR is massive so I won't ask you to look over the logic, but once I request a review of you could you please look over the architecture changes and design decisions I made?

ramirezmike commented 3 years ago

runtime.lua/bootstrap.lua

just to make sure I'm understanding, would this at all be user configurable or is it primarily just scripting for the "nog runtime environment" that is part of the build step?

once I request a review of you could you please look over the architecture changes and design decisions I made?

yeah, I'm trying to keep tabs on this but I'll definitely look over everything when I get a chance.

TimUntersberger commented 3 years ago

just to make sure I'm understanding, would this at all be user configurable or is it primarily just scripting for the "nog runtime environment" that is part of the build step?

This file is meant for setting up the global nog variable. Some of the implementation is on the rust side and some on the lua side. I prefer moving as much as possible to the lua side for simplicity.

TimUntersberger commented 3 years ago

Also, what do you think of some sort of "running first time" popup that directs users to the documentation? I worry about if a user just blindly downloads latest and then thinks everything is broken when it's just they need to convert their configs. Maybe it won't be an issue after this? idk

Maybe when we don't find an init.lua in the configs folder?

TimUntersberger commented 3 years ago

@ramirezmike regarding the following task

nog.plug_uninstall currently doesn't work because of permission problems

I don't know how to fix this yet. Should I wait until I fixed this or just open a separate issue and merge this? AFAIK this also doesn't work in the current master branch.

TimUntersberger commented 3 years ago

Do you think we should have a page in the docs dedicated to converting existing config files?

I guess there is no harm in doing it? Seems pretty awkward to write though. Don't really know how I should explain it.

ramirezmike commented 3 years ago

Also, what do you think of some sort of "running first time" popup that directs users to the documentation? I worry about if a user just blindly downloads latest and then thinks everything is broken when it's just they need to convert their configs. Maybe it won't be an issue after this? idk

Maybe when we don't find an init.lua in the configs folder?

that could work actually. A check for that, throw a popup up. that's probably not too crazy

ramirezmike commented 3 years ago

@ramirezmike regarding the following task

nog.plug_uninstall currently doesn't work because of permission problems

I don't know how to fix this yet. Should I wait until I fixed this or just open a separate issue and merge this? AFAIK this also doesn't work in the current master branch.

definitely separate issue, I think. The work around of "you have to delete the folder yourself" isn't too bad for something that might not come up a lot.

ramirezmike commented 3 years ago

Do you think we should have a page in the docs dedicated to converting existing config files?

I guess there is no harm in doing it? Seems pretty awkward to write though. Don't really know how I should explain it.

I'm taking notes while rewriting my config and can write something up.

ramirezmike commented 3 years ago

I'm actually having trouble compiling this. Just for the record, I compile on my linux computer and it hasn't been a problem so far, but I'm running into weird errors I think related to lua. Gonna keep trying but if not I might bite the bullet and setup my gaming pc to be a gaming/rust dev pc hah

TimUntersberger commented 3 years ago

I compile on my linux computer and it hasn't been a problem so far

for real ?? How is that possible haha?

Gonna keep trying but if not I might bite the bullet and setup my gaming pc to be a gaming/rust dev pc hah

Are you using nog on this pc?

I'm taking notes while rewriting my config and can write something up.

Please do πŸ™

ramirezmike commented 3 years ago

for real ?? How is that possible haha?

Just changing the build target. There are a couple things that need to be installed, I did it a long time ago specifically to work on nog. It does build larger executables, but aside from that I haven't really had any problems.

Are you using nog on this pc?

I completely use it for gaming, just booting it up specifically to go into steam. That said, I did manage to get it all setup today finally. For some reason I couldn't compile the main branch, it kept complaining about const fns in the parking_lot crate, but... the luajit branch works. I'm gonna keep looking at it and post more comments if needed.

ramirezmike commented 3 years ago

I'm having trouble getting focus/swapping to work right... not sure if it's my bindings

    nog.nbind("w", function() nog.ws_focus("up") end)
    nog.nbind("a", function() nog.ws_focus("left") end)
    nog.nbind("s", function() nog.ws_focus("down") end)
    nog.nbind("d", function() nog.ws_focus("right") end)

    nog.nbind("alt+h", function() nog.ws_swap("left") end)
    nog.nbind("alt+j", function() nog.ws_swap("down") end)
    nog.nbind("alt+k", function() nog.ws_swap("up") end)
    nog.nbind("alt+l", function() nog.ws_swap("right") end)

it's like... I feel like nog is swallowing these but also isn't reacting to them. Not sure, gonna look more tomorrow at this point.

TimUntersberger commented 3 years ago

I'm having trouble getting focus/swapping to work right... not sure if it's my bindings

The problem was that the conversion from the string to the enum was case sensitive. The conversion no longer is case sensitive.

ramirezmike commented 3 years ago

I was checking out the docs, what is nog/docs/api/Display.html ? It's like a blank page

Also, here configuration/keybindings.html we might want to add the keys from #261?

I think the only things I have left that I want to test out is checking out how to do some sort of config value toggling/increment/decrement. I think that's been removed, is that right? Additionally, I think maybe we should just update the README with a section that is like "Converting config.ns to init.lua" and points to another file with more information based on my notes rather than including it in the official docs, what do you think?

TimUntersberger commented 3 years ago

have left that I want to test out is checking out how to do some sort of config value toggling/increment/decrement. I think that's been removed, is that right?

Yep. I don't think there is any need for these functions anymore.

-- inc
nog.config.bar.height = nog.config.bar.height + 1
-- dec
nog.config.bar.height = nog.config.bar.height - 1
-- toggle
nog.config.work_mode = not nog.config.work_mode

Additionally, I think maybe we should just update the README with a section that is like "Converting config.ns to init.lua" and points to another file with more information based on my notes rather than including it in the official docs, what do you think?

πŸ‘

I was checking out the docs, what is nog/docs/api/Display.html ? It's like a blank page

Don't quite remember why this is here πŸ˜†. I will remove this.

ramirezmike commented 3 years ago

I added a small commit that adds a config.md file with a rough draft of some tips that I think could be useful. I think all that's missing are notes on rules, workspaces and modes.

I also added a change to twm/src/main.rs to create the config folder if it's missing. Feel free to make changes or move files if you'd like.

TimUntersberger commented 3 years ago

This seems to be ready to merge for me. Did you find anything else?

ramirezmike commented 3 years ago

This seems to be ready to merge for me. Did you find anything else?

I pushed one change (commented above) but aside from that I think it's good to go. Let me know if you agree with that behavior or not.

TimUntersberger commented 3 years ago

I agree 100%. Great work!

Thank god this is now over πŸ˜†