davidgranstrom / scnvim

Neovim frontend for SuperCollider.
GNU General Public License v3.0
197 stars 26 forks source link

environment vars not evaluating #5

Closed kflak closed 5 years ago

kflak commented 5 years ago

Great work on the plugin! Getting some strange behavior, though:

Evaluating var hello = "world" works as expected.

Evaluating ~hello = "world" produces this:

ERROR: Message 'put' not understood.
RECEIVER:
   nil
ARGS:
   Symbol 'hello'
Instance of String {    (0x55c5ac9f93b8, gc=28, fmt=07, flg=10, set=02)
  indexed slots [5]
      0 : w
      1 : o
      2 : r
      3 : l
      4 : d
}
CALL STACK:
    DoesNotUnderstandError:reportError
        arg this = <instance of DoesNotUnderstandError>
    Nil:handleError
        arg this = nil
        arg error = <instance of DoesNotUnderstandError>
    Thread:handleError
        arg this = <instance of Thread>
        arg error = <instance of DoesNotUnderstandError>
    Object:throw
        arg this = <instance of DoesNotUnderstandError>
    Object:doesNotUnderstand
        arg this = nil
        arg selector = 'put'
        arg args = [*2]
    Symbol:envirPut
        arg this = 'hello'
        arg aValue = "world"
    Interpreter:interpretPrintCmdLine
        arg this = <instance of Interpreter>
        var res = nil
        var func = <instance of Function>
        var code = "~hello = "world""
        var doc = <instance of Document>
        var ideClass = nil
    Process:interpretPrintCmdLine
        arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Message 'put' not understood.
RECEIVER: nil

System: Arch Linux, urxvt, nvim v0.3.4

davidgranstrom commented 5 years ago

Hi @kflak,

Thanks! I'm happy you are trying this out, the plugin is still in it's early stages.

I'm not able to reproduce the bug you are experiencing here, could you please give me a complete example providing more context on how to trigger the error?

Also, what version of SuperCollider are you using?

kflak commented 5 years ago

Happy to be a test bunny for something so lifechanging ;-)

It's happening both in a very minimal context, literally the two lines of code above evaluated separately, as well as in a bigger setup that fails on the first env var declaration:

