autocomplete next steps

surya spent several hours with me helping me strategize about next steps for autocomplete. i’m quickly putting some notes here so i remember:

  1. write the tern definition file for *one* piece of the p5 source code *by hand*. this will give me the ability to see how autocomplete works when it does what i want to. he suggested p5.image because it has the most logical schema, i.e. a prototype with private methods. much of the rest of p5 is add-ons to one global p5 object.
  2. specifically, parse every line that starts p5.image.prototype as well as the @method for that object
  3. once that’s done, test the def file in the tern.js demo. like the one here but forked and cloned with the new p5 def file added.
  4. once that’s working, create a python script to read into every p5 source file and repeat the process i went through with p5.image.

Google Summer of Code Final Submission

My original proposal was to implement autocomplete in the p5.js web editor. Here’s an excerpt:

 

The p5 web editor is currently in development, with plans to launch in time for fall semester classes. Currently, there’s no autocomplete code functionality and it’s not possible to access documentation from within the editor. We could use tern.js to solve both of these problems. Tern.js is a code-analysis engine for Javascript that works with CodeMirror, the code editor behind the p5 web editor. In addition to autocomplete, tern.js supports shortcuts to documentation and the ability to easily rename all occurrences of a variable. 

 

The p5.js web editor uses React for the front-end and is built on top of CodeMirror, a code editor for the browser.

I’ve been trying to hook up Tern.js—”a standalone Javascript analysis engine”—to implement autocomplete.

Tern relies on a JSON file called a Tern definition file in order to “specify the types of things” you code and trigger different autocomplete functions accordingly. You can read more about that file here.

Part of getting Tern working with p5.js is creating a Tern definition file for the p5.js library so that, when you’re writing in the editor, Tern can analyze what you’re writing. Tern has a utility to do this, but it didn’t work with the p5.js library.

As a hacky workaround, I adapted some scripts that convert YUIDoc documentation into Tern definition files. Repos are linked below. Because p5.js documentation is generated with YUI/YUIDoc, this sort of worked: you can trigger docs on p5 functions and autocomplete p5 function names.

But there’s a scoping problem where methods and variables that should not be available to certain functions still appear as autocomplete options.

As of August 2017, I’m trying a new approach to generating the Tern definition file.

Repositories

  1. My branch of the p5 web editor connected to Tern: https://github.com/kaganjd/p5.js-web-editor/tree/autocomplete. To get it up and running, you’d follow steps in the README.
  2. Code to generate the Tern definition file for the p5.js library: https://github.com/processing/p5-tern.yuidoc. This is set up to be a module dependency of the main p5.js repository and executed with a Grunt task from there.
  3. Documentation re: errors when running the Tern definition generator code: https://gist.github.com/kaganjd/32c87c49fda5f61b78aa2b88993daca4
  4. Next steps: https://gist.github.com/kaganjd/1e033541fa00af3e760c0acddf6fc197

The workflow for this whole thing in the wild will be:

  1. Generate Tern definition file from the main p5.js project by running grunt tern
  2. Put the file output of that process, which should be a JSON file and must be named ‘p5.json’, into the p5.js web editor project—specifically, p5.js-web-editor/node_modules/tern/defs
  3. Use autocomplete with the web editor!

Other docs

External docs

ui issue for herbivore

surya’s been helping me wrap my brain around vue/vuex so i can do more coding work on herbivore. i filed what i thought would be an easy issue in order to get started:

in my head, i was like, “oh, change the css :hover styling and call it a day.” did not take me long to discover that: no. u see, we’re changing the ui dynamically based on information we’re getting from the network. vue and vuex let you manage all this information by setting the starting state and then defining stuff you want to happen based on new information you get (with getters), actions you do, and mutations that occur to the state based on those actions. what follows is a walk-through of my process, written in present tense even though it’s already done because tense is confusing sometimes. here we go.

Continue reading “ui issue for herbivore”

dummy sites for herbivore

eve and i put up some really basic form websites, one on HTTP and one on HTTPS, because we want to demo how HTTP form submissions are totally interceptable. the sites need some cleanup, but the test was still helpful and i think we’re on the right track! check it out:

form-test

update: the application formerly known as ajooba

we had our first semi-official user testing session! i made a document that i thought could guide our session, but it was actually hard to stick to once we got started. i think for future user testing sessions, none of us devs/designers should be in the room because we talk too much and wanna go into great detail about what we ~intended~ with different features. we still got great feedback because we were showing the tool to people who know a ton about teaching and technology. next time will be a more formal thing, and i think we’ll write a script/list of objectives for someone else to administer.

eve took amazing notes, which we converted into a list of issues file-able on github:

she’s busy animating transitions that will hopefully make some of the information we’re conveying more intuitive to understand. i’m really excited about what she’s working on.

meanwhile, i’ve been trying to wrap my brain around the code base since i stopped keeping up with it after surya did a big awesome refactor a few months ago. the front is vue.js with vuex. the back is node.js. the back talks to the front via sockets. that’s about where i’m at right now. i made this sketch of vue files:

