4coder » Forums » Bugs in the Customization API
teryror
Tristan Dannenberg
7 posts

Simultaneously a dreamer and an early quitter

#12723 Bugs in the Customization API
3 months, 2 weeks ago Edited by Tristan Dannenberg on Aug. 3, 2017, 7:37 a.m.

Hi Allen,

I've been working on some rather involved customizations, essentially replacements for special emacs modes I used to use (or would have, had I invested some more time into learning them). I've come across some bugs in the 4coder API, as well as some (simple?) things that would make my time with this a whole lot easier.

  • Opening more than 8 Query_Bars at once crashes 4coder:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    CUSTOM_COMMAND_SIG(repro_query_bar_crash) {
        Query_Bar qb = {0};
        qb.prompt = make_lit_string("Prompt: ");
        qb.string = make_lit_string("Some text...");
        
        for (int i = 0; i < 9; ++i) {
            start_query_bar(app, &qb, 0);
        }
        
        // We won't even make it here
    }
      
    

    I assume this is because they were not intended to be used the way I did. I built my own fuzzy string matcher, and essentially tried to replace the interactive_open UI by opening and closing these as the user types. Limiting the number of files shown to 7 (leaving the 8th bar for input) solved the problem.
    This turned out to work so well that I used the same infrastructure to build other fuzzy lists, e.g. for selecting an arbitrary command to execute. What I really would have liked is to just have some function that displays the UI, but uses the string matcher and list of strings I provide.
  • directory_cd doesn't do anything unless rel_path is "..". I can't really provide repro code here, because the command is supposed to fail if the specified relative path does not exist, and I don't know the directory contents you will be testing with.
    (Edit: It just occured to me that this one is almost certainly platform dependent. All of this is on Windows 8.1)
  • This is the one that surprised me the most: using buffer_set_setting to set BufferSetting_MapID exhibits really strange behaviour: if the specified mapid is anything other than 0, mapid_global (0x01000000), or mapid_file (0x01000001), the call silently fails and the buffer's mapid will be set to mapid_file instead.
    Speaking of buffer settings, I would also really like to associate some arbitrary information with a buffer that can be retrieved later. For example, when opening a buffer in *hex* mode, I create a new buffer where the actual byte values will be pretty printed. Many commands interacting with the hex buffer need to also reference the source buffer (i.e. the one viewed through the hex buffer). This relation could be expressed by storing the source buffer's buffer_id with the hex buffer.
I know you have a lot on your plate; the feature requests here are mere suggestions, of course.

I'm still in the process of upgrading my customization code to the newest 4coder version (which I've been meaning to do for nearly half a year now!), and heavily improving on my old implementation of these bigger features. That's why I won't share the actual customization code yet - most of it isn't done yet.
That's just a matter of time, though. Hacking on 4coder has been my go-to programming activity ourside of work for the past week or so, and it is tremendous fun.

Thanks again for making such a fantastic tool!
Cheers
Mr4thDimention
Allen Webster
283 posts
2 projects

Heyo

#12766 Bugs in the Customization API
3 months, 2 weeks ago

I'm glad you are at least having fun with it!

These are all pretty interesting issues you've brought up, so I'll break them down and address them one at a time.

1. Query Bars are intentionally limited to 8 per view because they were never meant as the long term GUI solution, but just a hack that unfortunately stayed in the code for too long. The idea of a more general GUI system, where you can specify a list of strings such as in the file list, as well as many other GUIs you might want, is a big part of what I have been thinking about behind the scenes. These problems will start getting solved in 4.1.0 and later builds.

2. This directory_cd thing is a bit surprising. I will dig into it a bit. A few things that might be going wrong are not using a full path for dir, or not using backslashes.

3. Hmm. I'm not sure what could be going wrong with the mapid. The default customization uses a custom command map for code files and that works, so I would need a repro case for this one.

As far as extra custom variables set on a buffer, that is a really good point. The sticky jump code had the same problem and I just implemented a hash table to map buffer ids to extra memory, but I don't want to force everyone else to write hash tables too... I'll have to think about the right way to solve that one for a bit.
teryror
Tristan Dannenberg
7 posts

Simultaneously a dreamer and an early quitter

#12789 Bugs in the Customization API
3 months, 2 weeks ago Edited by Tristan Dannenberg on Aug. 5, 2017, 4:14 p.m.

I sort of expected you would want a repro case for that, but it really is as simple as it sounds. I too did think I was misusing the API somehow, but after stepping through the assembly for a bit, it seems that you loop over the list of all maps to verify that the specified mapid has been initialized, but somehow end up defaulting to mapid_file anyway?

I'm not sure, I suck at reading x86 assembly, and didn't want to step on your toes by reverse engineering too much.

Here is a full config that creates two command maps, with ID 0 and 1 respectively, and sets the *scratch* buffer to use mapid 0.

