lamed_learn
Version:
Learning through code templates
415 lines (381 loc) • 14.8 kB
JavaScript
// llearn2.js
// Purpose: This module...
// Created by: cobolivier
// Created on: 2019/03/28
// ------------------------------------------------------
/* jshint esversion: 6 */
const _test = require('lamed_test')
const { Ok, notOk, notOk_Then, Equal, notEqual, con, testAND } = _test // eslint-disable-line
// con.traceSet(0)
con.useChalk(require('chalk'))
con.trace('Starting llearn2...')
const _fs = require('fs')
const _helper = require('./helper')
const _lio = require('lamed_io')
const _app = require('lamed_consoleapp')
_lio.About()
const _opn = require('opn') // npm i opn -s
// const _folderRecursive = require('recursive-readdir') // npm i recursive-readdir -s
const _package = require('../package.json')
const _config = _package.config
const _cmd1 = require('node-run-cmd') // npm i node-run-cmd --save
// const _cmd2 = require('node-cmd'); // npm i node-cmd --save
const _lfolder = require('lamed_folder') // npm i lfolder -s
// const _fileOpen = require('./fileopen')
const _vscode = require('lamed_vscode')
const _search = require('lamed_filesearch')
require('ltype_string')
require('ltype_date')
const _name = require('lamed_name')
// Local storage
// const _localstorage = require('node-localstorage') // npm i node-localstorage -s
// const _appSettings = new _localstorage.LocalStorage('./.appSettings')
// const _app = require('./localstorage_functions')
const _store = new _lio.LocalStorage('./.appSettings')
// Environment
// con.trace_Set(0)
const _setupEnv = _store.Get('environment', 'JSN')
const _setupEnvName = _store.Get('environmentName', '(Unknown)')
const _setupEnvGlobal = _store.Get('environmentGlobal', true)
con.trace({ _setupEnv, _setupEnvName, _setupEnvGlobal })
con.traceLine()
/* Setup the search folder */
const _setupDir = _lfolder.fromRootFolder('templates/')
let _setupSearchDir = ''
if (_setupEnv.substring(1, 2) === ':') {
_setupSearchDir = _setupEnv
} else if (_setupEnv.substring(0, 1) === '/') {
_setupSearchDir = _lfolder.fromRootFolder(_setupEnv, -1)
} else {
_setupSearchDir = _lfolder.fromRootFolder('templates/' + _setupEnv)
}
const _setupGlobalDir = _lfolder.fromRootFolder('templates/_global/')
con.trace({ _setupDir, _setupSearchDir, _setupGlobalDir })
const _os = require('os')
let folder_root = _lfolder.fromRootFolder() // eslint-disable-line
let folder_console = _lfolder.consoleFolder() // eslint-disable-line
let setup_username = _os.userInfo().username // eslint-disable-line
let folder_privatePath = _config.privateKnowledge // eslint-disable-line
con.trace({ folder_root, folder_console, setup_username, folder_privatePath })
/**
* Save the environment items
* @param setupEnv
* @param setupEnvName
* @param setupEnvGlobal
*/
function EnvironmentSet (setupEnv, setupEnvName = '(Unknown)', setupEnvGlobal = true) {
// con.logRed(`Saved to '${_appSettings._location}'`)
_store.Set('environment', setupEnv)
_store.Set('environmentName', setupEnvName)
_store.Set('environmentGlobal', setupEnvGlobal)
con.trace({ setupEnv, setupEnvName, setupEnvGlobal })
}
/* Let the user choose the default environment */
function setupKnowledgeBase (privatePath) {
/* Setup of environment */
let base = _config.knowledgebase
if (privatePath !== '') {
const privateFile = require(privatePath)
const private1 = privateFile.knowledgebase
if (private1.length > 0) {
base = base.concat(private1)
}
}
con.logGreen('\nPlease choose knowledge base:')
let no = 1
for (let ii = 0; ii < base.length; ii++) {
const item = `${no++}. ${base[ii].name}`
if (item.includes(_setupEnvName)) {
con.logGreen(item)
} else con.log(item)
}
no--
_app.readLine(`Please select option 1..${no} ?`)
.then((index) => {
const env = base[index - 1]
let globalOn = true
if (_test.notOk(env.global)) globalOn = true
else globalOn = env.global
con.trace({ env })
EnvironmentSet(env.folder, env.name, globalOn)
con.logGreen(`Knowledge base was set to:\n ->'${env.name}'; Folder: '${env.folder}'`)
})
.catch(() => {
con.logRed('You did not make a valid choice!')
// return;
})
}
/* ------[Program start here]---------- */
function llearn () {
_helper.checkParm()
.then(templateFilter)
.catch((error) => {
// console.error(error.stack);
// console.trace(); // In order to trace the source better, comment out the catch
showError(error)
})
}
llearn()
/* ------------------------------ */
String.prototype.toTitleCase = function () { // eslint-disable-line
return this.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() })
}
function editTemplate (editFile) {
if (Ok(editFile)) {
// let cmd = 'code64.bat "' + editFile + '"';
if (_lio.exist(editFile) === false) con.logGreen(`'${editFile}' does not exists.`)
const cmd = _vscode.vscodeOpenCommand(editFile)
// let cmd = _fileOpen._codeEditor + ' "' + editFile + '"'
con.logLine()
con.log(cmd)
_vscode.vscodeOpen(editFile)
// _cmd1.run(cmd, showError)
// .catch((err) => {
// con.trace({ err })
// })
} else {
con.logRed('There is no template to edit - please select one first.')
}
}
/* Execute the command line parameters - eq. search for templates for keyword */
async function templateFilter (option) {
/* Parameters are ok -> continue to format settings */
con.trace({ option })
/* Ensure template folders exist */
option.folder = _setupSearchDir
if (_lio.exist(option.folder) === false) _fs.mkdirSync(option.folder) // search folder
if (_setupEnvGlobal !== 'false') {
option.folder2 = _setupGlobalDir
if (_lio.exist(option.folder2) === false) _fs.mkdirSync(option.folder2) // global folder
}
if (option.topic === 'setup') {
/* setup */
if (_lio.exist(folder_privatePath)) {
con.trace({ folder_privatePath })
setupKnowledgeBase(folder_privatePath)
} else {
// eslint-disable-next-line camelcase
con.logRed(`Private knowledge base '${folder_privatePath}' does not exits. (Fix in package.json).`)
setupKnowledgeBase('')
}
/* templates */
} else if (option.topic === 'templates') {
// Templates
const history = _store.History()
_search.TemplateFilesShow(history)
const file = await _search.TemplateFilesSelect(history)
con.log(`You choose: ${file}`)
// historyShow(option)
/* edit || folder || create */
} else if (option.topic === 'edit' || option.topic === 'folder' || option.topic === 'create') {
let editFile = ''
let path = ''
/* create */
if (option.topic === 'create') {
// Create the file
path = folder_console // eslint-disable-line
editFile = option.keyword[0]
// con.log({editFile})
// let header = editFile.toTitleCase().replaceAll('_', ' ')
// let body = `# ${header}\n\n`
editFile = _name.nameSafe(editFile)
editFile = _lio.fileSetExtension(editFile, '.md')
const body = '# ' + _name.name2Heading(option.keyword[0]) + '\n\n\n'
editFile = path + editFile
if (_lio.exist(editFile) === false) {
_fs.writeFileSync(editFile, body)
} // move to _lio
option.topic = 'edit'
} else {
/* edit || folder */
editFile = _store.HistoryItem(1).replaceAll('/', '\\') // Change folder paths
path = _search.folderGet(editFile, '\\')
}
// con.trace_Set(0)
con.trace({ editFile, path })
// Copy path to clipboard
copy2Clipboard(path)
/* edit */
if (option.topic === 'edit') {
/* edit template */
setTimeout(() => editTemplate(editFile), 1000) // Allow for other io operations to complete
}
} else {
if (option.keyword[0] === undefined || option.keyword[0] === true) option.keyword[0] = ''
else option.value = option.keyword[0].toLowerCase()
if (option.topic === 'all' && option.keyword[0] === '') option.showFiles = false
else option.showFiles = true
/* Display search settings */
con.logLine()
// con.log(`Searching in: "${option.folder}"`);
if (option.showFiles) {
con.log('Description : ' + option.description)
con.log(`Keyword(s) : [${option.keyword}]`)
if (Ok(option.remove)) {
con.log(`Remove: : [${option.remove}]`)
}
con.log(`Topic : ${option.topic.toUpperCase()}`)
} else con.log('Description : Showing template folders')
con.log(`Environment : ${_setupEnv}`)
con.logLine()
await templateSearch(option)
}
}
async function templateSearch (option) {
let files = []
if (option.showFiles) {
// Search setup for local folder
const keys = option.keyword
// con.log({keys})
if (keys.includesAny('.') === true) {
option.folder = _lfolder.consoleFolder()
option.folder2 = undefined
option.keyword = keys.removeAny('.')
}
files = await _search.templateSearch([option.folder, option.folder2], option.keyword, option.remove)
} else files = await _search.folderSearch([option.folder, option.folder2], option.keyword, option.remove)
con.trace({ files })
_search.TemplateFilesShow(files)
const file = await _search.TemplateFilesSelect(files)
if (file) {
templateChoice(option, file)
} else {
/* No template chosen -> copy folder to clipboard */
const path = option.folder.replaceAll('/', '\\')
_app.clipboard_CopyTo(path)
con.logGreen(`-> "${path}" was copied to clipboard.`)
}
}
/* copy code 2 clipboard */
function copy2Clipboard (code) {
con.log('\n')
con.log('Copy to clipboard:')
con.logGreen(code)
_app.clipboard_CopyTo(code)
}
/* Evaluate the template choice */
async function templateChoice (option, file) {
// con.log('templateChoice');
if (option.showFiles) {
// let template = file.replace('./', _setupSearchDir)
let folder1 = ''
if (file.includes('_global_')) { folder1 = option.folder2 } else folder1 = option.folder
const template = file.replace('./', folder1)
/* copy template to clipboard */
con.logBold('You choose: ' + template)
// historyPush(template)
_store.Push(template)
let item = ''
if (template.includes('.xls')) item = 'starter.bat excel "' + template + '"'
if (template.includes('.doc')) item = 'starter.bat winword "' + template + '"'
if (template.includes('.png')) item = 'starter.bat mspaint "' + template + '"'
if (item === '') copyTemplate2Clipboard(template)
else {
// This is a document you need to open
item = item.replaceAll('/', '\\')
con.log({ item })
con.log('(Run "ll -f" for the folder)')
_cmd1.run(item).catch((err) => {
con.log({ err })
})
}
} else {
/* folder was chosen -> show folder contents */
// let template = option.files[index - 1]
let template = file.replace('./', '')
template = template.substring(0, template.length - 1).toLowerCase()
const key = template.split('/') // Make key an array
con.log(`\n\nSearching: '${key}'\n`)
// con.log({key});
option.keyword = key
option.files = key
option.showFiles = true
// con.log({option});
await templateSearch(option)
}
}
/* Read the template file and copy to the clipboard */
function copyTemplate2Clipboard (file) {
_store.Push(file)
_lio.readFile(file)
.then((code) => {
/* set standard parameters */
code = code.replace('$END$', '')
code = code.replaceAll('$DATE$', new Date().toStr())
code = code.replaceAll('$USER$', 'Perez Lamed van Niekerk')
// con.log({code});
/* search for parameters in the template */
_helper.parametersGet(code)
.then((parse) => {
if (parse !== '') {
/* replace the parameters */
// con.log({parse});
if (_test.Ok(parse.keyword1)) {
code = code.replaceAll(`$${parse.parameter1}$`, parse.keyword1)
if (_test.Ok(parse.parameter2)) {
code = code.replaceAll(`$${parse.parameter2}$`, parse.keyword2)
}
} else con.logRed('No parameter given - nothing replaced!')
}
/* Show the template in blue */
/* copy template to clipboard */
code = code.replace('/* Edit code before run */', '')
const comment = _helper.Comment(code)
if (comment) {
code = code.replace('/?' + comment, '')
con.log('\n----------------------------------------')
con.log(comment)
con.log('----------------------------------------')
}
if (file.includes('.bat')) {
code = code.replace('\n', '') // Only one liners supported for commands
// bat file
if (code.includes('http')) {
con.log({ code })
_opn(code)
con.log('\nUrl was opened.')
} else {
// var run = 'run.bat '+ code;
// con.log(code);
_cmd1.run(code).catch((err) => {
con.log({ err })
})
code = code.replace('explorer ', '') // remove 'explorer' from the command -> only folder path remains
// con.log(run);
}
} else if (file.includes('.md')) {
// Markdown file.
// let code2 = 'explorer "' + file +'"';
// let code2 = 'md32.bat ' + file;
// con.log({file});
code = _search.folderGet(file, '/').replaceAll('/', '\\') // Get the folder of the file.
_vscode.vscodeOpen(file)
// con.log({code});
// let code2 = 'code64.bat ' + file;
// let code2 = _fileOpen._codeEditor + ' "' + file + '"'
// con.log(code2)
// _cmd1.run(code2).catch((err) => {
// con.log({ err })
// }) // this will only work for windows;
}
// Copy code the clipboard
// con.log("123423");
copy2Clipboard(code)
})
.catch(showError)
})
.catch(showError)
}
/**
* show error message in red
* @param {string} error - the error to show
*/
function showError (error) {
con.log()
con.logLine()
con.logRed('Catch -> ' + error)
con.logLine()
console.error(error.stack)
_helper.help_parameters()
}