and am redoing the annotated file tree exercise:

/Users/jkagan/Desktop/herbivore
|-- NOTES.md
|-- README.md
|-- app
|  |-- App.vue
|  |-- components
|  |  |-- Console.vue
|  |  |-- InfoBar.vue
|  |  |-- NavMenu.vue
|  |  |-- ToolBar.vue
|  |  |-- tools
|  |  |  |-- Network.vue - frontend table for network view (columns, ability to sort, etc)
|  |  |  |-- Sniffer.vue - frontend table for sniffer view (columns, ability to sort, key code shortcuts. etc)
|  |  |  -- SnifferPayload.vue - frontend window for payload view in sniffer tool; this is where the HTTP vs HTTPS text lives
|  | 
-- viz
|  |     |-- Grid.js
|  |     |-- Viz.vue - for testing; deleted
|  |     |-- VizTree.vue - vue template for visualization area
|  |     -- VizTreeStyleParams.js
|  |-- filters
|  | 
-- index.js
|  |-- main.js - everything that's in the app div, rendered in index.html
-- store
|     |-- modules
|       |-- sniffer.js - includes actions, getters, mutations re: newPacket, clearSnifferInfo
|       |-- toolbar.js - includes actions, getters, mutations re: currentTool, currentView, toolRunning, toolNames, clearToolbarInfo
|      
-- network-info.js
|     |-- actions.js
|     |-- getters.js
|     |-- index.js
|     -- mutation-types.js - this is basically a list of all the ways to commit new data to the vuex store. this is how state is updated in network view, sniffer view, and toolbar side panel. all these mutation types are used in the 'modules' files: sniffer.js, toolbar.js, network-info.js
|-- assets
-- imgs
|     -- play.png
|-- dist
|  |-- build.js
-- public
|     -- fonts
|        |-- photon-entypo.eot
|        |-- photon-entypo.ttf
|       
-- photon-entypo.woff
|-- fonts
|-- herbivore-darwin-x64 - binary
|-- index.html - thing that renders app div from app/main.js, build.js script
|-- main.js - first thing to launch. sets new browser window, sets sudo permissions for sniffing, sets sockets that talk to vue.js and network scripts
|-- network-scripts
|  |-- Network.js - network constructor function; outputs to terminal. to init, _getHostNamePromise, _getHostName, _scanArpTable, _pingSubnet, _getAllHostnames, _checkHost, _getHostBuffer, cmd, start, stop
|  |-- Sniffer.js
|  |-- ToolManager.js
|  |-- old
|  |  |-- pcap-parser.js
|  |  -- tcp-test.js
-- pcap-filters.js
|-- package.json
|-- styles - photon styling, plus old scss stuff
|  |-- main.scss
-- photon.css
-- webpack.config.js - webpack builds the dist/build.js file that's rendered in index.html

‘how the web works’ workshop feedback

i’ve been working at the glass room as an “inGenious” and taught an hour-long workshop there on saturday about how the web works. everyone who does a workshop has been sending feedback to everyone else so we can all be more prepared next time we teach. here’s what i said about mine:

hey! here’s feedback from the workshop i did saturday at 3pm:

there were a whole bunch of people (30-40?), so we couldn’t go around and do names/intros. but we did write our names on tape as name tags, which i found helpful and i hope they did too since they had to do an activity together.

i started with an intro and then asked what folks were interested in. the responses were generally either ‘knowing more about infrastructure’ or ‘knowing specific things to do to protect my privacy’

then, i handed out the internet infrastructure cards- about one set per 6-7 people, which i think worked okay. the groups finished laying everything out very quickly, like less than 10 minutes. i asked groups to share out how this activity went for them and there were a few sentiments:
– ‘i thought i knew how this worked, but when i had to lay everything out, i realized there were some gaps in my knowledge’
– ‘what’s a national gateway?’

– ‘why are there two computers?’

in general, i think the cards were really helpful for people. on reflection, and after reading the feedback forms, i think i should have spent more time going over each element in the set of cards instead of only having groups explain their own layouts. i think i also should have done a better job explaining why there are multiple right answers and your configuration could have routers, servers, etc in a different place than other groups.

after doing the big picture stuff, i showed some links that i put together: kaganjd.github.io/how-the-web-works

people were *really* into the submarine cable map!

i used that + infrastructure cards to say that the internet is physical and that there are different places along the line where info can be intercepted. then, i went into vpn vs. tor vs. https. i explained a little bit of the technical stuff and tried to just reiterate over and over again that people should def get ‘https everywhere’ (free!) and try a 2-week free trial of cloak vpn. people had fairly technical questions about vpn’s- how do they work? do i need one at home? does it encrypt everything? etc., so i’d be ready for that (many thx to sara for helping me navigate those!)

there were 2 kinda derailer/mansplainy guys. a way i tried to address them was listen for a little bit, nod my head, and then try to tie something they said back to something someone said earlier or a question someone else asked. then, i could shift the mic to the new person and we could eventually get back on track.

so yeah! it was fun! if you’re teaching this one and have q’s about any of this, let me know!