(
    ~projectfolder = "/home/kf/sc/primemover/";
    ~numSpeakers = 4;
    ~numMics = 4;
    ~numSubs = 2;
    ~micOffset = 4;
    ~subBus = ~numSpeakers;
    ~hasLaunchpad = false;
    ~hasQmidiNet = false;
    ~inBus = ~numSpeakers + ~numSpeakers;

    MIDIClient.init;
    // MIDIIn.connectAll;
    MIDIClient.sources.do{|device, idx|
        if(device.name.contains("Launchpad")){
            MIDIIn.connect(idx, device);
            "% connected\n".postf(device.name);
            ~hasLaunchpad = true;
        }
    };
    // if(MIDIClient.externalDestinations.asString.contains("Launchpad")){~hasLaunchpad = true};
    // if(MIDIClient.externalDestinations.asString.contains("QmidiNet")){~hasQmidiNet = true};

    Buffer.freeAll;
    s.quit;
    s.options.numInputBusChannels = ~numMics + ~micOffset;
    s.options.numOutputBusChannels = ~inBus;
    //make sure there's enough memory for the delay lines
    s.options.memSize = 65536;
    //make sure there's enough buffers
    s.options.numBuffers = 2048;
    //make sure there's enough internal buffers
    s.options.numWireBufs = 256;
    s.latency  = 0.02;
    s.waitForBoot(
        {
            if(~hasLaunchpad){
                this.executeFile((~projectfolder++"launchpad/setup.scd").standardizePath);
                "Launchpad set up".postln;
            };

            //load synthdefs
            this.executeFile((~projectfolder++"sdefs.scd").standardizePath);

            //read all samples in "audio" folder to buffers, 
            //one dictionary entry for each subfolder
            //s.sync to make sure the buffers get properly loaded
            ~buffers = Dictionary.new;
            PathName((~projectfolder++"audio").standardizePath).folders.do({|folder| 
                ~buffers.add(folder.folderName.asSymbol -> folder.entries.collect({|file|
                    s.sync;
                    Buffer.readChannel(s, file.fullPath, channels: 0);
                }));
            });
            "Buffers read".postln;

            //set up groups
            this.executeFile((~projectfolder++"groups.scd").standardizePath);
            "groups.scd done".postln;

            //create tracks 
            this.executeFile((~projectfolder++"tracks.scd").standardizePath);
            "tracks.scd done".postln;

            //patterns
            PathName(~projectfolder++"patterns").filesDo({|file| 
                this.executeFile(file.absolutePath);
                postf("% done\n", file); 
            });

            // set up minibee global variables
            this.executeFile((~projectfolder++"minibee/mbGlob.scd").standardizePath);
            "mbGlob.scd done".postln;

            // set up mbDeltaTrigs
            this.executeFile((~projectfolder++"minibee/mbDeltaTrigs.scd").standardizePath);
            "mbDeltaTrigs.scd done".postln;

            // set up mbCCs
            this.executeFile((~projectfolder++"minibee/mbCC.scd").standardizePath);
            "mbCC.scd done".postln;

            // set up light
            // if(~hasQmidiNet){
            //     this.executeFile((~projectfolder++"light.scd").standardizePath);
            //     "light.scd done".postln;
            // };

            // in the end, load the cues and pray that it works
            this.executeFile((~projectfolder++"cues.scd").standardizePath);
            "cues.scd done".postln;

            if(~hasLaunchpad){
                this.executeFile((~projectfolder++"launchpad/isasolo.scd").standardizePath);
                1.wait;
                //turn off launchpad again
                ~launchpadOut.control(176, 0, 0);
            }
        }
    );
)

produces the following output:

ERROR: Message 'put' not understood.
RECEIVER:
   nil
ARGS:
   Symbol 'projectfolder'
Instance of String {    (0x556de15fe898, gc=28, fmt=07, flg=10, set=02)
  indexed slots [23]
      0 : /
      1 : h
      2 : o
      3 : m
      4 : e
      5 : /
      6 : k
      7 : f
      8 : /
      9 : s
     10 : c
     11 : /
     12 : p
     13 : r
     14 : i
     15 : m
     16 : e
     17 : m
     18 : o
     19 : v
     20 : e
     21 : r
     22 : /
}
CALL STACK:
    DoesNotUnderstandError:reportError
        arg this = <instance of DoesNotUnderstandError>
    Nil:handleError
        arg this = nil
        arg error = <instance of DoesNotUnderstandError>
    Thread:handleError
        arg this = <instance of Thread>
        arg error = <instance of DoesNotUnderstandError>
    Object:throw
        arg this = <instance of DoesNotUnderstandError>
    Object:doesNotUnderstand
        arg this = nil
        arg selector = 'put'
        arg args = [*2]
    Symbol:envirPut
        arg this = 'projectfolder'
        arg aValue = "/home/kf/sc/primemover/"
    < closed FunctionDef >  (no arguments or variables)
    Interpreter:interpretPrintCmdLine
        arg this = <instance of Interpreter>
        var res = nil
        var func = <instance of Function>
        var code = "(
    ~projectfolder = "/hom..."
        var doc = <instance of Document>
        var ideClass = nil
    Process:interpretPrintCmdLine
        arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Message 'put' not understood.
RECEIVER: nil

Running this on sclang 3.10.0. Don't think it's a problem on the language side, as running sclang from the terminal behaves as expected. Somthing about the parsing on linux, perhaps...? Just spitballing here, don't really have any idea why...

davidgranstrom commented 5 years ago

Thanks for the repro! I still can not reproduce the error on my side though, I'll try on linux later today just to make sure. Do you have the latest version of scnvim? (I did some changes in the block-eval code a couple of days ago)

