Coder Social home page Coder Social logo

Stash List Buffer about neogit HOT 15 OPEN

neogitorg avatar neogitorg commented on July 20, 2024 1
Stash List Buffer

from neogit.

Comments (15)

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024 1

Hi, @CKolkey I submitted your changes and made a PR #1280 could you take a look at it? :)

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

Hi @TimUntersberger , I would like to implement list for stash.

image

I dug around source code and saw it already implemented here

function M.list()
return cli.stash.args("list").call({ hidden = true }).stdout
end

But I'm unsure as to how I'm supposed to link everything together. I'm not even sure if the list command is for git stash list. I did some basic preliminary work in this commit AlphabetsAlphabets@c9e8b55

from neogit.

CKolkey avatar CKolkey commented on July 20, 2024

Right on! So, you've got it right that git.stash.list() will give you the raw data you need. To get it all wired up, you'll need to:

That's pretty much it at the high level. Here's a reference of how it looks in Magit, in case you're not familiar.
Screenshot 2024-04-13 at 12 20 24

The reflog buffer has right-aligned virtual text, so you can use that as a reference on how to get the timestamp over there.

If you have any other questions, feel free to ping me here :)

Oh, and I'd recommend basing the work on the nightly branch. It probably won't be a big deal, since I haven't messed with the stash stuff as far as I recall, but it wouldn't hurt.

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

@CKolkey thanks so much for the guidance 🙏. I'll get to work on this when I can.

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

@CKolkey I know you said I can ping you whenever I have questions so I'll do that. I'm only worried it'll get excessive is all 😅 anyways so here's my question.

I'm wondering how I can get the list method to work when at the stash popup when all the options are displayed. I added actions.list to the popup builder in stash/init.lua but it's greyed out.

image

Right now, it's still greyed out. The reason I'm asking is because I'm not sure how I can test if what I've done so far is correct. I'm unsure of how to test my current progress to see if I'm on the right track.

https://github.com/AlphabetsAlphabets/neogit/blob/master/lua/neogit/popups/stash/actions.lua#L56-L58

Here, I'm wondering what's the purpose of the use method. I get that I'll need to implement my own StashListBuffer but do I need to use it together with use? From what I gathered FuzzyFinderBuffer is when you want to log a user's keypress for fuzzy finding. I'm thinking I can simply ignore use and use StashListBuffer instead.

This is the work I've manage to get done so far AlphabetsAlphabets@ea74fda

from neogit.

CKolkey avatar CKolkey commented on July 20, 2024

Hey hey - to get it to show up in the popup, you need to pass the function into the builder method as the last argument. Check out the others that have a action.* as the last argument.

You won't need to use the use() function, thats for CLI related stuff. list() is opening a new buffer, so check out the other functions that launch a buffer. The fuzzy finder is an example of that, but you can also check out the log popup for examples :)

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

@CKolkey I've been trying to figure out why there are no changes to the UI despite me modifying the source. My only conclusion is that I missed something you said and I edited the wrong files. Also FYI I'm using rocks.nvim but I don't think that should be an issue.

https://github.com/AlphabetsAlphabets/neogit/blob/master/lua/neogit/popups/stash/init.lua#L31

In here I added actions.list to the action call. But, when I restart Neogit, the option for list is still greyed out.

image

I'm not sure if I missed something that you said. In the same file I linked, I deleted the "Transform" section to see if the UI would change but no, it didn't. It is still there.

image

  local p = popup
    .builder()
    :name("NeogitStashPopup")
    :group_heading("Stash")
    :action("z", "both", actions.both)
    :action("i", "index")
    :action("w", "worktree")
    :action("x", "keeping index")
    :action("P", "push", actions.push)
    :new_action_group("Snapshot")
    :action("Z", "both")
    :action("I", "index")
    :action("W", "worktree")
    :action("r", "to wip ref")
    :new_action_group("Use")
    :action("p", "pop", actions.pop)
    :action("a", "apply", actions.apply)
    :action("d", "drop", actions.drop)
    :new_action_group("Inspect")
    -- Only way to add functionality is to add `actions.list` to `stash/actions.lua`
    :action("l", "List", actions.list)
    :action("v", "Show")
    :env({ stash = stash })
    :build()

