def userPreferencesStatus(view): ''' Shows the COM port and the environment selected for the user Arguments: view {st object} -- stores many info related with ST ''' try: from .Preferences import Preferences except: from libs.Preferences import Preferences pass native = Preferences().get('native', False) # Check for environment if native: env = Preferences().get('native_env_selected', False) else: env = Preferences().get('env_selected', False) if env: setStatus(view, env.upper(), key='_deviot_env') # check for port env = Preferences().get('id_port', False) if env: setStatus(view, env, key='_deviot_port')
class SerialMonitor(object): """ Handle the messages sended and received from/to the serial monitor """ def __init__(self, serial_port, console=None): super(SerialMonitor, self).__init__() self.port = serial_port self.serial = pyserial.Serial() self.serial.port = serial_port self.queue = Messages.MessageQueue(console) self.Preferences = Preferences() self.is_alive = False def isRunning(self): return self.is_alive def start(self): self.queue.startPrint() if not self.is_alive: baudrate = self.Preferences.get('baudrate', 9600) self.serial.baudrate = baudrate if isSerialAvailable(self.port): self.serial.open() self.is_alive = True monitor_thread = threading.Thread(target=self.receive) monitor_thread.start() else: self.queue.put('serial_port_used_{0}', self.port) self.stop() def stop(self): self.is_alive = False self.queue.stopPrint() def receive(self): length_before = 0 while self.is_alive: number = self.serial.inWaiting() if number > 0: in_text = self.serial.read(number) length_in_text = len(in_text) in_text = convertMode(in_text, length_before) self.queue.put(in_text) length_before += length_in_text length_before %= 16 time.sleep(0.01) self.serial.close() def send(self, out_text): line_ending = self.Preferences.get('line_ending', '\n') out_text += line_ending self.queue.put('sended_{0}', out_text) out_text = out_text.encode('utf-8', 'replace') self.serial.write(out_text)
class I18n(object): def __init__(self): self.lang_params = {} self.ids_lang = [] self.id_path_dict = {} self.trans_dict = {} self.listIds() self.Preferences = Preferences() self.id_lang = self.Preferences.get('id_lang', Tools.getSystemLang()) self.changeLang(self.id_lang) def listIds(self): language_list_path = Paths.getLanguageList() self.lang_params = JSONFile(language_list_path).getData() language_path = Paths.getLanguagePath() lang_file_paths = glob.glob(language_path + '/*.lang') lang_file_names = [os.path.basename(p) for p in lang_file_paths] self.ids_lang += [os.path.splitext(nam)[0] for nam in lang_file_names] self.id_path_dict.update(dict(zip(self.ids_lang, lang_file_paths))) self.ids_lang.sort(key=lambda _id: self.lang_params.get(_id)[1]) def changeLang(self, lang_id): if lang_id in self.id_path_dict: self.id_lang = lang_id lang_file_path = self.id_path_dict[lang_id] lang_file = LanguageFile(lang_file_path) self.trans_dict = lang_file.getTransDict() else: self.id_lang = 'en' self.trans_dict = {} self.Preferences.set('id_lang', self.id_lang) def translate(self, text, *params): trans_text = self.trans_dict.get(text, text) for seq, param in enumerate(params): seq_text = '{%d}' % seq trans_text = trans_text.replace(seq_text, str(param)) return trans_text def getLangId(self): return self.id_lang def getLangIds(self): return self.ids_lang def getLangNames(self, lang_id): return self.lang_params.get(lang_id, ['Unknown', 'Unknown'])
def toggleSerialMonitor(window=None): """ Toggle the state of the serial monitor Arguments: window {object} windows to call or close the serial monitor """ try: from .Serial import SerialMonitor from . import Serial from .Preferences import Preferences from .Messages import MonitorView except: from libs.Serial import SerialMonitor from libs import Serial from libs.Preferences import Preferences from libs.Messages import MonitorView monitor_module = Serial serial_monitor = None preferences = Preferences() serial_port = preferences.get('id_port', '') serial_ports = Serial.listSerialPorts() # create window and view if not exists if window is None: window = sublime.active_window() if serial_port in serial_ports: if serial_port in monitor_module.serials_in_use: serial_monitor = monitor_module.serial_monitor_dict.get( serial_port, None) if not serial_monitor: monitor_view = MonitorView(window, serial_port) serial_monitor = SerialMonitor(serial_port, monitor_view) if not serial_monitor.isRunning(): serial_monitor.start() if serial_port not in monitor_module.serials_in_use: monitor_module.serials_in_use.append(serial_port) monitor_module.serial_monitor_dict[serial_port] = serial_monitor else: serial_monitor.stop() monitor_module.serials_in_use.remove(serial_port)
def println(self, text): if(len(text)): from .Preferences import Preferences view = self.window.find_output_panel('exec') if(view.size() < 1): self.window.run_command("show_panel", {"panel": "output.exec"}) self.panel.set_read_only(False) # allow to show percentage in one line if(search(r"[Uploading:]\s\[=*\s*\] \d+%", text) is not None): # change focus panel_view = self.window.find_output_panel('exec') self.window.focus_view(panel_view) # remove las line before write macro = "res://Packages/Default/Delete Line.sublime-macro" self.window.run_command("run_macro_file", {"file": macro}) self.window.run_command("run_macro_file", {"file": macro}) self.window.run_command("run_macro_file", {"file": macro}) self.panel.run_command("append", {"characters": text}) # Preferences to auto-scroll auto_scroll = True if not self.monitor else Preferences().get('auto_scroll', True) if(view.size() > 90 and auto_scroll): self.panel.run_command( "move_to", {"extend": False, "to": "eof"}) self.panel.set_read_only(True)
def __init__(self, serial_port, console=None): super(SerialMonitor, self).__init__() self.port = serial_port self.serial = pyserial.Serial() self.serial.port = serial_port self.queue = Messages.MessageQueue(console) self.Preferences = Preferences() self.is_alive = False
def run(self): views = [] path = Preferences().get('ini_path', False) path = os.path.join(path, 'platformio.ini') view = self.window.open_file(path) views.append(view) if views: self.window.focus_view(views[0])
def __init__(self): self.lang_params = {} self.ids_lang = [] self.id_path_dict = {} self.trans_dict = {} self.listIds() self.Preferences = Preferences() self.id_lang = self.Preferences.get('id_lang', Tools.getSystemLang()) self.changeLang(self.id_lang)
class I18n(object): def __init__(self): self.lang_params = {} self.ids_lang = [] self.id_path_dict = {} self.trans_dict = {} self.listIds() self.Preferences = Preferences() self.id_lang = self.Preferences.get('id_lang', Tools.getSystemLang()) self.changeLang(self.id_lang) def listIds(self): language_list_path = Paths.getLanguageList() self.lang_params = JSONFile(language_list_path).getData() language_path = Paths.getLanguagePath() lang_file_paths = glob.glob(language_path + '/*.lang') lang_file_names = [os.path.basename(p) for p in lang_file_paths] self.ids_lang += [os.path.splitext(nam)[0] for nam in lang_file_names] self.id_path_dict.update(dict(zip(self.ids_lang, lang_file_paths))) self.ids_lang.sort(key=lambda _id: self.lang_params.get(_id)[1]) def changeLang(self, lang_id): self.id_lang = lang_id if (lang_id in self.id_path_dict) else 'en' lang_file_path = self.id_path_dict[self.id_lang] lang_file = LanguageFile(lang_file_path) self.trans_dict = lang_file.getTransDict() self.Preferences.set('id_lang', self.id_lang) def translate(self, text, *params): trans_text = self.trans_dict.get(text, text) for seq, param in enumerate(params): seq_text = '{%d}' % seq trans_text = trans_text.replace(seq_text, str(param)) return trans_text def getLangId(self): return self.id_lang def getLangIds(self): return self.ids_lang def getLangNames(self, lang_id): return self.lang_params.get(lang_id, ['Unknown', 'Unknown'])
def __init__(self, window=None, view=None): self.view = view self.window = window self.Preferences = Preferences() # create window and view if not exists if self.window is None: self.window = sublime.active_window() self.view = self.window.active_view() # console console_name = 'Deviot|Library' + str(time.time()) console = Messages.Console(self.window, name=console_name) # Queue for the user console self.message_queue = MessageQueue(console) # CLI self.Commands = CommandsPy(console=console)
def is_checked(self): monitor_module = Serial state = False serial_port = Preferences().get('id_port', '') if serial_port in monitor_module.serials_in_use: serial_monitor = monitor_module.serial_monitor_dict.get( serial_port) if serial_monitor and serial_monitor.isRunning(): state = True return state
def println(self, text): try: from .Preferences import Preferences except: from libs.Preferences import Preferences # Preferences to auto-scroll auto_scroll = Preferences().get('auto_scroll', True) self.view.set_read_only(False) self.view.run_command("append", {"characters": text}) if(auto_scroll): self.view.run_command("move_to", {"extend": False, "to": "eof"}) self.view.set_read_only(True)
def on_close(self, view): """ When a sketch is closed, temp files are deleted Arguments: view {ST object} -- Sublime Text Object """ # Serial Monitor monitor_module = Serial if Messages.isMonitorView(view): name = view.name() serial_port = name.split('-')[1].strip() if serial_port in monitor_module.serials_in_use: cur_serial_monitor = monitor_module.serial_monitor_dict.get( serial_port, None) if cur_serial_monitor: cur_serial_monitor.stop() monitor_module.serials_in_use.remove(serial_port) # Remove cache keep_cache = Preferences().get('keep_cache', True) if (keep_cache): return file_path = Tools.getPathFromView(view) if (not file_path): return file_name = Tools.getFileNameFromPath(file_path, ext=False) tmp_path = Paths.getTempPath() tmp_all = os.path.join(tmp_path, '*') tmp_all = glob.glob(tmp_all) for content in tmp_all: if file_name in content: tmp_path = os.path.join(tmp_path, content) rmtree(tmp_path, ignore_errors=False) Preferences().set('builded_sketch', False) # Empty enviroment menu Menu().createEnvironmentMenu(empty=True)
def convertMode(in_text, str_len=0): """ Convert a text in differents formats (ASCII,HEX) Arguments: in_text {string} Text to convert Keyword Arguments: str_len {int} leng of the in_text string (default: {0}) Returns: [string] -- Converted string """ text = u'' display_mode = Preferences().get('display_mode', 'Text') if display_mode == 'Ascii': for character in in_text: text += chr(character) elif display_mode == 'Hex': for (index, character) in enumerate(in_text): text += u'%02X ' % character if (index + str_len + 1) % 8 == 0: text += '\t' if (index + str_len + 1) % 16 == 0: text += '\n' elif display_mode == 'Mix': text_mix = u'' for (index, character) in enumerate(in_text): text_mix += chr(character) text += u'%02X ' % character if (index + str_len + 1) % 8 == 0: text += '\t' if (index + str_len + 1) % 16 == 0: text_mix = text_mix.replace('\n', '+') text += text_mix text += '\n' text_mix = '' if (text_mix): less = (31 - index) for sp in range(less): text += ' ' text += '\t' text += text_mix else: text = in_text.decode('utf-8', 'replace') text = text.replace('\r', '').replace('NULL', '') return text
def sendSerialMessage(text): """ Sends a text message over available the serial monitor Arguments: text {string} Text to send """ try: from . import Serial from .Preferences import Preferences except: from libs import Serial from libs.Preferences import Preferences monitor_module = Serial preferences = Preferences() serial_port = preferences.get('id_port', '') if serial_port in monitor_module.serials_in_use: serial_monitor = monitor_module.serial_monitor_dict.get( serial_port, None) if serial_monitor and serial_monitor.isRunning(): serial_monitor.send(text)
def __init__(self): self.Preferences = Preferences() self.base_dir = Paths.getDeviotUserPath() self.env_dir = Paths.getEnvDir() self.env_bin_dir = Paths.getEnvBinDir() self.cache_dir = Paths.getCacheDir() self.env_file = Paths.getEnvFile() self.cached_file = False # console window = sublime.active_window() console_name = 'Deviot|Pio_Install' + str(time.time()) console = Messages.Console(window, name=console_name) # Queue for the user console self.message_queue = Messages.MessageQueue(console)
def plugin_loaded(): protected = Preferences().get('protected') if (not protected): thread = threading.Thread(target=PioInstall().checkPio) thread.start() ThreadProgress(thread, _('processing'), _('done')) else: # creating files Tools.createCompletions() Tools.createSyntaxFile() Menu().createMainMenu() Menu().createLibraryImportMenu() Menu().createLibraryExamplesMenu() # Run serial port listener Serial_Lib = Serial.SerialListener(func=Menu().createSerialPortsMenu) Serial_Lib.start()
def getBuildPath(file_name): try: from .Preferences import Preferences except: from libs.Preferences import Preferences build_dir = Preferences().get('build_dir', False) if (build_dir): build_dir = os.path.join(build_dir, file_name) try: os.makedirs(build_dir) except OSError as exc: if exc.errno != errno.EEXIST: raise exc pass return build_dir
def createSketch(sketch_name, path): try: from . import Paths from .Preferences import Preferences except: from libs import Paths from libs.Preferences import Preferences # file path sketch_path = os.path.join(path, sketch_name) if not os.path.exists(sketch_path): os.makedirs(sketch_path) # use cpp file/template intead of ino cpp = Preferences().get('use_cpp', False) if cpp: ext = '.cpp' else: ext = '.ino' # get template template_file_name = 'template' + ext preset_path = Paths.getPresetPath() template_file_path = os.path.join(preset_path, template_file_name) with open(template_file_path) as file: src_code = file.read() src_file_name = sketch_name + ext src_file_path = os.path.join(sketch_path, src_file_name) # save new file with open(src_file_path, 'w') as src_file: src_code = src_code.replace('${src_file_name}', src_file_name) src_file.write(src_code) # open new file views = [] window = sublime.active_window() view = window.open_file(src_file_path) views.append(view) if views: window.focus_view(views[0])
def println(self, text): try: from .Preferences import Preferences except: from libs.Preferences import Preferences # Preferences to auto-scroll auto_scroll = Preferences().get('auto_scroll', False) self.view.set_read_only(False) pos = self.view.size() if python_version < 3: edit = self.view.begin_edit() self.view.insert(edit, pos, text) self.view.end_edit(edit) else: if (auto_scroll): self.view.show(pos) self.view.run_command("append", {"characters": text}) self.view.set_read_only(True)
def setStatus(view, text=False, erase_time=0, key=False): ''' Sets the info to show in the status bar of Sublime Text. This info is showing only when the working file is considered IoT Arguments: view {st object} -- stores many info related with ST ''' if (not view): return is_iot = isIOTFile(view) if (key and is_iot): view.set_status(key, text) info = [] if (is_iot and not erase_time): try: from .Preferences import Preferences except: from libs.Preferences import Preferences pio_version = Preferences().get('pio_version', 0) info = '%s v%s | Pio v%s' % (__title__, str(__version__), pio_version) view.set_status('_deviot_version', info) if (text and erase_time): view.set_status('_deviot_extra', text) if (erase_time > 0): def cleanStatus(): view.erase_status('_deviot_extra') sublime.set_timeout(cleanStatus, erase_time)
def createSerialPortsMenu(self): ''' Creates a menu list with all serial ports available ''' port_list = Serial.listSerialPorts() ip_port = Preferences().get('ip_port', '') if (ip_port): port_list.insert(0, ip_port) menu_preset = self.getTemplateMenu(file_name='serial.json') menu_ports = [{ "caption": _("menu_add_ip"), "command": "add_serial_ip" }, { "caption": "menu_not_used_port", "command": "select_port", "checkbox": True, "args": { "id_port": "none" } }] for port in port_list: temp_info = {} temp_info['caption'] = port temp_info['command'] = 'select_port' temp_info['checkbox'] = True temp_info['args'] = {'id_port': port} menu_ports.append(temp_info) menu_preset[0]['children'][0]['children'] = menu_ports self.saveSublimeMenu(data=menu_preset, sub_folder='serial', user_path=True)
def __init__(self, view=False, console=False, install=False, command=True): ''' Initialize the command and preferences classes, to check if the current work file is an IoT type it received the view parameter (ST parameter). This parameter is necessary only in the options like build or upload. Keyword Arguments: view {st object} -- stores many info related with ST (default: False) ''' self.Preferences = Preferences() self.Menu = Menu() # user console if(console): current_time = time.strftime('%H:%M:%S') self.message_queue = MessageQueue(console) self.message_queue.startPrint() # For installing purposes if(install): self.Commands = CommandsPy(console=console) return self.view = view self.execute = True self.is_native = False self.is_iot = False if(view): # avoid to do anything with a monitor view view_name = view.name() sketch_size = view.size() file_path = Tools.getPathFromView(view) if(not file_path and 'monitor' in view_name.lower()): try: current_time = time.strftime('%H:%M:%S') self.message_queue.put('invalid_file_{0}', current_time) except: pass self.execute = False return # unsaved file if(command and not file_path and sketch_size > 0): saved_file = self.saveCodeInFile(view) view = saved_file[1] file_path = Tools.getPathFromView(view) if(command and not sketch_size): self.message_queue.put('not_empty_sketch_{0}', current_time) # current file / view current_path = Paths.getCurrentFilePath(view) if(not current_path): return self.is_iot = Tools.isIOTFile(view) current_dir = Paths.getCWD(current_path) parent_dir = Paths.getParentCWD(current_path) file_name = Tools.getFileNameFromPath(file_path) temp_name = Tools.getFileNameFromPath(current_path, ext=False) if(not self.is_iot): self.execute = False # check IoT type file if(console and not self.is_iot and not self.execute): current_time = time.strftime('%H:%M:%S') msg = 'not_iot_{0}{1}' if(not file_name): msg = 'not_empty_sketch_{0}' self.message_queue.put(msg, current_time, file_name) self.execute = False return if(not command and not self.is_iot): return # Check native project for file in os.listdir(parent_dir): if(file.endswith('platformio.ini')): self.dir = parent_dir self.src = False self.is_native = True break # set native paths if(not self.is_native): build_dir = self.Preferences.get('build_dir', False) if(not build_dir): build_dir = Paths.getTempPath(temp_name) self.src = current_dir self.dir = build_dir # unsaved changes if (command and view.is_dirty()): view.run_command('save') if(console): self.message_queue.put( '[ Deviot {0} ] {1}\\n', version, file_name) time.sleep(0.02) # Initilized commands self.Commands = CommandsPy(console=console, cwd=self.dir)
class PlatformioCLI(CommandsPy): ''' This class handle all the request to the platformio ecosystem. From the list of boards to the build/upload of the sketchs. More info about platformio in: http://platformio.org/ Extends: CommandsPy ''' def __init__(self, view=False, console=False, install=False, command=True): ''' Initialize the command and preferences classes, to check if the current work file is an IoT type it received the view parameter (ST parameter). This parameter is necessary only in the options like build or upload. Keyword Arguments: view {st object} -- stores many info related with ST (default: False) ''' self.Preferences = Preferences() self.Menu = Menu() # user console if(console): current_time = time.strftime('%H:%M:%S') self.message_queue = MessageQueue(console) self.message_queue.startPrint() # For installing purposes if(install): self.Commands = CommandsPy(console=console) return self.view = view self.execute = True self.is_native = False self.is_iot = False if(view): # avoid to do anything with a monitor view view_name = view.name() sketch_size = view.size() file_path = Tools.getPathFromView(view) if(not file_path and 'monitor' in view_name.lower()): try: current_time = time.strftime('%H:%M:%S') self.message_queue.put('invalid_file_{0}', current_time) except: pass self.execute = False return # unsaved file if(command and not file_path and sketch_size > 0): saved_file = self.saveCodeInFile(view) view = saved_file[1] file_path = Tools.getPathFromView(view) if(command and not sketch_size): self.message_queue.put('not_empty_sketch_{0}', current_time) # current file / view current_path = Paths.getCurrentFilePath(view) if(not current_path): return self.is_iot = Tools.isIOTFile(view) current_dir = Paths.getCWD(current_path) parent_dir = Paths.getParentCWD(current_path) file_name = Tools.getFileNameFromPath(file_path) temp_name = Tools.getFileNameFromPath(current_path, ext=False) if(not self.is_iot): self.execute = False # check IoT type file if(console and not self.is_iot and not self.execute): current_time = time.strftime('%H:%M:%S') msg = 'not_iot_{0}{1}' if(not file_name): msg = 'not_empty_sketch_{0}' self.message_queue.put(msg, current_time, file_name) self.execute = False return if(not command and not self.is_iot): return # Check native project for file in os.listdir(parent_dir): if(file.endswith('platformio.ini')): self.dir = parent_dir self.src = False self.is_native = True break # set native paths if(not self.is_native): build_dir = self.Preferences.get('build_dir', False) if(not build_dir): build_dir = Paths.getTempPath(temp_name) self.src = current_dir self.dir = build_dir # unsaved changes if (command and view.is_dirty()): view.run_command('save') if(console): self.message_queue.put( '[ Deviot {0} ] {1}\\n', version, file_name) time.sleep(0.02) # Initilized commands self.Commands = CommandsPy(console=console, cwd=self.dir) def checkInitFile(self): """ Check each platformio.ini file and loads the environments already initialized. """ protected = self.Preferences.get('protected', False) if(not protected): return # Empy menu if it's not a IoT file if(not self.is_iot): if(Tools.getPythonVersion() > 2): self.Menu.createEnvironmentMenu(empty=True) return ini_path = Paths.getFullIniPath(self.dir) # show non native data if(not self.is_native): self.Preferences.set('native', False) self.Preferences.set('ini_path', self.dir) self.Menu.createEnvironmentMenu() return else: self.Preferences.set('native', True) self.Preferences.set('ini_path', self.dir) # get data from platformio.ini file ini_list = [] with open(ini_path, 'r') as file: pattern = compile(r'\[(\w+)\W(\w+)\]') for line in file: if pattern.findall(line): if('#' not in line): line = match(r"\[\w+:(\w+)\]", line).group(1) ini_list.append(line) # save preferences, update menu data type = 'board_id' if not self.is_native else 'found_ini' self.Preferences.set(type, ini_list) self.Menu.createEnvironmentMenu() def removeEnvFromFile(self, env): """ Removes the environment select from the platformio.ini file Arguments: env {string} -- environment to remove """ ini_path = self.Preferences.get('ini_path', False) if(not ini_path): return found = False write = False buffer = "" # exclude environment selected ini_path = Paths.getFullIniPath(ini_path) if(not os.path.isfile(ini_path)): return with open(ini_path) as file: for line in file: if(env in line and not found): found = True write = True if(not found): buffer += line if(found and line == '\n'): found = False # save new platformio.ini if(write): with open(ini_path, 'w') as file: file.write(buffer) def overrideSrc(self, ini_path, src_dir): """ Append in the platformio.ini file, the src_dir option to override the source folder where the sketch is stored Arguments: ini_path {string} -- path of the platformio.ini file src_dir {string} -- path where source folder the is located """ header = '[platformio]' ini_path = Paths.getFullIniPath(self.dir) with open(ini_path) as file: if header not in file.read(): with open(ini_path, 'a+') as new_file: new_file.write("\n%s\n" % header) new_file.write("src_dir=%s\n" % src_dir) def initSketchProject(self, chosen): ''' command to initialize the board(s) selected by the user. This function can only be use if the workig file is an IoT type (checked by isIOTFile) ''' # check if it was already initialized ini_path = Paths.getFullIniPath(self.dir) if(os.path.isfile(ini_path)): with open(ini_path) as file: if(chosen in file.read()): return init_board = '--board=%s ' % chosen if(not init_board): current_time = time.strftime('%H:%M:%S') msg = 'none_board_sel_{0}' self.message_queue.put(msg, current_time) self.Commands.error_running = True return command = ['init', '%s' % (init_board)] self.Commands.runCommand(command) if(not self.Commands.error_running): if(self.is_native): self.Preferences.set('init_queue', '') if(not self.is_native and self.src): self.overrideSrc(self.dir, self.src) def buildSketchProject(self): ''' Command to build the current working sketch, it must to be IoT type (checked by isIOTFile) ''' if(not self.execute): self.message_queue.stopPrint() return # get environment based on the current project type = 'env_selected' if not self.is_native else 'native_env_selected' choosen_env = self.Preferences.get(type, '') if(type == 'native_env_selected' and not choosen_env): choosen_env = self.Preferences.get('init_queue', '') # check environment selected if(not choosen_env): current_time = time.strftime('%H:%M:%S') self.message_queue.put('none_env_select_{0}', current_time) return False # initialize the sketch self.initSketchProject(choosen_env) if(self.Commands.error_running): self.message_queue.stopPrint() return command = ['run', '-e %s' % choosen_env] self.Commands.runCommand(command) # set build sketch if(not self.Commands.error_running): self.Preferences.set('builded_sketch', True) return choosen_env else: self.Preferences.set('builded_sketch', False) def uploadSketchProject(self): ''' Upload the sketch to the select board to the select COM port it returns an error if any com port is selected ''' if(not self.execute): self.message_queue.stopPrint() return # Stop serial monitor Tools.closeSerialMonitors(self.Preferences) # Compiling code choosen_env = self.buildSketchProject() if(not choosen_env): return if(self.Commands.error_running): self.message_queue.stopPrint() return id_port = self.Preferences.get('id_port', '') current_ports = listSerialPorts() if(id_port not in current_ports): id_port = False # check port selected if(not id_port): current_time = time.strftime('%H:%M:%S') self.message_queue.put('none_port_select_{0}', current_time) return command = ['run', '-t upload --upload-port %s -e %s' % (id_port, choosen_env)] self.Commands.runCommand(command) if(not self.Commands.error_running): autorun = self.Preferences.get('autorun_monitor', False) if(autorun): Tools.toggleSerialMonitor() self.Preferences.set('autorun_monitor', False) self.message_queue.stopPrint() def cleanSketchProject(self): ''' Delete compiled object files, libraries and firmware/program binaries if a sketch has been built previously ''' if(not self.execute): return builded_sketch = self.Preferences.get('builded_sketch', '') if(not builded_sketch): return command = ['run', '-t clean'] self.Commands.runCommand(command) if(not self.Commands.error_running): self.Preferences.set('builded_sketch', False) self.message_queue.stopPrint() def upgradePio(self): self.message_queue.put('[ Deviot {0} ]\\n', version) self.message_queue.put('searching_pio_updates', version) command = ['upgrade'] self.Commands.runCommand(command, verbose=True) command = ['--version'] out = self.Commands.runCommand(command, verbose=True, setReturn=True) if(out): pio_version = match(r"\w+\W \w+ (.+)", out).group(1) self.Preferences.set('pio_version', pio_version) self.saveAPIBoards() self.Menu.createMainMenu() def openInThread(self, type, chosen=False): """ Opens each action; build/upload/clean in a new thread Arguments: type {string} -- type of action. Valid values: build/upload/clean """ if(type == 'init'): action_thread = threading.Thread( target=self.initSketchProject, args=(chosen,)) action_thread.start() elif(type == 'build'): action_thread = threading.Thread(target=self.buildSketchProject) action_thread.start() elif (type == 'upload'): action_thread = threading.Thread(target=self.uploadSketchProject) action_thread.start() elif(type == 'upgrade'): action_thread = threading.Thread(target=self.upgradePio) action_thread.start() else: action_thread = threading.Thread(target=self.cleanSketchProject) action_thread.start() ThreadProgress(action_thread, _('processing'), _('done')) def saveCodeInFile(self, view): """ If the sketch in the current view has been not saved, it generate a random name and stores in a temp folder. Arguments: view {ST Object} -- Object with multiples options of ST """ ext = '.ino' tmp_path = Paths.getTempPath() file_name = str(time.time()).split('.')[0] file_path = os.path.join(tmp_path, file_name) file_path = os.path.join(file_path, 'src') os.makedirs(file_path) full_path = file_name + ext full_path = os.path.join(file_path, full_path) region = sublime.Region(0, view.size()) text = view.substr(region) file = JSONFile(full_path) file.writeFile(text) view.set_scratch(True) window = view.window() window.run_command('close') view = window.open_file(full_path) return (True, view) def getAPIBoards(self): ''' Get the list of boards from platformIO API using CLI. To know more info about platformIO visit: http://www.platformio.org/ Returns: {json object} -- list with all boards in a JSON format ''' window = sublime.active_window() view = window.active_view() Tools.setStatus(view, _('updating_board_list')) boards = [] Run = CommandsPy() command = ['boards', '--json-output'] boards = Run.runCommand(command, setReturn=True) Tools.setStatus(view, _('Done'), erase_time=4000) return boards def saveAPIBoards(self, update_method=False): ''' Save the JSON object in a specific JSON file ''' boards = self.getAPIBoards() self.Menu.saveTemplateMenu( data=boards, file_name='platformio_boards.json', user_path=True) self.saveEnvironmentFile() if(update_method): update_method() def saveEnvironmentFile(self): ''' Load the JSON file with the list of all boards and re order it based on the vendor. after that format the data to operate with the standards required for the ST Returns: {json array} -- list of all boards to show in the menu ''' boards_list = [] platformio_data = self.Menu.getTemplateMenu( file_name='platformio_boards.json', user_path=True) if(not platformio_data): return platformio_data = json.loads(platformio_data) for datakey, datavalue in platformio_data.items(): # children children = {} children['caption'] = datavalue['name'] children['command'] = 'select_env' children['checkbox'] = True children['args'] = {'board_id': datakey} # Board List temp_info = {} temp_info[datakey] = {'children': []} temp_info[datakey]['children'].append(children) boards_list.append(temp_info) # Save board list self.Menu.saveTemplateMenu( boards_list, 'env_boards.json', user_path=True)
def run(self): Preferences().set('default_path', False)
class Libraries: """ Handle the library API from platformIO More info: http://docs.platformio.org/en/latest/librarymanager/index.html """ def __init__(self, window=None, view=None): self.view = view self.window = window self.Preferences = Preferences() # create window and view if not exists if self.window is None: self.window = sublime.active_window() self.view = self.window.active_view() # console console_name = 'Deviot|Library' + str(time.time()) console = Messages.Console(self.window, name=console_name) # Queue for the user console self.message_queue = MessageQueue(console) # CLI self.Commands = CommandsPy(console=console) def downloadList(self, keyword): """ Search a library in the platformio API api.platformio.org the data of all pages are stored in a json file. The result of the search is showing in the st quick panel Arguments: keyword {string}: Keyword to search the library in the platformio API """ # building query request = {} request['query'] = keyword query = urlencode(request) # request parameters url = 'http://api.platformio.org/lib/search?' user_agent = 'Deviot/' + str(version) + \ ' (Sublime-Text/' + str(sublime.version()) + ')' headers = {'User-Agent': user_agent} req = Request(url + query, headers=headers) # receive first page response = urlopen(req) list = json.loads(response.read().decode()) # check number of pages nloop = list['total'] / list['perpage'] if(nloop > 1): # next pages nloop = int(nloop) + 1 if nloop > int(nloop) else nloop for page in range(2, nloop + 1): # building query of next pages request['page'] = page query = urlencode(request) req = Request(url + query, headers=headers) # receive first page response = urlopen(req) page_next = json.loads(response.read().decode()) for item_next in page_next['items']: list['items'].append(item_next) # save data in file self.saveLibraryData(list, 'default_list.json') # show result in the quick panel sublime.set_timeout(self.show_results, 0) def show_results(self): self.window.run_command('show_results') def getList(self): """ Gets the list with all libraries found and returns on the quick panel Returns: [dict] -- dictionary with all libraries found """ # get file list = self.getLibrary('default_list.json') list_ins = self.Preferences.get('user_libraries', '') # if none result if(list['total'] == 0): list = [_('none_lib_found')] return list # arrange list to the quickpanel quick_list = [] for item in list['items']: if(str(item['id']) + ' ' not in " ".join(list_ins) + ' '): item_list = [] item_list.append(item['name']) item_list.append(item['description']) item_list.append(str(item['id'])) quick_list.append(item_list) # save and return data self.saveLibraryData(quick_list, 'quick_list.json') return quick_list def installLibrary(self, selected): """ Install the selected library Arguments: selected {int} position in dict of the library selected """ list = self.getLibrary('quick_list.json') lib_id = list[selected][2] lib_name = list[selected][0] self.message_queue.startPrint() self.message_queue.put('[ Deviot {0} ]\\n', version) time.sleep(0.01) # Install Library with CLI command = ['lib', 'install', lib_id] self.Commands.runCommand(command, extra_message=lib_name) # update list of libraries installed in the preference file self.getInstalledList(ids=True) # update menu Tools.updateMenuLibs() def installedList(self): """ Show the installed libraries. Returns: [dict] -- dictionary with the data to show in the quick panel """ list = self.getLibrary('quick_list.json') return list def getInstalledList(self, ids=False): """ Run the CLI command to get the list of library(ies) installed, stores the data in a json file and run a command to show the quick panel with all the data founded """ command = ['lib', 'list', '--json-output'] Commands = CommandsPy() output = Commands.runCommand(command, setReturn=True) output = json.loads(output) # return a dict with the ids of the installed libraries if(ids): installed_ids = [] if(output): for item in output: installed_ids.append(str(item['id'])) self.Preferences.set('user_libraries', installed_ids) return # arrange list to the quickpanel quick_list = [] if(output): for item in output: item_list = [] item_list.append(item['name']) item_list.append(item['description']) item_list.append(str(item['id'])) quick_list.append(item_list) else: quick_list = [_('none_lib_installed')] # save the data and run the quick panel self.saveLibraryData(quick_list, 'quick_list.json') self.window.run_command('show_remove_list') def removeLibrary(self, selected): """ Run a CLI command with the ID of the library to uninstall, also remove the reference of the ID in the preferences file. Arguments: selected {int} position of the option selected in the quick panel. """ list = self.getLibrary('quick_list.json') lib_id = list[selected][2] lib_name = list[selected][0] self.message_queue.startPrint() self.message_queue.put('[ Deviot {0} ]\\n', version) time.sleep(0.01) # uninstall Library with CLI command = ['lib', 'uninstall', lib_id] self.Commands.runCommand(command, extra_message=lib_name) # remove from preferences if (not self.Commands.error_running): installed = self.Preferences.get('user_libraries', '') if(installed): if(lib_id in installed): self.Preferences.data.setdefault( 'user_libraries', []).remove(lib_id) self.Preferences.saveData() # update menu Tools.updateMenuLibs() def saveLibraryData(self, data, file_name): """ Stores the data of the libraries in a json file Arguments: data {json} json data with the libraries file_name {string} name of the json file """ libraries_path = Paths.getLibraryPath() library_path = os.path.join(libraries_path, file_name) libraries = JSONFile(library_path) libraries.setData(data) libraries.saveData() def getLibrary(self, file_name): """ Get a specific json file and return the data Arguments: file_name {string} Json file name where is stored the library data Returns: [dict] -- Dictionary with the library data """ plugin_path = Paths.getLibraryPath() library_path = os.path.join(plugin_path, file_name) libraries = JSONFile(library_path).getData() return libraries
def run(self): verbose = Preferences().get('verbose_output', False) Preferences().set('verbose_output', not verbose)
def is_checked(self): return Preferences().get('verbose_output', False)
def run(self): keep = Preferences().get('use_cpp', False) Preferences().set('use_cpp', not keep)
class Libraries: """ Handle the library API from platformIO More info: http://docs.platformio.org/en/latest/librarymanager/index.html """ def __init__(self, window=None, view=None): self.view = view self.window = window self.Preferences = Preferences() # create window and view if not exists if self.window is None: self.window = sublime.active_window() self.view = self.window.active_view() # console console_name = 'Deviot|Library' + str(time.time()) console = Messages.Console(self.window, name=console_name) # Queue for the user console self.message_queue = MessageQueue(console) # CLI self.Commands = CommandsPy(console=console) def downloadList(self, keyword): """ Search a library in the platformio API api.platformio.org the data of all pages are stored in a json file. The result of the search is showing in the st quick panel Arguments: keyword {string}: Keyword to search the library in the platformio API """ # building query request = {} request['query'] = keyword query = urlencode(request) # request parameters url = 'http://api.platformio.org/lib/search?' user_agent = 'Deviot/' + str(version) + \ ' (Sublime-Text/' + str(sublime.version()) + ')' headers = {'User-Agent': user_agent} req = Request(url + query, headers=headers) # receive first page response = urlopen(req) list = json.loads(response.read().decode()) # check number of pages nloop = list['total'] / list['perpage'] if (nloop > 1): # next pages nloop = int(nloop) + 1 if nloop > int(nloop) else nloop for page in range(2, nloop + 1): # building query of next pages request['page'] = page query = urlencode(request) req = Request(url + query, headers=headers) # receive first page response = urlopen(req) page_next = json.loads(response.read().decode()) for item_next in page_next['items']: list['items'].append(item_next) # save data in file self.saveLibraryData(list, 'default_list.json') # show result in the quick panel sublime.set_timeout(self.show_results, 0) def show_results(self): self.window.run_command('show_results') def getList(self): """ Gets the list with all libraries found and returns on the quick panel Returns: [dict] -- dictionary with all libraries found """ # get file list = self.getLibrary('default_list.json') list_ins = self.Preferences.get('user_libraries', '') # if none result if (list['total'] == 0): list = [_('none_lib_found')] return list # arrange list to the quickpanel quick_list = [] for item in list['items']: if (str(item['id']) + ' ' not in " ".join(list_ins) + ' '): item_list = [] item_list.append(item['name']) item_list.append(item['description']) item_list.append(str(item['id'])) quick_list.append(item_list) # save and return data self.saveLibraryData(quick_list, 'quick_list.json') return quick_list def installLibrary(self, selected): """ Install the selected library Arguments: selected {int} position in dict of the library selected """ list = self.getLibrary('quick_list.json') lib_id = list[selected][2] lib_name = list[selected][0] self.message_queue.startPrint() self.message_queue.put('[ Deviot {0} ]\\n', version) time.sleep(0.01) # Install Library with CLI command = ['lib', 'install', lib_id] self.Commands.runCommand(command, extra_message=lib_name) # update list of libraries installed in the preference file self.getInstalledList(ids=True) # update menu Tools.updateMenuLibs() def installedList(self): """ Show the installed libraries. Returns: [dict] -- dictionary with the data to show in the quick panel """ list = self.getLibrary('quick_list.json') return list def getInstalledList(self, ids=False): """ Run the CLI command to get the list of library(ies) installed, stores the data in a json file and run a command to show the quick panel with all the data founded """ command = ['lib', 'list', '--json-output'] Commands = CommandsPy() output = Commands.runCommand(command, setReturn=True) output = json.loads(output) # return a dict with the ids of the installed libraries if (ids): installed_ids = [] if (output): for item in output: installed_ids.append(str(item['id'])) self.Preferences.set('user_libraries', installed_ids) return # arrange list to the quickpanel quick_list = [] if (output): for item in output: item_list = [] item_list.append(item['name']) item_list.append(item['description']) item_list.append(str(item['id'])) quick_list.append(item_list) else: quick_list = [_('none_lib_installed')] # save the data and run the quick panel self.saveLibraryData(quick_list, 'quick_list.json') self.window.run_command('show_remove_list') def removeLibrary(self, selected): """ Run a CLI command with the ID of the library to uninstall, also remove the reference of the ID in the preferences file. Arguments: selected {int} position of the option selected in the quick panel. """ list = self.getLibrary('quick_list.json') lib_id = list[selected][2] lib_name = list[selected][0] self.message_queue.startPrint() self.message_queue.put('[ Deviot {0} ]\\n', version) time.sleep(0.01) # uninstall Library with CLI command = ['lib', 'uninstall', lib_id] self.Commands.runCommand(command, extra_message=lib_name) # remove from preferences if (not self.Commands.error_running): installed = self.Preferences.get('user_libraries', '') if (installed): if (lib_id in installed): self.Preferences.data.setdefault('user_libraries', []).remove(lib_id) self.Preferences.saveData() # update menu Tools.updateMenuLibs() def saveLibraryData(self, data, file_name): """ Stores the data of the libraries in a json file Arguments: data {json} json data with the libraries file_name {string} name of the json file """ libraries_path = Paths.getLibraryPath() library_path = os.path.join(libraries_path, file_name) libraries = JSONFile(library_path) libraries.setData(data) libraries.saveData() def getLibrary(self, file_name): """ Get a specific json file and return the data Arguments: file_name {string} Json file name where is stored the library data Returns: [dict] -- Dictionary with the library data """ plugin_path = Paths.getLibraryPath() library_path = os.path.join(plugin_path, file_name) libraries = JSONFile(library_path).getData() return libraries
class PioInstall(object): def __init__(self): self.Preferences = Preferences() self.base_dir = Paths.getDeviotUserPath() self.env_dir = Paths.getEnvDir() self.env_bin_dir = Paths.getEnvBinDir() self.cache_dir = Paths.getCacheDir() self.env_file = Paths.getEnvFile() self.cached_file = False # console window = sublime.active_window() console_name = 'Deviot|Pio_Install' + str(time.time()) console = Messages.Console(window, name=console_name) # Queue for the user console self.message_queue = Messages.MessageQueue(console) def checkPio(self): # defining default env paths os.environ['PATH'] = self.getEnvPaths() # checking python cmd = ['python', '--version'] out = childProcess(cmd) # show error and link to download if(out[0] > 0): current_time = time.strftime('%H:%M:%S') go_to = sublime.ok_cancel_dialog( "deviot_need_python", "button_download_python") if(go_to): sublime.run_command( 'open_url', {'url': 'https://www.python.org/downloads/'}) return # check if pio is installed self.message_queue.startPrint() self.message_queue.put("deviot_setup{0}", version) current_time = time.strftime('%H:%M:%S') cmd = ['pio', '--version'] out = childProcess(cmd) if(out[0] == 0): current_time = time.strftime('%H:%M:%S') self.message_queue.put("pio_is_installed{0}", current_time) self.endSetup() return current_time = time.strftime('%H:%M:%S') self.message_queue.put("pio_isn_installed{0}", current_time) # check if virtualenv file is cached if(os.path.exists(self.env_file)): self.cached_file = True # download virtualenv if(not self.cached_file): current_time = time.strftime('%H:%M:%S') self.message_queue.put("downloading_files{0}", current_time) headers = Tools.getHeaders() url_file = 'https://pypi.python.org/packages/source/v/virtualenv/virtualenv-14.0.1.tar.gz' try: file_request = Request(url_file, headers=headers) file_open = urlopen(file_request) file = file_open.read() except: current_time = time.strftime('%H:%M:%S') self.message_queue.put( "error_downloading_files{0}", current_time) print("There was an error downloading virtualenv") return # save file try: output = open(self.env_file, 'wb') output.write(bytearray(file)) output.close() except: current_time = time.strftime('%H:%M:%S') self.message_queue.put("error_saving_files{0}", current_time) print("There was an error saving the virtualenv file") return # extract file current_time = time.strftime('%H:%M:%S') self.message_queue.put("extracting_files{0}", current_time) tmp = tempfile.mkdtemp() Tools.extractTar(self.env_file, tmp) # install virtualenv in a temp dir current_time = time.strftime('%H:%M:%S') self.message_queue.put("installing_pio{0}", current_time) temp_env = os.path.join(tmp, 'env-root') cwd = os.path.join(tmp, 'virtualenv-14.0.1') cmd = ['python', 'setup.py', 'install', '--root', temp_env] out = childProcess(cmd, cwd) # error if(out[0] > 0): current_time = time.strftime('%H:%M:%S') self.message_queue.put("error_installing_env_{0}", current_time) return # make vitualenv for root, dirs, files in os.walk(tmp): for file in files: if(file == 'virtualenv.py'): cwd = root if(os.path.exists(cwd)): cmd = ['python', 'virtualenv.py', '\"' + self.env_dir + '\"'] out = childProcess(cmd, cwd) # error if(out[0] > 0): current_time = time.strftime('%H:%M:%S') self.message_queue.put("error_making_env_{0}", current_time) return # remove temp dir rmtree(tmp) # install pio executable = os.path.join(self.env_bin_dir, 'pip') cmd = ['\"' + executable + '\"', 'install', 'platformio'] out = childProcess(cmd) # error if(out[0] > 0): current_time = time.strftime('%H:%M:%S') self.message_queue.put("error_installing_pio_{0}", current_time) return self.endSetup() current_time = time.strftime('%H:%M:%S') self.message_queue.put("setup_finished{0}", current_time) def getEnvPaths(self): # default paths default_paths = Tools.getDefaultPaths() system_paths = os.environ.get("PATH", "").split(os.path.pathsep) env_paths = [] env_paths.extend(default_paths) env_paths.extend(system_paths) env_paths = list(OrderedDict.fromkeys(env_paths)) env_paths = os.path.pathsep.join(env_paths) return env_paths def saveEnvPaths(self, new_path): env_paths = self.getEnvPaths().split(os.path.pathsep) paths = [] paths.extend(new_path) paths.extend(env_paths) paths = list(OrderedDict.fromkeys(paths)) paths = os.path.pathsep.join(paths) self.Preferences.set('env_path', paths) self.Preferences.set('protected', True) self.Preferences.set('enable_menu', True) def endSetup(self): # get pio version executable = os.path.join(self.env_bin_dir, 'pio') cmd = ['\"' + executable + '\"', '--version'] out = childProcess(cmd) pio_version = match(r"\w+\W \w+ (.+)", out[1]).group(1) self.Preferences.set('pio_version', pio_version) # save env paths env_path = [self.env_bin_dir] self.saveEnvPaths(env_path) # copy menu sys_os = Tools.getOsName() preset_path = Paths.getPresetPath() plg_path = Paths.getPluginPath() dst = os.path.join(plg_path, 'Settings-Default', 'Main.sublime-menu') if(sys_os == 'windows'): src_path = os.path.join(preset_path, 'Main.sublime-menu.windows') copy(src_path, dst) elif(sys_os == 'osx'): src_path = os.path.join(preset_path, 'Main.sublime-menu.osx') copy(src_path, dst) else: src_path = os.path.join(preset_path, 'Main.sublime-menu.linux') copy(src_path, dst) # creating files (menu, completions, syntax) generateFiles()
def is_checked(self): return Preferences().get('keep_cache', True)
def run(self): Paths.selectDir(self.window, key='build_dir', func=Preferences().set)
def run(self): Paths.selectDir(self.window, key='default_path', func=Preferences().set)
def run(self, id_lang): Preferences().set('id_lang', id_lang)
def run(self): keep = Preferences().get('keep_cache', True) Preferences().set('keep_cache', not keep)
def is_checked(self): return Preferences().get('use_cpp', False)
def selectDir(window, index=-2, level=0, paths=None, key=None, func=None, label=None): try: from .Preferences import Preferences from .I18n import I18n except: from libs.Preferences import Preferences from libs.I18n import I18n if index == -1: return '' if level > 0 and index == 0: sel_path = paths[0].split('(')[1][:-1] if func: if key: save_path = [sel_path, index, level] if (key == 'default_path'): sel_path = save_path Preferences().set('last_path', save_path) func(key, sel_path) return else: if index == 1: level -= 1 elif index > 1: level += 1 default_path = Preferences().get('default_path', False) if (not default_path): default_path = Preferences().get('last_path', False) if (index == -2 and default_path): paths = [default_path[0]] index = default_path[1] level = default_path[2] if level <= 0: level = 0 dir_path = '.' parent_path = '..' paths = listRootPath() else: sel_path = paths[index] if sel_path == ROOT_PATH: sel_path = '/' dir_path = os.path.abspath(sel_path) parent_path = os.path.join(dir_path, '..') cur_dir = Dir(dir_path) sub_dirs = cur_dir.listDirs() paths = [d.getPath() for d in sub_dirs] _ = I18n().translate paths.insert(0, parent_path) paths.insert(0, _('select_cur_dir_{0}', dir_path)) sublime.set_timeout( lambda: window.show_quick_panel( paths, lambda index: selectDir(window, index, level, paths, key, func)), 5)
def is_checked(self, id_lang): saved_id_lang = Preferences().get('id_lang') return saved_id_lang == id_lang