agentsclimarketplace

Bif development

Skill ortus-boxlang/skills/boxlang-core-development/bif-development

BoxLang AI skills repository and Claude Plugin

Install
npx -y skills add ortus-boxlang/skills --skill bif-development

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use this skill when creating custom BoxLang built-in functions (BIFs): @BoxBIF annotation, invoke() method, argument handling, accessing BoxRuntime and services, BoxLang vs Java BIF implementations, member functions, and registering BIFs via modules.

SKILL.md

8.7 KB, as published. Nobody here has run it

BoxLang BIF Development

Overview

Built-in functions (BIFs) are globally available functions in BoxLang — no imports needed. When placed in a module's bifs/ directory, they are automatically discovered and registered at module load time. BIFs can be implemented in either BoxLang or Java.

BoxLang BIF

Minimal Example

// bifs/Greet.bx
// File name = function name (case-insensitive: greet, Greet, GREET all work)

@BoxBIF
class {

    function invoke( required string name ) {
        return "Hello, #arguments.name#!"
    }

}
// Usage anywhere in BoxLang (no import)
greet( "Ada" )   // "Hello, Ada!"

Full-Featured BoxLang BIF

// bifs/StringTitleCase.bx
@BoxBIF
class {

    /**
     * Converts a string to title case.
     *
     * @str The input string
     * @delimiters Word delimiters (default: space)
     * @return Title-cased string
     */
    string function invoke(
        required string str,
        string delimiters = " "
    ) {
        if ( !len( arguments.str ) ) return ""

        var words = listToArray( arguments.str, arguments.delimiters )
        return words
            .map( (w) -> uCase( left(w,1) ) & lCase( mid(w,2,len(w)) ) )
            .toList( arguments.delimiters )
    }

}

Java BIF

For performance-critical functions or when you need deep JVM access:

// src/main/java/com/example/bifs/StringTitleCase.java
package com.example.bifs;

import ortus.boxlang.runtime.bifs.BIF;
import ortus.boxlang.runtime.bifs.BoxBIF;
import ortus.boxlang.runtime.bifs.BoxMember;
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.scopes.ArgumentsScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.BoxLangType;

@BoxBIF
// Optional: also register as a member function on String
@BoxMember( type = BoxLangType.STRING, name = "titleCase" )
public class StringTitleCase extends BIF {

    // Declare argument metadata
    public StringTitleCase() {
        super();
        declaredArguments = new Argument[] {
            new Argument( true,  "string", Key.of( "str" ) ),
            new Argument( false, "string", Key.of( "delimiters" ), " " )
        };
    }

    /**
     * @param context   Current execution context
     * @param arguments Function arguments scope
     */
    @Override
    public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
        String str        = arguments.getAsString( Key.of( "str" ) );
        String delimiters = arguments.getAsString( Key.of( "delimiters" ) );

        if ( str == null || str.isEmpty() ) return "";

        String[] words = str.split( "[" + delimiters + "]" );
        StringBuilder sb = new StringBuilder();
        for ( int i = 0; i < words.length; i++ ) {
            if ( i > 0 ) sb.append( delimiters.charAt( 0 ) );
            if ( !words[i].isEmpty() ) {
                sb.append( Character.toUpperCase( words[i].charAt(0) ) );
                sb.append( words[i].substring(1).toLowerCase() );
            }
        }
        return sb.toString();
    }
}

With @BoxMember, the BIF is also callable as a member function:

"hello world".titleCase()  // "Hello World"
titleCase( "hello world" ) // "Hello World" (BIF style)

Key Java Classes for BIF Development

Class/InterfacePackagePurpose
BIFortus.boxlang.runtime.bifsBase class for all BIFs
@BoxBIFortus.boxlang.runtime.bifsMarks a class as a BIF
@BoxMemberortus.boxlang.runtime.bifsRegisters as member function
IBoxContextortus.boxlang.runtime.contextCurrent execution context
ArgumentsScopeortus.boxlang.runtime.scopesTyped argument access
Keyortus.boxlang.runtime.scopesString key interning
Argumentortus.boxlang.runtime.typesArgument descriptor
BoxLangTypeortus.boxlang.runtime.typesEnum of BoxLang types
BoxRuntimeortus.boxlang.runtimeRuntime singleton

