codeeditor — u_pbt_codeeditor #
← Referência dos componentes · Índice do guia
Editor de código com realce de sintaxe: dez linguagens, números de linha, dobragem de regiões, pesquisa e substituição, marcadores de diagnóstico na calha e largada de ficheiros.
▶ Ver ao vivo — Aplicação de demonstração, mosaico Code editor: a pré-visualização, o código que o produz e esta página, lado a lado.
Em resumo #
| Userobject | u_pbt_codeeditor |
| Classe de items | — (componente sem items) |
| Serve para | Introduzir ou apresentar código, uma consulta SQL, um ficheiro de configuração: em todos os casos em que um multilineedit carece de legibilidade |
| Opções opt-in | ib_track_caret, ib_allow_drop, ib_folding |
Início rápido #
// event open da window
uo_editor.is_syntax = uo_editor.SYNTAX_SQL
uo_editor.is_text = "SELECT c.name, SUM(o.amount) AS total~r~n" &
+ "FROM customer c~r~n" &
+ "WHERE o.status = 'paid'"
// Local variables
string ls_sql
// Reler o que o utilizador introduziu realmente
ls_sql = uo_editor.of_get_text()
is_textdevolve o mesmo: aquilo que o utilizador escreve chega lá assim que a escrita assenta (eventue_changed).
Linguagens reconhecidas #
is_syntax aceita uma destas constantes, ou SYNTAX_NONE (cadeia vazia) para texto simples sem realce.
| Linguagem | Constante | Outras grafias aceites |
|---|---|---|
| PowerScript | SYNTAX_POWERSCRIPT | pb, powerbuilder |
| SQL | SYNTAX_SQL | tsql, plsql |
| JavaScript | SYNTAX_JAVASCRIPT | js, jsx |
| JSON | SYNTAX_JSON | jsonc |
| Família C | SYNTAX_C · SYNTAX_CPP · SYNTAX_CSHARP · SYNTAX_JAVA | c++, cxx, cs |
| HTML / XML | SYNTAX_HTML · SYNTAX_XML | htm, xhtml, svg |
| CSS | SYNTAX_CSS | scss, less |
| Python | SYNTAX_PYTHON | py |
| YAML | SYNTAX_YAML | yml |
| Markdown | SYNTAX_MARKDOWN | md, mkd |
As linguagens de uma mesma família partilham o realce (SYNTAX_JAVA colore como SYNTAX_C, SYNTAX_XML como SYNTAX_HTML): a constante escolhida documenta a intenção do programador, mas o resultado no ecrã é o mesmo. O valor não distingue maiúsculas de minúsculas e um nome desconhecido recai no texto simples, sem erro.
Propriedades #
Conteúdo e linguagem #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_text | string | "" | O código apresentado no editor. Em leitura, devolve o conteúdo vivo, incluindo aquilo que o utilizador escreveu, com os finais de linha recebidos: um texto em CRLF relê-se em CRLF, um texto só com CR em CR, dobrado ou não; um texto que os mistura relê-se em CRLF. Um texto novo apresenta-se a partir da primeira linha, apaga os marcadores de of_add_marker e não está modificado (ib_modified) |
is_syntax | string | "" | Linguagem de realce: constantes SYNTAX_* (ver a tabela acima). SYNTAX_NONE = texto simples. Relê-se tal como foi escrita: SYNTAX_CSHARP continua SYNTAX_CSHARP, mesmo que C# partilhe a gramática do C |
ib_readonly | boolean | false | Editor só de leitura: o utilizador consulta sem poder modificar |
ib_modified | boolean | false | true assim que o texto difere do declarado como guardado: um novo is_text não está modificado, a escrita, of_insert_text ou uma substituição tornam-no modificado, anular até ao texto guardado repõe-no a false. Reponha-o a false depois de guardar; true força-o |
Apresentação #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
ib_line_numbers | boolean | true | Mostra ou oculta a calha de números de linha, à esquerda; ocultos, uma calha estreita mantém os marcadores de dobragem e os diagnósticos de of_add_marker |
ib_current_line | boolean | true | Realça a linha onde se encontra o cursor; no modo ib_wrap a faixa cobre todas as filas da linha |
ib_folding | boolean | false | Opt-in: permite a dobragem das regiões #region … #endregion (//#region em PowerScript, JavaScript ou C) a partir da calha: #region começa dobrada, #regionopen aberta; os marcadores ficam mesmo com ib_line_numbers = false. É um modo de leitura: enquanto está activo o editor não aceita escrita, porque a área de entrada contém então o texto dobrado e não o código-fonte; ativá-lo sobre regiões fechadas também esquece o histórico de Ctrl+Z. Um marcador alcança-se pelo teclado (Tab); Enter ou Espaço dobra-o ou expande-o |
ib_wrap | boolean | false | Muda as linhas longas de linha em vez de deslocar lateralmente |
ii_tab_size | integer | 4 | Número de colunas ocupadas por uma tabulação, de 1 a 12 (qualquer outro valor volta a 4); Enter depois de uma chaveta de abertura indenta com esta largura |
is_font_family | string | "" | Tipo de letra do editor (vazio = tipo de letra monoespaçado do tema) |
ii_font_size | integer | 0 | Tamanho do tipo de letra em píxeis (0 = tamanho do tema) |
Navegação e interações #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
ib_search_enabled | boolean | true | Ativa a barra de pesquisa integrada (Ctrl+F, Ctrl+H para substituir — ver «Teclado»); a false, of_find devolve -4 |
ib_find_match_case | boolean | false | Opção de pesquisa: só encontra o texto com as mesmas maiúsculas e minúsculas. O botão Aa da barra é o mesmo interruptor; vale para of_find, of_replace e of_replace_all |
ib_find_whole_word | boolean | false | Opção de pesquisa: só encontra o texto como palavra inteira (o _ faz parte da palavra: ls_a não é encontrado em ls_ab). Botão ab da barra |
ib_find_regex | boolean | false | Opção de pesquisa: o texto é uma expressão regular (sintaxe JavaScript); a substituição de of_replace pode então usar $1, $& e $<name>. Uma expressão inválida não encontra nada, enquadra o campo a vermelho e faz of_replace devolver -5. Botão .* da barra |
il_doc_line | long | 0 | Traz a linha indicada para o meio da vista e marca-a com uma faixa de destaque (numeração a partir de 1, como a calha) — a linha que uma documentação ou um resultado de pesquisa designa. O cursor e a seleção do utilizador não se mexem (il_caret_line desloca o cursor). Uma linha escondida numa região dobrada abre essa região; a faixa também é pintada no modo ib_wrap. 0 apaga a faixa; uma linha para lá do fim não marca nada e relê-se tal como foi escrita; qualquer novo is_text apaga a faixa |
il_caret_line | long | 1 | A linha do cursor, a partir de 1, lida ao vivo (dobrado: a da calha). Escrevê-la põe o cursor no início dessa linha e trá-la para o ecrã — o «ir para a linha» de um erro de compilação; uma linha escondida numa região dobrada abre essa região, uma linha para lá do fim fica na última. Com ib_track_caret, ue_caret_changed segue-se, como com um clique — nada quando o cursor não se mexe |
il_caret_column | long | 1 | A coluna do cursor, a partir de 1, lida ao vivo: a posição do carácter na sua linha (uma tabulação conta como um). Escrevê-la desloca o cursor ao longo da linha; para lá do fim da linha fica nesse fim. Com ib_track_caret, ue_caret_changed segue-se, como com um clique |
ib_track_caret | boolean | false | Opt-in: aciona ue_caret_changed em cada deslocação do cursor — gesto do utilizador ou ordem do seu código; um documento novo (is_text, um carregamento) não diz nada do cursor |
ib_allow_drop | boolean | false | Opt-in: aceita a largada de ficheiros a partir do Explorador do Windows; os caminhos completos chegam através de ue_drop_files |
is_theme_style | string | "" | Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança |
is_theme_mode | string | "" | Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança |
il_theme_accent | long | -1 | Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema) |
is_tooltip | string | "" | Tooltip simples apresentado ao passar sobre o componente |
is_super_tooltip_title | string | "" | Título do tooltip enriquecido (prevalece sobre is_tooltip) |
is_super_tooltip_text | string | "" | Texto do tooltip enriquecido (aceita marcação enriquecida) |
is_super_tooltip_image | string | "" | Imagem do tooltip enriquecido |
Métodos #
| Método | Função |
|---|---|
of_get_text ( ) → string | Devolve o conteúdo vivo: o mesmo valor que is_text, para código que prefira uma chamada de método |
of_find (string as_text) | Abre a barra de pesquisa, escreve nela o texto e realça todas as suas ocorrências, segundo as opções ib_find_* (dobrado, só nas linhas visíveis). A primeira ocorrência a partir do cursor é trazida para o ecrã; o cursor só se move quando o utilizador fecha a barra. Um texto vazio esvazia o campo e apaga os realces. Devolve 0 uma vez aplicado, -4 quando ib_search_enabled vale false, -2 se o componente não estiver criado |
of_insert_text (string as_text) | Insere texto no cursor, exatamente como se o utilizador o tivesse escrito: a seleção atual é substituída, o cursor fica depois da inserção e esta é trazida para o ecrã. É o método de um botão inserir um excerto, onde is_text deitaria fora o trabalho em curso. Durante uma pesquisa, a inserção vai para o cursor do utilizador, nunca sobre a ocorrência. Quando o foco está no editor ou na sua barra de pesquisa, a inserção passa pelo caminho de edição do navegador: Ctrl+Z ainda a anula. Aciona ue_changed, e com ib_track_caret ue_caret_changed segue-se, como com uma escrita. Nada é inserido enquanto o editor estiver só de leitura (ib_readonly) ou dobrado (ib_folding). Devolve 0 uma vez aplicado, -4 só de leitura ou dobrado, -5 com um texto vazio, -2 se o componente não estiver criado |
of_replace (string as_find, string as_replace) | Substitui a primeira ocorrência de as_find a partir do cursor (recomeçando do início) e trá-la para o ecrã; aplicam-se as opções ib_find_*, e com ib_find_regex a substituição pode usar $1, $& e $<name>. Um Ctrl+Z anula-a. Com ib_track_caret, ue_caret_changed segue-se quando o cursor se mexe. Devolve o número de ocorrências substituídas (1, ou 0 se não houver nenhuma), -4 só de leitura ou dobrado, -5 com uma pesquisa vazia ou uma expressão inválida, -2 se o componente não estiver criado |
of_replace_all (string as_find, string as_replace) | Substitui todas as ocorrências de as_find, num único passo de anulação. Mesmas opções e mesmos códigos que of_replace; devolve o número de ocorrências substituídas |
of_selected_text ( ) → string | Devolve o texto que o utilizador selecionou, lido ao vivo ("" sem seleção), com os finais de linha de is_text |
of_select_range (long al_from_line, long al_from_col, long al_to_line, long al_to_col) | Seleciona de (linha, coluna) a (linha, coluna), tudo a partir de 1, e traz a seleção para o ecrã; o cursor fica na extremidade indicada em último lugar, e uma coluna para lá do fim da sua linha fica nesse fim. Com ib_track_caret, ue_caret_changed segue-se, como com um arrastamento. Devolve 0 uma vez aplicado, -5 com uma linha fora do documento ou uma coluna inferior a 1, -4 quando o editor está dobrado, -2 se o componente não estiver criado |
of_line_count ( ) | Devolve o número de linhas do documento, dobrado ou não, lido ao vivo — o limite de uma caixa «ir para a linha» |
of_add_marker (long al_line, string as_kind, string as_tooltip) | Marca uma linha da calha com um diagnóstico — MARKER_ERROR, MARKER_WARNING ou MARKER_INFO — e um tooltip (aceita marcação): o que um compilador diz, onde o diz. Vários marcadores podem partilhar uma linha: o mais grave dá o ícone, o tooltip lista-os todos. Pertencem ao documento: um novo is_text apaga-os. Devolve 0 uma vez aplicado, -5 com uma linha fora do documento ou um tipo desconhecido, -2 se o componente não estiver criado |
of_remove_marker (long al_line) | Retira todos os marcadores de uma linha. Devolve 0 uma vez retirados, -5 se a linha não tiver nenhum, -2 se o componente não estiver criado |
of_clear_markers ( ) | Retira todos os marcadores da calha. Devolve 0 uma vez aplicado, -2 se o componente não estiver criado |
of_marker_count ( ) | Devolve o número de marcadores da calha, lido ao vivo (dois numa linha contam como dois) |
of_reset ( ) | Repõe todas as propriedades nos respetivos valores predefinidos e esvazia o editor. Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
of_set_redraw (boolean) | Agrupa uma rajada de modificações numa única representação. Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
of_save_as_png (string) · of_save_as_jpg (string) | Exporta a representação como imagem. Devolve 0 depois de a imagem ser escrita, -4 se a escrita falhar, -2 se o componente não estiver criado |
Eventos #
| Evento | Acionado quando |
|---|---|
ue_changed ( ) | O utilizador modificou o conteúdo e a escrita assentou — acionado também depois de of_insert_text ou de uma substituição. O evento não transporta nada: preenchê-lo obrigava a reler todo o documento a cada escrita assente, para uma aplicação que na maioria das vezes só quer saber que mudou. Quem quiser o código pede-o — is_text ou of_get_text(); ib_modified diz se difere do texto guardado |
ue_caret_changed (long al_line, long al_col) | O cursor deslocou-se (tecla, clique, arrastamento, escrita, ou o seu código); linha e coluna contadas a partir de 1, sendo a linha a da calha quando o editor está dobrado e a coluna a posição do carácter na sua linha (uma tabulação conta como um). O seu código aciona-o como o gesto (il_caret_line, il_caret_column, of_select_range, of_insert_text, of_replace); nada quando o cursor não se mexe, e um documento novo (is_text, um carregamento) não diz nada do cursor — requer ib_track_caret = true |
ue_find_result (long al_count, long al_index) | Uma pesquisa foi concluída, ou passa para outra ocorrência: al_count ocorrências encontradas, al_index = posição daquela que está destacada (a partir de 1). Durante a escrita só é lançado se a contagem mudar; fechar a barra não o lança; nem uma pesquisa vazia |
ue_drop_files (string as_files[]) | Foram largados ficheiros a partir do Windows: caminhos completos, uma entrada por ficheiro. Requer ib_allow_drop = true |
ue_drag_enter ( ) | Um arrastamento de ficheiros entra no editor (ib_allow_drop) |
ue_drag_leave ( ) | O arrastamento de ficheiros sai do editor |
ue_ready ( ) | O componente terminou o carregamento; tudo o que foi enviado antes foi reproduzido |
ue_runtime_missing ( ) | O runtime WebView2 está ausente: o componente permanece vazio |
ue_bg_color (long al_color) | O componente calculou a cor de fundo do respetivo tema; o userobject já a adotou (backcolor) |
Teclado #
| Tecla | Efeito |
|---|---|
| Tab | Indenta até à tabulação seguinte (ii_tab_size); várias linhas selecionadas: indenta todo o bloco |
| Shift+Tab | Reduz a indentação da linha ou do bloco |
| Enter | Nova linha com a mesma indentação, um nível a mais depois de {, ( ou [ |
| Ctrl+F | Abre a barra de pesquisa, preenchida com a seleção (ib_search_enabled) |
| Ctrl+H | Abre a barra com a sua linha de substituição (só editor modificável) |
| F3 · Shift+F3 | Ocorrência seguinte · anterior, a partir do código ou da barra |
| Enter · Shift+Enter (barra) | Ocorrência seguinte · anterior; no campo de substituição, Enter substitui a ocorrência atual e Ctrl+Enter substitui todas |
| Esc | Fecha a barra e põe o cursor na ocorrência atual |
| Tab, depois Enter ou Espaço (calha) | Alcança um marcador de dobragem e dobra-o ou expande-o (ib_folding) |
A coluna indicada por ue_caret_changed e il_caret_column é a posição do carácter na sua linha: uma tabulação conta como um, seja qual for a sua largura no ecrã.
Exemplos #
Um editor de consultas SQL #
// Congelar o desenho durante a configuracao
uo_query.of_set_redraw(/*on*/ false)
// Coloracao SQL, depois a consulta a mostrar
uo_query.is_syntax = uo_query.SYNTAX_SQL
uo_query.is_text = "-- Melhores clientes por volume de negocios recebido~r~n" &
+ "SELECT c.name, SUM(o.amount) AS total~r~n" &
+ "FROM customer c~r~n" &
+ " INNER JOIN orders o ON o.cust_id = c.id~r~n" &
+ "WHERE o.status = 'paid'~r~n" &
+ "GROUP BY c.name~r~n" &
+ "ORDER BY total DESC"
// Um so redesenho, tudo de uma vez
uo_query.of_set_redraw(/*on*/ true)
// event clicked de cb_execute
string ls_sql
// Executar a consulta tal como foi introduzida
ls_sql = uo_query.of_get_text() // o que o utilizador introduziu realmente
of_execute(ls_sql)
Um visualizador só de leitura #
Ideal para apresentar código gerado, um registo ou um excerto que o utilizador deve ler sem o modificar.
// Coloracao PowerScript
uo_preview.is_syntax = uo_preview.SYNTAX_POWERSCRIPT
// Um visualizador so de leitura: sem cursor, sem margem, sem realce
uo_preview.ib_readonly = true // apenas consulta, sem cursor de escrita
uo_preview.ib_line_numbers = false // oculta a calha de numeros
uo_preview.ib_current_line = false // sem realce da linha atual
uo_preview.ib_wrap = true // muda de linha em vez de deslocar
uo_preview.ii_tab_size = 2 // tabulacoes apresentadas em 2 colunas
// O codigo a mostrar
uo_preview.is_text = of_generate_code()
Acompanhar a posição do cursor numa barra de estado #
// Notificar cada movimento do cursor (ue_caret_changed)
uo_editor.ib_track_caret = true // subscricao explicita: caso contrario nenhum evento
// event ue_caret_changed de uo_editor : (long al_line, long al_col)
uo_status.of_panel(/*key*/ "pos").is_text = "Linha " + String(al_line) + ", col. " + String(al_col)
Sem ib_track_caret, o cursor não comunica nada: este acionador é de frequência elevada e permanece desligado enquanto não for pedido.
Pesquisar e ir para uma linha #
// Abre a barra de pesquisa e realca todas as ocorrencias
uo_editor.of_find(/*text*/ "ll_total")
// event ue_find_result de uo_editor : (long al_count, long al_index)
if al_count = 0 then
uo_status.of_panel(/*key*/ "main").is_text = "Nenhuma ocorrência"
else
uo_status.of_panel(/*key*/ "main").is_text = String(al_index) + " / " + String(al_count)
end if
// Ir para a linha que um compilador assinalou e marca-la na calha
uo_editor.of_add_marker(/*line*/ ll_error_line, /*kind*/ uo_editor.MARKER_ERROR, /*tooltip*/ ls_error_text)
uo_editor.il_caret_line = ll_error_line // o cursor vai para la, a linha vem para o ecra
uo_editor.of_focus_webview() // o utilizador corrige de imediato
Abrir um ficheiro largado a partir do Explorador #
// Accept files dropped from the Explorer
uo_editor.ib_allow_drop = true
// event ue_drop_files de uo_editor : (string as_files[])
string ls_content
integer li_file
// as_files[1] transporta o caminho COMPLETO do primeiro ficheiro largado
li_file = FileOpen(as_files[1], StreamMode!, Read!)
if li_file > 0 then
FileReadEx(li_file, ls_content)
FileClose(li_file)
// Colorir pela extensao do ficheiro e mostrar o seu conteudo
uo_editor.is_syntax = of_syntax_for_extension(as_files[1])
uo_editor.is_text = ls_content
end if
Reagir às modificações #
// event ue_changed de uo_editor : ( )
cb_save.enabled = uo_editor.ib_modified // anular ate ao texto guardado repoe-no a false
// event clicked de cb_save
if of_save_script(uo_editor.is_text) = 1 then
uo_editor.ib_modified = false // o texto guardado passa a ser a referencia
cb_save.enabled = false
end if
O evento só é despoletado depois de a escrita estabilizar: uma introdução contínua não gera um evento por cada tecla.
Mudar o nome de uma variável em todo o script #
// Local variables
long ll_count
// So palavras inteiras: ll_total2 e outra variavel
uo_editor.ib_find_whole_word = true
ll_count = uo_editor.of_replace_all(/*find*/ "ll_total", /*replace*/ "ldc_amount") // um unico Ctrl+Z anula tudo
Boas práticas #
- Definir sempre
is_syntaxantes deis_text: o código é realçado logo na primeira apresentação, sem que se veja um novo realce. - Para uma apresentação em modo de consulta, a combinação
ib_readonly+ib_line_numbers = false+ib_wrapproduz um visualizador sóbrio, que deixa de parecer um editor. - Para recuperar o que foi introduzido, ler
is_text(ouof_get_text()) assim que a escrita assentar — ou seja, dentro do seuue_changed, que lhe diz quando. ib_foldingsó tem interesse em ficheiros longos e estruturados; deve manter-se desligado para excertos curtos. Desligue-o antes de permitir alterações: um esquema dobrado lê-se, não se edita, eof_get_text()devolve sempre o código-fonte inteiro, regiões fechadas incluídas.- O carregamento de um ficheiro grande deve ser enquadrado por
of_set_redraw(false)/of_set_redraw(true). - Chamar
of_reset()antes de carregar um documento de outra natureza: caso contrário, a linguagem, o tamanho de tabulação ou o modo só de leitura anteriores mantêm-se em vigor. - Depois de guardar, reponha
ib_modifiedafalse: volta atrueà primeira tecla, e afalsese o utilizador anular até ao texto guardado. - Para mostrar os erros de uma compilação,
of_clear_markers()e depois umof_add_markerpor diagnóstico, eil_caret_lineno primeiro.
Herdado da base comum #
Estes membros existem em todos os componentes visuais — não são próprios deste. São detalhados uma só vez, nos capítulos transversais; esta tabela apenas diz onde os ler.
| Membros | Função | Detalhado em |
|---|---|---|
of_reset | Repor o componente a zero | 3.6 Repor um componente a zero: of_reset() |
of_register_shortcut · of_clear_shortcuts | Atalhos de teclado do componente | 3.5 Os atalhos de teclado |
of_is_created · of_is_ready · of_get_last_error | Se nasceu, se está pronto, o que falhou | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar a renderização como imagem | 3.8 Exportar a representação como imagem |
of_set_redraw | Agrupar as alterações num único repinte | 3.10 Boas práticas |
of_preload_icons | Ícones mostrados sem atraso | Apresentação instantânea: of_icon |
of_set_translation | Traduzir uma legenda do componente | 5.2 Adaptar uma etiqueta: of_set_translation |
of_focus_webview | Dar o foco ao componente | 6.4 Teclado e focus |
of_print · of_print_to_pdf | Imprimir, ou escrever um PDF | 6.9 Imprimir |
of_set_property · of_get_property · of_component_name | Controlar uma propriedade pelo nome | 3.1 O motor de propriedades |
Duas ajudas não são herdadas: of_icon e of_escape_markup vivem em n_pbt_utils. Declare um — n_pbt_utils lnv_utils, nada a criar — e chame-as nele.