I removed the "Transform" section locally. It isn't pushed.

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

I also did some more work to create the workflow for git stash list by adding some options to the buffer as well. I can't test it because of the issue mentioned above where changes I make have no effect. The work is done in this commit AlphabetsAlphabets@0556ef5

The reason it's different from how git log handles it is because git stash list has options you can provide. As far as I can tell, I haven't been able to find an operation in Neogit that requires you to selection an operation (like stash) then a type (like list) then options as well (like --follow). The user may want git stash list or git stash list --follow.

That's why in my commit, I decided to close the popup that is made by Z and then replacing it with options that git stash list supports after the hits l key. Once they have chosen option(s) to apply then a new tab will open which shows them the output of git stash list filtered by whatever option they specified.

The reason I don't want to create a new tab immediately like for git log is because as far as I can tell, all of the keybindings valid in the tab after :Neogit works as well. I don't know how to use features like cherry picking from the tab generated by git log from neogit.

[popups.mapping_for("CherryPickPopup")] = popups.open("cherry_pick", function(p)
p { commits = self.buffer.ui:get_commits_in_selection() }
end),
[popups.mapping_for("BranchPopup")] = popups.open("branch", function(p)
p { commits = self.buffer.ui:get_commits_in_selection() }
end),
[popups.mapping_for("CommitPopup")] = popups.open("commit", function(p)
p { commit = self.buffer.ui:get_commit_under_cursor() }

But from the lines I linked, the function to cherry pick from the new tab does exist. But may conflict with existing keybindings. This statement is based of the fact that when I was in the new tab, I can press c and have the commit options appear and v to have the revert options appear. But the more I think about it, I'm pretty sure that's just because of how LogViewBuffer is implemented. I'm not very familiar with Lua and this code base is a lot more complex than I thought it would be. Maybe, I can have Neogit create a new tab, then have keybindings specific to StashViewBuffer that'll apply options like --follow.

So to summarize

  1. Close existing popup from Z. Then replace with options for git stash list then create a new tab.
  2. Immediately list the output from git stash list in a new tab and have custom keybindings for that tab to enable flags like --follow then refresh the buffer with the output filtered based on the options selected.

I'm pretty sure 2 is the better option though. Doesn't require re-inventing the wheel.

One more thing is regarding the complexity, are there any tips you would suggest for getting familiar with the code in general? Other than referencing similar code from files and reading the comments and things like that.

from neogit.

CKolkey avatar CKolkey commented on July 20, 2024

I'm not sure if I missed something that you said. In the same file I linked, I deleted the "Transform" section to see if the UI would change but no, it didn't. It is still there.
I'm not sure how rocks works entirely, but make sure it's using the codebase you're editing. A fast way to find out is to stick a error("I got called") at the top of a file, and if there's no error... you're not loading that file.

To your other points, we can always add more options to git stash list later, for now I'd just get the basic case working. To that point, option 2 would be preferred.

You're right, its because of how the log buffer is implemented, but one of the key things about Magit, and Neogit, is that level of interactivity with everything in the buffers. So, all the popup menus would work the same everywhere, including the stash list. Fortunately, you can more or less just copy that over from the log buffer, since everything using the UI framework represents the data the same way internally. But all of those mapping can be added after you have the UI rendering something, so don't worry about that up front.

😓 I'm afraid I don't really have any tips for dealing with complex codebases besides read, read, read, and find common patterns. greping for stuff is your friend, I use that a lot. And, mostly, practice. The more you practice familiarizing yourself with different codebases, the easier it gets.

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

I'm not sure how rocks works entirely, but make sure it's using the codebase you're editing. A fast way to find out is to stick a error("I got called") at the top of a file, and if there's no error... you're not loading that file.

Yeah, you're right. For one reason or not another it wasn't being sourced. I managed to fix it by outright editing the files in the install location lol

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

@CKolkey I've managed to make decent progress! Now, I'm only confused at building the UI. I got the pieces to create a UI like Magit in your earlier comment. I've checked the examples but it doesn't quite click with me. Could you give me an example of how to build the UI?

AlphabetsAlphabets@0ba8952 is the latest commit after everything is setup.

from neogit.

CKolkey avatar CKolkey commented on July 20, 2024

Sure. You'll pass a render key to the buffer constructor like here:

render = function()
return ui.View(self.entries)
end,

Ideally, all state should get passed into the view through this, meaning the view itself shouldn't make any git.* calls.

This is a good view example:

local Ui = require("neogit.lib.ui")

You have a top level component, which has cols and rows and text components.

Don't worry about adding stuff to the common ui elements - thats where things move to once I need them in multiple places. For now, you can keep it all encapsulated in the lua/neogit/buffers/stash_list/ui.lua file.

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

@CKolkey I did all of that.

M.Stash = Component.new(function(stashes)
  local children = {}
  for _, stash in ipairs(stashes) do
    -- Split raw output as the stash_id is useful later.
    local raw = util.split(stash, ":")
    local stash_id = raw[1] -- stash@{<num>}
    local stash_msg = raw[2] .. ":" .. raw[3] -- WIP on <branch>: <commit> <msg>"
    local entry = row({
      text(stash_id), text(stash_msg)
    })


    table.insert(children, entry)
  end


  return col(children)

Above snippet from here.

I'm positive I followed the examples well but there is no output. So, I'm unsure of where the issue is. The video is the behavior I currently have.

2024-04-19.11-56-34.mp4

from neogit.

AlphabetsAlphabets avatar AlphabetsAlphabets commented on July 20, 2024

Hey, @CKolkey would you mind helping me with this? I'm still stuck unfortunately 😅

from neogit.

CKolkey avatar CKolkey commented on July 20, 2024

Try this :) (I can't push to your fork)

diff --git a/lua/neogit/buffers/common.lua b/lua/neogit/buffers/common.lua
index 8979cdfb..a6e5dd8e 100644
--- a/lua/neogit/buffers/common.lua
+++ b/lua/neogit/buffers/common.lua
@@ -219,7 +219,7 @@ M.CommitEntry = Component.new(function(commit, args)
       }, graph, { text(" ") }, ref, { text(commit.subject) }),
       {
         virtual_text = {
-          { " ",                                     "Constant" },
+          { " ", "Constant" },
           {
             util.str_clamp(commit.author_name, 30 - (#commit.rel_date > 10 and #commit.rel_date or 10)),
             "NeogitGraphAuthor",
diff --git a/lua/neogit/buffers/stash_list_view/init.lua b/lua/neogit/buffers/stash_list_view/init.lua
index 78fbbdee..c435c4c0 100644
--- a/lua/neogit/buffers/stash_list_view/init.lua
+++ b/lua/neogit/buffers/stash_list_view/init.lua
@@ -1,8 +1,7 @@
 local Buffer = require("neogit.lib.buffer")
 local config = require("neogit.config")
-local git = require("neogit.lib.git")
+local CommitViewBuffer = require("neogit.buffers.commit_view")
 
-local StashEntry = require("neogit.lib.git.stash")
 local ui = require("neogit.buffers.stash_list_view.ui")
 
 ---@class StashListBuffer
@@ -10,10 +9,9 @@ local ui = require("neogit.buffers.stash_list_view.ui")
 local M = {}
 M.__index = M
 
---- Gets all current stashes
-function M.new()
+function M.new(stashes)
   local instance = {
-    stashes = git.stash.list()
+    stashes = stashes,
   }
 
   setmetatable(instance, M)
@@ -44,11 +42,13 @@ function M:open()
           self:close()
         end,
         ["<enter>"] = function()
-          -- Still looking for how to view a stash
-          -- CommitViewBuffer.new(self.buffer.ui:get_commit_under_cursor(), self.files):open()
+          CommitViewBuffer.new(self.buffer.ui:get_commit_under_cursor()):open()
         end,
-      }
+      },
     },
+    after = function()
+      vim.cmd([[setlocal nowrap]])
+    end,
     render = function()
       return ui.View(self.stashes)
     end,
diff --git a/lua/neogit/buffers/stash_list_view/ui.lua b/lua/neogit/buffers/stash_list_view/ui.lua
index f22eb804..17245338 100644
--- a/lua/neogit/buffers/stash_list_view/ui.lua
+++ b/lua/neogit/buffers/stash_list_view/ui.lua
@@ -1,38 +1,36 @@
 local Ui = require("neogit.lib.ui")
 local Component = require("neogit.lib.ui.component")
+local util = require("neogit.lib.util")
 
 local text = Ui.text
 local col = Ui.col
 local row = Ui.row
 
-local util = require("neogit.lib.util")
-
-local StashEntry = require("neogit.lib.git.stash").StashEntry
-
 local M = {}
 
----Parses output of `git stash list` and splits elements into table
-M.Stash = Component.new(function(stashes)
-  local children = {}
-  for _, stash in ipairs(stashes) do
-    -- Split raw output as the stash_id is useful later.
-    local raw = util.split(stash, ":")
-    local stash_id = raw[1] -- stash@{<num>}
-    local stash_msg = raw[2] .. ":" .. raw[3] -- WIP on <branch>: <commit> <msg>"
-    local entry = row({
-      text(stash_id), text(stash_msg)
-    })
-
-    table.insert(children, entry)
-  end
-
-  return col(children)
+M.Stash = Component.new(function(stash)
+  local label = table.concat({ "stash@{", stash.idx, "}" }, "")
+
+  return col({
+    row({
+      text.highlight("Comment")(label),
+      text(" "),
+      text(stash.message),
+    }, {
+      virtual_text = {
+        { " ", "Constant" },
+        { stash.rel_date, "Special" },
+      },
+    }),
+  }, { oid = label })
 end)
 
 ---@param stashes StashEntry[]
 ---@return table
 function M.View(stashes)
-  return M.Stash(stashes)
+  return util.map(stashes, function(stash)
+    return M.Stash(stash)
+  end)
 end
 
 return M
diff --git a/lua/neogit/lib/git/stash.lua b/lua/neogit/lib/git/stash.lua
index f93096e8..fa2e4f6e 100644
--- a/lua/neogit/lib/git/stash.lua
+++ b/lua/neogit/lib/git/stash.lua
@@ -7,6 +7,7 @@ local M = {}
 
 ---@class StashEntry
 ---@field stash_id string the id of the stash i.e. stash@{7}
+---@field rel_date string relative timestamp
 ---@field message string the message associated with each stash.
 
 local function perform_stash(include)
@@ -129,7 +130,13 @@ function M.register(meta)
     state.stashes.items = util.map(M.list(), function(line)
       local idx, message = line:match("stash@{(%d*)}: (.*)")
 
+      ---@class StashEntry
       return {
+        rel_date = cli.log
+          .max_count(1)
+          .format("%cr")
+          .args("stash@{" .. idx .. "}")
+          .call({ hidden = true }).stdout[1],
         idx = tonumber(idx),
         name = line,
         message = message,
diff --git a/lua/neogit/popups/stash/actions.lua b/lua/neogit/popups/stash/actions.lua
index c51fa59e..8796a4dd 100644
--- a/lua/neogit/popups/stash/actions.lua
+++ b/lua/neogit/popups/stash/actions.lua
@@ -54,9 +54,8 @@ function M.drop(popup)
   use("drop", popup.state.env.stash)
 end
 
---- git stash list
-function M.list(popup)
-  StashListBuffer.new():open()
+function M.list()
+  StashListBuffer.new(git.repo.state.stashes.items):open()
 end
 
 M.rename = operation("stash_rename", function(popup)
-- 
2.44.0

from neogit.

Related Issues (20)

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.