You can press the spacebar to run a command that should essentially just trigger an assert that a buffer_set_setting call did what it was supposed to do. You can also comment out said assert to verify that the map has not been set at all, and it's not just the local Buffer_Summary that's not getting updated. (The commands are bound properly, as far as I can tell by using inherit_map, though I don't show that here)

But maybe I AM misusing the API in some way and just going insane?

---

As for directory_cd, here is some code that is roughly equivalent to what I do already (which should work, if I read the documentation right):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
CUSTOM_COMMAND_SIG(repro_cd) {
    char hot_dir_space[1024];
    String hot_dir = make_fixed_width_string(hot_dir_space);
    hot_dir.size = directory_get_hot(app, hot_dir.str, hot_dir.memory_size);
    
    File_List hot_files = get_file_list(app, expand_str(hot_dir));
    for (uint32_t i = 0; i < hot_files.count; ++i) {
        if (hot_files.infos[i].folder) {
            int32_t old_size = hot_dir.size;
            
            directory_cd(app, hot_dir.str, &hot_dir.size, hot_dir.memory_size, hot_files.infos[i].filename, hot_files.infos[i].filename_len);
            
            // This should crash also
            Assert(old_size != hot_dir.size);
            
            break;
        }
    }
}


(I do some more error checking in my own code, but as I said, it fails silently, for me anyways)

With that, thank you for all your efforts!
Mr4thDimention
Allen Webster
283 posts
2 projects

Heyo

#12791 Bugs in the Customization API
3 months, 2 weeks ago

Okay I think this will work perfectly, I'll get these on my bug list and get back to you when I can.
teryror
Tristan Dannenberg
7 posts

Simultaneously a dreamer and an early quitter

#13198 Bugs in the Customization API
1 month, 2 weeks ago

Wow, a lot of time has passed where I couldn't really work on my customizations.

But since I've been sick all week, I decided to finally go back and finish what I needed before publishing the code. It can now be found on my GitHub, but there's still some cleanup left to be done, and probably some bugs left to be fixed. As always, there's also a lot of nice-to-haves I still haven't gotten around to (most of which can be found by searching the repository for TODO comments).

One of those is a git interface, which I started working on today, as well as mouse input support for the other command packs. Unfortunately, I can't really make progress on either because of more issues with the customization API.

First: exec_system_command. It works fine if you want to actually display the command line output to the user or run another graphical application, but I want to use the machine readable modes of the user-installed git executable, and parse the output immediately. This does not seem to be possible, as the command is executed asynchronously and there's no way to just wait for it to finish.

I'd like a separate function that works more like get_user_input (i.e. block the execution of the current command until the result is ready). While we're at it, it'd be great if that version just returns the status code of the executed command, rather than appending it to the text output.

Even with that, I don't see a good way to add support for git push and git pull, which may query the user for a name and password. If git accepted those as command line arguments, it'd be no problem, but that's apparently a bad idea for security reasons. The alternative is using SSH keys for authentication, but requiring that for the frontend to be functional doesn't seem great, though I can't really imagine what an API for sending user input to the other process should look like.

Speaking of get_user_input, it exhibits rather strange behaviour when called with the EventOnMouse flags:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
CUSTOM_COMMAND_SIG(repro_mouse_input_weirdness) {
    View_Summary active_view = get_active_view(app, AccessAll);
    View_Summary test_view = open_view(app, &active_view, ViewSplit_Bottom);
    
    while (true) {
        User_Input in = get_user_input(app, EventOnLeftButton, 0);
        
        if (in.abort) {
            // NOTE: This will be reached in the iteration after the mouse
            // button release event, even if we don't produce any more input,
            // though this seems to depend on which view you click in?
            Assert(false);
        } else if (in.type == UserInputMouse) {
            // Pretend we actually do something here
            continue;
        }
    }
    
    close_view(app, &test_view);
}


In the code where I stumbled across this issue, this actually causes a crash inside 4coder after the command has exited, though I can't seem to find a simple repro-case for that. I imagine this might be because I don't clean up properly, since I use a lot of temporary views in weird combinations with view_set_highlight.
Mr4thDimention
Allen Webster
283 posts
2 projects

Heyo

#13201 Bugs in the Customization API
1 month, 2 weeks ago

Thanks for the update! I'll take this all into consideration. For now, I will just clarify how the current system is meant to work with get_user_input.

Even if you don't request an abort on any type of input, there is always a way to abort a command and that is by changing the active view by clicking on (and releasing on) a different view. Whether or not that behavior is intuitive usually depends on the user and what they are trying to implement. In a new iteration of the API, input would not exist on a per-view basis like it does now, and you would be able to have commands take mouse input across multiple views, but the current architecture of the system does not allow that.

Hope that helps in some way.
teryror
Tristan Dannenberg
7 posts

Simultaneously a dreamer and an early quitter

#13202 Bugs in the Customization API
1 month, 2 weeks ago

Ahh, I guess that makes sense.

I really only added mouse support for completeness before releasing my customizations, since I try to not actually use the mouse in my own workflow, so I never noticed that pattern. Looks like I can't actually do that for the find-and-replace GUI, then. At least for now.

Looking forward to the next builds!