• Jump To … +
    server.coffee src/actionknob.coffee src/autosem.coffee src/bitbucket_kba.coffee src/browserlog.coffee src/datareduction.coffee src/dci.coffee src/dciknob.coffee src/deeseeeye.coffee src/dnd.coffee src/doof.coffee src/formurla-mngr.coffee src/fractalpanel.coffee src/fractalpanel_test.coffee src/front.coffee src/ingestor.coffee src/kbabitbucket.coffee src/knobctrl.coffee src/lib_test.coffee src/nanoclock.coffee src/noodb.coffee src/noodbabstract.coffee src/noodbbrowser.coffee src/noodbbrowser_test.coffee src/noodbsec.coffee src/noorauth.coffee src/noorplugin.coffee src/noorquery.coffee src/noorvm.coffee src/noorwrite.coffee src/quadparser.coffee src/quadparsern3.coffee src/rbac.coffee src/reactor.coffee src/rebase.coffee src/rsrcidx.coffee src/sandboxactions.coffee src/screen_ctx.coffee src/spogi.coffee src/tabular_widget.coffee src/visctrl.coffee src/voicesknob.coffee src/whowhen.coffee src/xsd2native.coffee
  • formurla-mngr.coffee

  • ¶
    try
      formurla_lib = require('formurla') # in-browser path
    catch err
      formurla_lib = require('../lib/formurla') # in mochaTest context
    Formurla = formurla_lib.Formurla
    InputStream = formurla_lib.InputStream
    TokenStream = formurla_lib.TokenStream
    
    class FormurlaManager
  • ¶

    Yes, this is called Formurla meaning formula in an url. eg /beside(above(a,b),beside(c,d)) +—+—+—+ | a | | | +—+ c | d | | b | | | +—+—-+–+ Where each of the above boxes is a FractalComponent and a,b,c and d are different kinds of content, for example a = Graph(foaf2014) b = AllegationsTable(authLog) c = SubjectsTable(authLog) d = d # the most appropriate visualizer for this identifier will display it So the real url might look like this: /beside(above(graph(g=foaf20140114.nq),allegations(authLog)),\ beside(SubjectsTable(AuthLog),d)) but really just mentioning an identifier should visualize that in the fashion the user prefers, so: /beside(authLog,systemLog,1d_2) would portray authLog, systemLog and 1d_2 with the user’s preferred visualizations for those entities, or the default visualizer, failing back to print().

    Note these points: /beside(beside,above) would actually show the code for beside and above beside one another.

    /beside(beside(),above()) would show the panes but they would be empty, ready to receive drops +—+—+—+ | | | |

         +   +   +---+
         |   |   |   |
         +---+---+---+
    

    Questions: 1) Does this mean the default front page has the formurla? /above(header,welcome) 2) Should it be shown? 3) Once logged in should it be? /above(header,beside(metaKB,intro)) 4) Those these are the appropriate formurlae, should we bother showing them? Uh, that is NOT clear! 5) Could coming up with shortcuts for formurlae help? For example the formurla /above(header,beside(metaKB,intro)) could have the shortcut /zBga which might be stored in the assertion: “above(header,beside(metaKB,intro))” which might be nestable, eg /beside(zBga,zBga) # yada yada, but you wouldn’t bother presumably

      formurla_prefix: '/__/'
      default_formurla: 'print("getting default_formurla from FormurlaManager")'
  • ¶

    default_formurla: “above(intro(),showDiv(FormurlaAstInspector),showDiv(FormurlaInspector))” default_formurla: ‘beside(print(10),intro(),print(3.14159))’ default_formurla: ‘beside(print(1),print(2),intro())’ default_formurla: ‘beside(1,2,3,4,intro())’ default_formurla: ‘above(intro(),”1”)’ default_formurla: ‘beside(intro())’ default_formurla: ‘above(beside(intro()))’ default_formurla: ‘above(beside(“NW”,”NE”),beside(“SW”,”SE”))’

      constructor: (@rootPanel, @noodb, @window, @global_args) ->
  • ¶

    pass window in, possibly a mock Ideally contexts are coming from knowledge. dragAndDropContext = dci.context(roles, interactions) someViz = dragAndDropContext.getVisualizationFor({ nodeTypeInVisualization: someType # eg: s,p,o,g,i,a,w visualizationNodeWasIn: someVisualization # eg: evaluations, subjects, graph, etc user: theCurrentUser # is this ever needed or is it available from FormurlaManager or NooDB? })

    screenContext = dci.context(roles, interactions) screenContext.visualizeThingAt({droppee: someThing, dropZone: fracPanel, visualization: someViz})

        @dci_contexts = {}
        @global_args or {}
        @global_args.default_div ?= 'blurb'
        @subscribe_to_essentials()
    
      subscribe_to_essentials: ->
        qryTerms = [{g: 'nrn:NooronDiscriminators'}]
        @noodb.subscribe(qryTerms)
    
      get_location_formurla: ->
        return @extract_formurla_from_url(decodeURI(@window.location.pathname))
    
      set_location_formurla: (the_formurla) ->
        @window.location.pathname = @formurla_prefix + the_formurla
    
      update_location_formurla: (the_formurla_or_expression) ->
        if typeof the_formurla_or_expression is 'string'
          if typeof @formurla_src is 'string'
            if @formurla_src isnt the_formurla_or_expression
              @set_location_formurla(the_formurla_or_expression)
    
      push_formurla: (formurla) ->
        url = @window.location.origin + @formurla_prefix + formurla
        @window.history.pushState({formurla: formurla}, formurla, url)
  • ¶

    If formurla is of the form: symbol eg: beside # a built-in function name (has no underscores) usr:1d # a namespaced id (has a colon) nrn:authLog # a namespaced id a1_2 # an id for something in nooron (a session, here) a1_2_1_1 # an id for something in nooron (an allegation, here) then: 1) look it up 2) find an appropriate visualization for it, eg: ‘symViz’ 3) and run symViz(symbol)

    If the formurla is of the form: symbol(…) eg: a1_2_23(nrn:1d_2, “penguin”) then: 1) look up the symbol 2) if it is executable, then run it with the arguments … 3) if it is not executable, then display an error in frac

    If formurla is of the form: literal eg: ‘tallest man 8\’11”‘ # a string with escaping “bob’s yr unk” # a string with the other quotes “line1\nline2\n” # a string with newlines 99 # a number 9.99 # a number 0xCAFEBABE # a hex number 0b11111111 # a binary number 0o31 # an octal number 2001-09-11 # a date 2001-09-11T08:43:00EDT # a dateTime then the literal is displayed in the default visualizer for that type calendar(2001-09-11) TODO Clarify when literal is an argument to an outer formurla or to be rendered

      run_formurla: (frac, formurla_or_expression) ->
        formurla_or_expression ?= @default_formurla
        @update_location_formurla(formurla_or_expression)
        expression = null
        if @a_formurla?
          expression = formurla_or_expression
        else
          @formurla_src = formurla_or_expression
          @a_formurla = @compile_formurla(@formurla_src)
          if @a_formurla.ast.prog and @a_formurla.ast.prog.length > 0
            expression = @get_first_expression(@a_formurla)
    
        if expression?
          switch expression.type
            when 'call'
              func_name = expression.func.value
              func = @resolve_function(func_name)
            when 'var'
              func = @find_visualizer_for(expression.value)
            else # eg: num, str
              func = @resolve_function('print')
              @noodb.log.error "not a func",expression
          if func?
            expression.the_function = func
            visualization = func.apply(@, [frac, expression])
            @noodb.log.info "just created visualization:",visualization
            return visualization
          else
            @noodb.log.error "function «#{func_name}» could not be resolved"
    
          if $? # if jQuery exists
            $(".formurlaAST").html( JSON.stringify(@a_formurla.ast,null,4) )
            $(".formurlaSrc").html( @formurla_src )
            $("#noorontime").show().appendTo($("#ca_2"))
    
        else
          msg = "no function found for: «#{@formurla_sr}» could not be resolved"
          @noodb.log.alert msg
          print = @resolve_function('print')
  • ¶

    oexpression.the_function = print

          visualization = print.apply(@, [frac, msg])
        return # returning null means no visualization created
    
      compile_formurla: (src) ->
        return new Formurla(src)
    
      get_first_expression: (formurla) ->
        return formurla.ast.prog[0]
    
      ast_to_src: (ast) ->
  • ¶

    this is a utility which could just as well live on Formurla

        @noodb.log.warning "ast_to_src() does not properly walk the tree"
        src = ""
        comma = ""
        if ast.type is 'call'
          src += ast.func.value
          src += "("
          for arg in ast.args
  • ¶

    src += comma

            if arg.type in ['var','num','str']
              src += arg.value
            if arg.type is 'assign' and arg.operator is '='
              src += "#{comma}#{arg.left.value}=#{arg.right.value},"
            comma = "," # not needed first time through
          src += ")"
          src = src.replace(/,,/g,',') # FIXME do not cause duplicate commas rather than removing them
          src = src.replace(/,\)/,')')
          return src
        else
          return 'print("... ast_to_src() does not know how to handle expression_ast.type' + "=#{ast.type}" + '")'
    
      replace_discriminator: (viz_inst, suppress_reload) ->
        fracpanel = viz_inst.fracpanel
        discr = viz_inst.discriminator
        viz_inst.discriminator_old
        ast = viz_inst.expression_ast
        @set_discriminator_in_ast(discr, ast)
        formurla_src = @ast_to_src(ast)
  • ¶

    console.log “FORMURLA”, formurla_src

        if not suppress_reload
          @replace_formurla(fracpanel, formurla_src)
    
      set_discriminator_in_ast: (discr, ast) ->
  • ¶

    console.log(Array(80).join(‘=’)) console.log(“set_discriminator_in_ast() <==”, JSON.stringify(ast, null, 4))

        for arg in ast.args
          if arg.left and arg.left.type is 'var' and arg.left.value is 'discr'
            found = arg
            break
        if not found # ie a discriminator was NOT found
  • ¶

    console.log “not found”

          arg =
            left:
              type: 'var'
              value: 'discr'
            operator: '='
            type: 'assign'
          ast.args.push(arg)
        if discr.uri and discr.uri.is_qname
          arg.right =
            type: 'var'
            value: discr.uri
        else
          arg.right =
            type: 'str'
            value: discr.uri and discr.uri or discr.src
  • ¶

    console.log “set_discriminator_in_ast() ==>”, JSON.stringify(ast, null, 4)

        return
    
      replace_function: (frac, new_function_name) ->
  • ¶

    Replace what is displayed in ‘frac’ with the execution of ‘function_name’ with the same arguments as the visualization function currently displayed.

        old_viz_inst = frac.visualization_instance
        expression_ast = old_viz_inst.expression_ast
        expression_ast.func.value = new_function_name
        formurla_src = "print(oink,said,the,duck,strangely)"
        formurla_src = @ast_to_src(expression_ast)
        @replace_formurla(frac, formurla_src)
  • ¶

    old_viz_inst.destroy()

      replace_formurla: (frac, formurla) ->
        @noodb.log.notice "replace_formurla() formurla:",formurla
        @previous_formurla = @a_formurla
        delete @a_formurla
        @run_formurla(frac, formurla)
    
      resolve_function: (func_name) ->
        full_name = 'BUILTIN_'+func_name
        func = @[full_name]
        if func?
          @noodb.log.info "found function #{func_name}"
        return func
    
      find_visualizer_for: (symbol) ->
  • ¶

    TODO vis_for_type < user_vis_for_type < vis_for_symbol < user_for_symbol

        @resolve_function('print')
    
      extract_formurla_from_url: (url) ->
        parts = url.split(@formurla_prefix)
        if parts.length > 1
          return parts[1]
        return undefined
    
      BUILTIN_above: (frac, expression) ->
        return if not expression.args?
        expression.args.forEach (arg,idx) =>
          if idx > 0
            frac = frac.add_sibling('south')
          @run_formurla(frac, arg)
    
      BUILTIN_beside: (frac, expression) ->
        return if not expression.args?
        expression.args.forEach (arg,idx) =>
          if idx > 0
            frac = frac.add_sibling('east')
          @run_formurla(frac, arg)
    
      BUILTIN_intro: (frac, expression) ->
        @BUILTIN_showDiv(frac, {type: "var", value: @global_args.default_div})
  • ¶

    Replace the bogus xiframes with iframes within blurb to get around the ytimg DNS timeout problem.

        Array.prototype.slice.call($("#blurb xiframe")).forEach (elem) ->
          elem.outerHTML = elem.outerHTML.replace(/xiframe/,"iframe")
    
      BUILTIN_formurlaSrc: (frac, expression) ->
  • ¶

    TODO make re-entrant by @run_formurla_src_in_panel(‘showDiv(“FormurlaInspector”)’, frac)

        @BUILTIN_print(frac, null, '<pre class="formurlaSrc"></pre')
    
      BUILTIN_formurlaAST: (frac, expression) ->
  • ¶

    @run_formurla_src_in_panel(‘showDiv(“FormurlaAstInspector”)’, frac)

        @BUILTIN_print(frac, null, '<pre class="formurlaAST"></pre')
    
      BUILTIN_showDiv: (frac, expression) ->
        window.showDiv_expression = expression
        try
          selector = "#" + expression.args[0].value
        catch e
          null
        if $? and selector
           $(selector).appendTo(frac.content_area)
           $(selector).show()
        frac.visualization_button.hide()
    
      BUILTIN_print: (frac, expression, raw_html) ->
        if not raw_html? and expression.args and expression.args[0]
          raw_html = expression.args[0].value
        frac.content_area.html(raw_html)
        frac.visualization_button.hide()
        frac.action_button.hide()
    
      makeFormurlaFromDescription: (description) ->
  • ¶

    We should call the mythical and as-yet-unavailable method pick_the_best(‘visualization’,forUser=’bob’, forThing=description)

        isa = description.thing_isa
        @noodb.log.info "makeFormurlaFromDescription()",description
        if isa is 'i'
  • ¶

    TODO make visualization ‘allegation()’ for viewing and authoring single allegations. This should probably be a degenerate form of ‘subject()’ which should essentially be a generic form

          return "allegations(i=#{description.thing_value})"
        args = []
        if isa is 'nrn:evaluationAggregation'
          vis_id = 'evaluations'
          if description.thing_cand_id?
            args.push("s=#{description.thing_cand_id}")
          if description.thing_crit_id?
            args.push("p=#{description.thing_crit_id}")
          if description.thing_graph_id?
            args.push("g=#{description.thing_graph_id}")
        else
          if description.thing_graph_id is 'nrn:metaKB' and description.thing_cand_id?
            vis_id = 'subjects'
            args.push("g=#{description.thing_cand_id}")
        if args.length
          return "#{vis_id}(#{args.join(',')})"
        if isa in ['p','s','g']
          @noodb.log.warning "processing of description.thing.value is not principled"
          return "evaluations(#{isa}=#{description.thing_value})"
        str = "  makeFormurlaFromDescription(DESCRIPTION:   "
        for k,v of description
          if k is 'viz'
            v = v.__proto__.constructor.name
          str += "#{k}=#{v}, "
        str += ") FAILED TO PLAN A FORMURLA"
        return "print(\"#{str}\")"
    
      visualizeDescriptionAtFracSide: (description, frac_id, edge_id) ->
        formurla_src = @makeFormurlaFromDescription(description)
  • ¶

    if formurla_src? alert formurla_src if console.clear? console.clear()

        msg = "FORMURLA: #{formurla_src} FRAC #{frac_id} EDGE #{edge_id}"
        @noodb.log.info msg
        frac_id ?= description.frac_id # if no frac_id then use the current one
        if edge_id?
          the_panel = @rootPanel.split_frac_on_side(frac_id, edge_id)
          @run_formurla_src_in_panel(formurla_src, the_panel)
        else
          @replace_formurla(@rootPanel.get_frac(frac_id), formurla_src)
          return
    
      run_formurla_src_in_panel: (the_src, the_panel) ->
        formurla = new Formurla(the_src)
        expression = formurla.ast.prog[0]
        return @run_formurla(the_panel, expression)
    
      getContext: (ctxName) ->
  • ¶

    Usage: screen_ctx = @formurlaManager.getContext(‘screen_ctx’)

    will load the module: ‘screen_ctx’ (a failed experiment)

        @contextCache ?= {} # assign if empty
        @contextCache[ctxName] ?= require(ctxName)
        @contextCache[ctxName].makeContext(@)
    
    (exports ? this).FormurlaManager = FormurlaManager