kflak commented 5 years ago

Yup, running latet version, as far as I can see (did a minpac-update just in case, and no change)

davidgranstrom commented 5 years ago

I couldn't reproduce this Ubuntu 16 (Xenial), I had an older version of SC (3.9.x) but I don't think it should matter in this case. So I'm starting to run out of ideas on what could be causing this..

If you feel up for it, you could try and add an echo statement here. Something like echomsg cmd and then check :messages after evaluating the code which triggers the error. The echoed string is the exact same as sclang receives, so then we will know if there is something wrong with the parsing on the nvim side.

kflak commented 5 years ago

OK, at least there is some way of debugging a bit...

I added echomsg cmd, and got ~hello = "world";^L

davidgranstrom commented 5 years ago

Ok, that is what I get here as well, and it is what's expected.

So I don't think this is something with the parsing in VimL but rather something going on when sending the string to stdin of the sclang process. Does it work as intended in scvim?

kflak commented 5 years ago

That's weird... used to work perfectly, now I get the same behavior there as well!

kflak commented 5 years ago

scide works, though...

madskjeldgaard commented 5 years ago

For what it's worth I just tested @kflak's code from above and it seems to work alright on my system using latest version of SC and SCNvim on MacOS 10.14.2

This is what's printed to the post window

file "/home/kf/sc/primemover/sdefs.scd" does not exist.
Buffers read
file "/home/kf/sc/primemover/groups.scd" does not exist.
groups.scd done
file "/home/kf/sc/primemover/tracks.scd" does not exist.
tracks.scd done
file "/home/kf/sc/primemover/minibee/mbGlob.scd" does not exist.
mbGlob.scd done
file "/home/kf/sc/primemover/minibee/mbDeltaTrigs.scd" does not exist.
mbDeltaTrigs.scd done
file "/home/kf/sc/primemover/minibee/mbCC.scd" does not exist.
mbCC.scd done
file "/home/kf/sc/primemover/cues.scd" does not exist.
cues.scd done
kflak commented 5 years ago

OK, a little bit further. I ignored it, because Document class has always been dysfunctional on scvim, but I am getting this on compile:

Info: 38 methods are currently overwritten by extensions. To see which, execute:
MethodOverride.printAll

compile done
localhost : setting clientID to 0.
internal : setting clientID to 0.
ERROR: Message 'dir' not understood.
RECEIVER:
class Document (0x55f5ec2aa000) {
  instance variables [19]
    name : Symbol 'Document'
    nextclass : instance of Meta_DocumentFile (0x55f5ece776c0, size=19, set=5)
    superclass : Symbol 'Object'
    subclasses : nil
    methods : instance of Array (0x55f5ec2a9500, size=4, set=2)
    instVarNames : instance of SymbolArray (0x55f5ec2aa180, size=2, set=2)
    classVarNames : nil
    iprototype : instance of Array (0x55f5ec2aa240, size=2, set=2)
    cprototype : nil
    constNames : nil
    constValues : nil
    instanceFormat : Integer 0
    instanceFlags : Integer 0
    classIndex : Integer 586
    classFlags : Integer 0
    maxSubclassIndex : Integer 586
    filenameSymbol : Symbol '/home/kf/.local/share/SuperCollider/Extensions/scide_scvim/SCNvim.sc'
    charPos : Integer 6394
    classVarIndex : Integer 378
}
ARGS:
CALL STACK:
    DoesNotUnderstandError:reportError
        arg this = <instance of DoesNotUnderstandError>
    Nil:handleError
        arg this = nil
        arg error = <instance of DoesNotUnderstandError>
    Thread:handleError
        arg this = <instance of Thread>
        arg error = <instance of DoesNotUnderstandError>
    Object:throw
        arg this = <instance of DoesNotUnderstandError>
    Object:doesNotUnderstand
        arg this = <instance of Meta_Document>
        arg selector = 'dir'
        arg args = [*0]
    Meta_Instr:initClass
        arg this = <instance of Meta_Instr>
    Meta_Class:initClassTree
        arg this = <instance of Meta_Class>
        arg aClass = <instance of Meta_Instr>
        var implementsInitClass = nil
    ArrayedCollection:do
        arg this = [*498]
        arg function = <instance of Function>
        var i = 131
    Meta_Class:initClassTree
        arg this = <instance of Meta_Class>
        arg aClass = <instance of Meta_Object>
        var implementsInitClass = nil
    Process:startup
        arg this = <instance of Main>
        var time = 0.831316912
    Main:startup
        arg this = <instance of Main>
        var didWarnOverwrite = false