Accessing BoxRuntime Services From a BIF

import ortus.boxlang.runtime.BoxRuntime;
import ortus.boxlang.runtime.cache.providers.ICacheProvider;
import ortus.boxlang.runtime.services.CacheService;

@BoxBIF
public class CachedFetch extends BIF {

    private BoxRuntime runtime = BoxRuntime.getInstance();

    @Override
    public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
        String url = arguments.getAsString( Key.of( "url" ) );

        CacheService cacheService = runtime.getCacheService();
        ICacheProvider cache      = cacheService.getDefaultCache();

        Object cached = cache.get( Key.of( url ) );
        if ( cached != null ) return cached;

        // Fetch data...
        Object result = fetchFromUrl( url );
        cache.set( Key.of( url ), result, 300L, 0L );  // 300s TTL
        return result;
    }
}

Accessing Context Services

@Override
public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
    // Get the current request scope
    IScope requestScope = context.getScopeNearby( RequestScope.name );

    // Get the application scope
    IScope appScope = context.getScopeNearby( ApplicationScope.name );

    // Get the session scope
    IScope sessionScope = context.getScopeNearby( SessionScope.name );

    // Resolve a variable
    Object val = context.scopeFindNearby( Key.of( "myVar" ), null ).value();

    // Invoke another function
    Object result = context.invokeFunction( Key.of( "len" ), new Object[]{ "hello" } );

    return result;
}

BoxLang BIF with Runtime Access

// bifs/GetAppSetting.bx
@BoxBIF
class {

    function invoke( required string key, any defaultValue = "" ) {
        // Access the BoxRuntime
        var runtime  = boxRuntime
        var appScope = getApplicationScope()  // available in web context

        return appScope.keyExists( arguments.key )
            ? appScope[ arguments.key ]
            : arguments.defaultValue
    }

}

Registering a BIF Alias

// Register under multiple names via multiple @BoxBIF annotations
@BoxBIF
@BoxBIF( alias = "strTitleCase" )
@BoxBIF( alias = "toTitleCase" )
public class StringTitleCase extends BIF { ... }

Member Function Registration

Member functions are BIFs callable on a specific type using dot notation:

@BoxBIF
@BoxMember( type = BoxLangType.ARRAY,  name = "shuffle" )   // array.shuffle()
@BoxMember( type = BoxLangType.STRING, name = "toSlug" )    // str.toSlug()
@BoxMember( type = BoxLangType.STRUCT, name = "deepMerge" ) // struct.deepMerge()
public class MyBIF extends BIF { ... }
[3,1,2].shuffle()
"Hello World".toSlug()   // "hello-world"
config.deepMerge( overrides )

BIF Argument Types

// Argument types available in ortus.boxlang.runtime.types.Argument
new Argument( required, type, key )
new Argument( required, type, key, defaultValue )

// Types: "any", "string", "numeric", "boolean", "array", "struct",
//        "query", "date", "function", "closure", "lambda", "class"

Testing Your BIF

// tests/specs/MyBIFTest.bx
class extends="testbox.system.BaseSpec" {

    function run() {
        describe( "greet BIF", function() {

            it( "should greet a person by name", function() {
                expect( greet("Ada") ).toBe( "Hello, Ada!" )
            })

            it( "should handle empty name", function() {
                expect( greet("") ).toBe( "Hello, !" )
            })

            it( "should be callable as member function", function() {
                expect( "Ada".titleCase() ).toBe( "Ada" )
                expect( "hello world".titleCase() ).toBe( "Hello World" )
            })

        })
    }

}
box testbox run

Discovering Registered BIFs

// List all registered BIFs (including your custom ones)
writeDump( getFunctionList() )

// Check if a specific BIF exists
if ( structKeyExists( getFunctionList(), "greet" ) ) {
    writeOutput( "greet BIF is registered!" )
}

References

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.