// title: 'Require' class for code importing // author: whillas // description: // Require files in your documents and they will be loaded in if they are one of the search paths. // First looks relative to the current document then thought search paths in the order they are added. // Add search paths with the *add() method in your startup file. So for example you might have this in your startup.scd file: // // ~mySC = "/Users/bob/Dropbox/SuperCollider/MySC"; // Require.add(~mySC ++ "/includes", true); // // then in any file you can include synthdefs or whatever you like from your /includes folder with // // Require("myCoolSynth.scd"); // // or multiple files: // // Require("player.scd", "delayeffect.scd"); // code: // Require files in your documents and they will be loaded // in if they are one of the search paths. // First looks relative to the current document then thought search paths in the order they are added. // Add search paths with the *add() method in your startup file. Will only keep one copy. // A Singleton (design pattern). Require { classvar instance; var <>searchPaths; // We actually want to mimic syntax from other languages, // so because *new is the default function on classes we can use it like: // Require("MySynthDef") and this will find the file and execute it. *new { arg ... files; ^Require.search(files) } *construct { ^super.new.init() } init { // Default path. searchPaths = [] } // Look for the file in all the searchPaths in order until we find one. // Will search for 'file' and 'file.scd'. *search { | files | var me = thisProcess.nowExecutingPath, trying, relative, paths = Array.newClear() ; if(me.isNil.not) { relative = PathName(me).pathOnly; paths = paths ++ [relative]; } { "Current document has not path! Have you saved it?".warn }; paths = paths ++ Require.get.searchPaths; if(files.isString) { files = [files] }; files.do{ | file | paths.do { | path | trying = (path +/+ file); if(trying.pathMatch.isEmpty.not and:{trying != me}) { ("Require loading: " ++ trying).postln; trying.load.postln; } } } } *get { ^( instance ?? { instance = Require.construct }) } *getSearchPaths { ^Require.get.searchPaths; } // Add a search path *add { | path, recursive | var path_list = []; if(path.isString.not) { path = path.asString; }; path = path.standardizePath; if(Require.get.searchPaths.indexOfEqual(path).isNil) { if(path.pathMatch.isEmpty.not) { if(recursive) { path_list = path_list ++ this.getSubFolders(PathName.new(path)); }; path_list.do{ | path | ("Require, adding path: " ++ path.fullPath).postln; Require.get.searchPaths = Require.get.searchPaths.add(path.fullPath); }; ^path_list } { ("Require, path does not exist: " ++ path).warn; } } { ("Require, NOT adding path, already have it: " ++ path).warn; } } // Get all the sub folders recursively // @param path PathName object // @return an Array of PathName objects *getSubFolders { | path | var result = [path]; result = result ++ path.folders.collect{ |p| this.getSubFolders(p); }; ^result.flat } }