^^ The preceding error dump is for ERROR: Message 'dir' not understood.
RECEIVER: Document

and it seems this is somehow related to the above errors.

kflak commented 5 years ago

Aha... one step closer still: removing SCNvim.sc from my extensions folder restores scvim to its working condition. I had a bit of trouble getting the symlink to work, so I copied the file over from the nvim package dir. Could this be a cause of the problem, perhaps?

madskjeldgaard commented 5 years ago

I actually did the same – removing SCVim and any symlinks and just hardcopying and pasting SCNvim.sc to my userExtensions folder.

kflak commented 5 years ago

Interesting... there is definitely something fishy going on with paths etc... in the Document class. When I removed SCNvim.sc from my extensions folder, the Document warnings on compile vanished as well.

kflak commented 5 years ago

Now here's the interesting bit: when I completely remove SCNvim.sc from any compile path and then run scnvim, everything works as expected. Restoring it and commenting out the Document class does the same.

davidgranstrom commented 5 years ago

Thank you all for investigating this further!

@kflak: I suspect you that you haven't installed SCNvim.sc inside Extensions/scide_scvim/SCNvim.sc? It's important that the class resides in this particular folder, otherwise you would get a "Duplicate class" error when launching the IDE/other front-ends (Document is implemented per editor). Would you mind checking that the path is correct?

On a side note, I strongly suggest the symlink approach as this will ensure you always have an up-to-date version of SCNvim.sc.

Edit: Sorry, I just read your stack trace a bit more carefully, and I see that it is indeed in the right location. It seems that the Instr class is calling Document.dir which fails because it is not yet fully implemented in scnvim (see #4). I didn't anticipate on this happening, and I'll try to find a work-around. (Maybe just comment it out as well, it would be the quick fix). In the mean time I would recommend you comment out the Document class at the bottom of SCNvim.sc as you did.

davidgranstrom commented 5 years ago

@kflak: I decided to comment out Document until #4 is merged, so if you update to the latest version of the plugin it will hopefully be resolved.

kflak commented 5 years ago

Very good, that's what I ended up doing as well. So far so good... And still I can't get the symlink to work, so I took another approach of adding the Classes dir to my sclang-conf instead.

davidgranstrom commented 5 years ago

Okay, great the hear that it's working now! And thanks for reporting this.

kflak commented 5 years ago

Sorry to necrobump a solved thread, but I just realized something going on under the hood that may or may not be useful: the Document class does not even exist on my system, as shown by this output when compiling:

ERROR: Class extension for nonexistent class 'Document'
     In file:'../../../../home/kf/.local/share/SuperCollider/downloaded-quarks/ddwGUIEnhancements/Document-scanFor.sc'

scide, however, provides its own document class...

Furthermore, I did some more digging, and it seems the original problem is in some ways related to the crucial-lib quark. I tried restoring scnvim's Document class, disabling all quarks, reenabling them one by one, and the bug popped up when cruciallib was loaded.

davidgranstrom commented 5 years ago

No worries. And yes that's correct, Document is implemented per editor/frontend. I was hoping to get away with a very crude Document implementation for scnvim which later could be extended, simply because I was mostly interested in getting thisProcess.nowExecutingPath to work. However, I think this was a bit short-sighted, since other plugins (such as crucial-lib and other quarks) might check if Document exists and if it does they would expect the API to be implemented as well.. so I will have to think about this some more.