fix: Add autocompletion items in Server Script

- API to add autocompletion items in Code field
This commit is contained in:
Faris Ansari 2021-04-17 23:09:16 +05:30 committed by Suraj Shetty
parent bcd2a3a986
commit 43f3ba3cba
4 changed files with 79 additions and 2 deletions

View file

@ -18,7 +18,7 @@ global_cache_keys = ("app_hooks", "installed_apps", 'all_apps',
'scheduler_events', 'time_zone', 'webhooks', 'active_domains',
'active_modules', 'assignment_rule', 'server_script_map', 'wkhtmltopdf_version',
'domain_restricted_doctypes', 'domain_restricted_pages', 'information_schema:counts',
'sitemap_routes', 'db_tables') + doctype_map_keys
'sitemap_routes', 'db_tables', 'server_script_autocompletion_items') + doctype_map_keys
user_cache_keys = ("bootinfo", "user_recent", "roles", "user_doc", "lang",
"defaults", "user_permissions", "home_page", "linked_with",

View file

@ -9,6 +9,12 @@ frappe.ui.form.on('Server Script', {
if (frm.doc.script_type != 'Scheduler Event') {
frm.dashboard.hide();
}
frm.call('get_autocompletion_items')
.then(r => r.message)
.then(items => {
frm.set_df_property('script', 'autocompletions', items)
});
},
setup_help(frm) {

View file

@ -5,11 +5,12 @@
from __future__ import unicode_literals
import ast
from types import FunctionType, ModuleType
from typing import Dict, List
import frappe
from frappe.model.document import Document
from frappe.utils.safe_exec import safe_exec
from frappe.utils.safe_exec import get_safe_globals, safe_exec, NamespaceDict
from frappe import _
@ -122,6 +123,26 @@ class ServerScript(Document):
if locals["conditions"]:
return locals["conditions"]
@frappe.whitelist()
def get_autocompletion_items(self):
def get_keys(obj):
out = []
for key in obj:
if key.startswith('_'):
continue
value = obj[key]
if isinstance(value, (FunctionType, ModuleType)):
out.append(key)
elif isinstance(value, (NamespaceDict, dict)):
out += [f'{key}.{subkey}' for subkey in get_keys(value)]
return out
items = frappe.cache().get_value('server_script_autocompletion_items')
if not items:
items = get_keys(get_safe_globals())
frappe.cache().set_value('server_script_autocompletion_items', items)
return items
@frappe.whitelist()
def setup_scheduler_events(script_name, frequency):

View file

@ -31,6 +31,56 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({
const input_value = this.get_input_value();
this.parse_validate_and_set_in_model(input_value);
}, 300));
// setup autocompletion when it is set the first time
Object.defineProperty(this.df, 'autocompletions', {
get() {
return this._autocompletions || [];
},
set: (value) => {
this.setup_autocompletion();
this.df._autocompletions = value;
}
});
},
setup_autocompletion() {
if (this._autocompletion_setup) return;
const ace = window.ace;
const get_autocompletions = () => this.df.autocompletions;
ace.config.loadModule("ace/ext/language_tools", langTools => {
this.editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true
});
let completer = {
getCompletions: function(editor, session, pos, prefix, callback) {
if (prefix.length === 0) {
callback(null, []);
return;
}
let autocompletions = get_autocompletions();
if (autocompletions.length) {
callback(
null,
autocompletions.map(a => ({
name: 'frappe',
value: a,
score: 100,
meta: 'Frappe API'
}))
);
}
}
}
langTools.addCompleter(completer);
});
this._autocompletion_setup = true;
},
refresh_height() {