“change sketch routes” PR walk-through

cassie walked me through a web editor issue that i was having a lot of trouble with. i learned a ton, so i’m documenting the process here.

we wanted to change sketch routes so that sketch URLs included the sketch username because that just makes more sense!

screen-shot-2016-11-30-at-5-51-42-pm

but within the editor, there are client-side routes and server-side routes.screen-shot-2016-11-30-at-5-53-56-pm

screen-shot-2016-11-30-at-5-53-28-pm

cassie explained the difference between these:

  • the server-side routes—which live in server.routes.js—render html. when a user initiates a session, they get data via these routes.
  • the client-side routes—which live in routes.jsx—render a react.js view. when a user doesn’t need a whole new session but just needs some data populated from a small portion of the editor, the interaction usually just makes an ajax request. an ajax request means that the entire page doesn’t have to refresh, so the new content gets loaded more quickly.

there is another set of server-side routes: the api routes, which are internal to the server-side. these endpoints serve JSON data, which is then used to populate react views on the front-end. we didn’t mess with api routes for this PR, but they’re important to know about.

in order to create our sensible new sketch routes, we edited 7 files in total but these were the 2 most important ones:

  • server/routes/server.routes.js
  • client/routes.jsx

so, in order, here’s how we did things:

  1. create a server-side route— /username/sketches/id —the response calls the function renderIndex() which renders the whole appscreen-shot-2016-11-30-at-5-49-53-pm
  2. create a client-side routescreen-shot-2016-11-30-at-6-07-31-pm
  3. then, we had to make sure that all the places in the web editor where you’d click to navigate to a particular sketch—from the sketch list, or to clone a project, or to share a project, or to create a new project, or to save a project—used the correct route to get the sketch you wanted. this is the kind of navigating within the app, as opposed to getting data from the server, that happens via ajax requests. here’s a photo of a link in the sketch list view so you have a sense of what i mean:screen-shot-2016-11-30-at-6-14-15-pm
  4. here’s how we changed the route in the SketchList.jsx file:screen-shot-2016-11-30-at-6-44-54-pmline 28 says: “if props.username is not undefined (so, it exists), then use it to build the route in line 68. otherwise, use props.user.username to build the route.”
  5. rinse and repeat for other places within the front-end where sketches are accessible from. review the pr to see them in detail.

things i found challenging:

  • knowing which react components had access to which props
  • the significance of step 2/the client-side route
  • wrapping my head around the api routes and how the JSON files at their endpoints ultimately get back to the front-end

the past few weeks

  • djt was elected president
  • i participated in 32 hours of training with tactical tech and mozilla leading up to working in the glass room, an exhibition and workshop space i’m so excited about
  • the tisch restroom policy committee met to start drafting a statement and signage plan for gender-neutral bathrooms throughout the building. it’s been heartening to work with professors and administrators who care about making tisch work for their trans and gender non-conforming students and colleagues.
  • i saw anna deveare smith’s tremendous show, notes from the field. trying to channel her generosity and energy the next four years++

fixing a bug in p5 textAlign()

lauren flagged this textAlign() bug as beginner-level, so i started digging into it. the problem was that you couldn’t center more than one line of text vertically within a bounding box. the textAlign() function would only center the block of text in relation to the first line—so the first line would be centered vertically, but the rest would be off. you can see what i mean in the video below.

riveting silent film of working on a p5.js bug

solution

to find the problem, i had to dig around in different parts of the p5.js file—doing ctrl + f “renderText” and “finalMaxHeight” and “Renderer2D” etc. to see how all the functions and constants were connected/talking to each other. eventually, i narrowed it down to this little else{} section of the textAlign() function. previously, this.renderText didn’t account for any offset you need with more than one line of text. so lauren helped me think through the math and we created the variable, offset.

Screen Shot 2016-04-22 at 3.34.55 PM

the code says:

the offset amount equals number of lines of text (that’s what cars.length gives us),

divided by two (that’s how you center something)

minus half a line of text (because when we use the CENTER argument, half the height of one line is baked in to that constant),

all multiplied the text leading (or, line height).

for all text you render, put the text itself, spread across however many lines, starting at location x, at location y minus the offset.

then, add line height for each line.

i also found the documentation in the reference to be really counter-intuitive so i added some more explanation. from this:

“Sets the current alignment for drawing text. The parameters LEFT, CENTER, and RIGHT set the alignment of text in relation to the values for the x and y parameters of the text() function.”

to this:

“Sets the current alignment for drawing text. Accepts two arguments: horizAlign (LEFT, CENTER, or RIGHT) and vertAlign (TOP, BOTTOM, CENTER, or BASELINE).

The horizAlign parameter is in reference to the x value of the text() function, while the vertAlign parameter is in reference to the y value.

So if you write textAlign(LEFT), you are aligning the left edge of your text to the x value you give in text(). If you write textAlign(RIGHT, TOP), you are aligning the right edge of your text to the x value and the top of edge of the text to the y value.”

hopefully that’ll be helpful.

instructions for creating the pull request

p5 development

preparing a p5 pull request