Página 1 de 1

Como pegar o Literal de um codblock

Enviado: 15 Jun 2016 08:35
por rubens
Bom dia...

Tenho o vetor
aCadas := { " &Clientes " ,{||CLIENTES() }}

Se eu uso
Alert( aCADAS[1,2] )
não acontece nada, não mostra nada

Quando depuro o programa e uso o comando
? aCADAS[1,2]
retorna
{ || ... }

Tem como eu pegar o texto da função dentro do codeblock?
No exemplo eu preciso pegar CLIENTES()

Obrigado
Rubens

Como pegar o Literal de um codblock

Enviado: 15 Jun 2016 11:07
por rubens

Como pegar o Literal de um codblock

Enviado: 15 Jun 2016 14:16
por fladimir
Aproveitando sua dúvida eu entendi algumas coisas e não entendi outras...

No topico q vc colocou o link tem o código demonstrando uma solução...

O q me chamou a atenção foi sobre "TRANSLATE" que entendo parcialmente... explico...

neste código tem:

Código: Selecionar todos

#Translate CBNew(<b>)  => { <b>, <(b)> }
#Translate CBEval(<b>) => eval( <b>\[1\] )
#Translate CBString(<b>) => <b>\[2\]
O primeiro entendi.. pega o conteúdo <b> e faz um Array tendo o primeiro elemento a string e no segundo vira um bloco de código

O segundo e o terceiro Translates entendi o q faz... MAS não entendo o porque tem q usar "\" barra invertida...

Saberia dizer?

Como pegar o Literal de um codblock

Enviado: 15 Jun 2016 14:55
por rubens
Fladimir,

Lá vem você com as perguntas difíceis !!! Faz um pergunta fácil...

Fiquei um tempão quebrando a cabeça tentando descobrir que opções seriam essas, até fiz umas pesquisas, mas...
Então resolvi testar e implementar, não é que funcionou para o que eu queria...
Então tá... deixei quieto...

Mas funcionou.. kkkk

Me parecem ser opções...

Me pareceu muito com validação de JavaScript... mas acho que não é...

Quem vai saber responder é o criador da solução, o Rossine ou o Pablo....

abçs...

Rubens

Como pegar o Literal de um codblock

Enviado: 15 Jun 2016 16:58
por rubens
Infelizmente funcionou mas não funcionou do jeito que eu preciso.

Olha só:

bCod1 := CBNew( { || MINHA_FUNC("Teste") } )

Daí se uso

? CBEval( bCod1 )
Executa o code block e imprime
Teste

? CBString( bCod1 )
Imprime a string do code block
{ || MINHA_FUNC("Teste") }

Só que eu preciso usar assim:
AVetor := { 'Teste',{ || MINHA_FUNC("Teste") }}

Ai vou mandar o code block no vetor
bCod1 := CBNew( AVetor[2] )
? CBString( bCod1)
Não retorna a string do vetor e sim AVetor[2] - literalmente.

Segue o código compilável se alguém puder dar uma olhada.
Preciso disso para exibir o nome da rotina dinamicamente. Meu menu é uma matriz com as opções e um codeblock que executa a rotina conforme a opção escolhida. Daí antes do Eval() que executa a função, eu recuperava o literal do código bloco que é o nome da função e apresentaria em algum canto da minha tela. Daí eu saberia o nome da rotina que estou sem ter que entrar em cada função e fazer isso manualmente. Só falta recuperar essa informação que não estou conseguindo com o código abaixo.

Código: Selecionar todos

#Translate CBNew(<b>)  => { <b>, <(b)> }
#Translate CBEval(<b>) => eval( <b>\[1\] )
#Translate CBString(<b>) => <b>\[2\]

function MAIN()

***************************************************************
// Assim funciona 
bCodNormal := {||Teste()} 
? CBString( bCodNormal )
// Imprime {||Teste()}

***************************************************************
// Preciso que funcione assim
aVetor{ 'Teste',{||Teste()}}
bCod1 := CBNew( aVetor[2] )
? CBString( bCod1 )
//  Imprime aVetor[2] e deveria imprimir {||Teste()}

***************************************************************
function Teste()
return nil

Obrigado
Rubens

Como pegar o Literal de um codblock

Enviado: 15 Jun 2016 17:55
por Jairo Maia
Olá Rubens,

Então porque não alterar e usar como no exemplo abaixo? Será que não resolve?:

Código: Selecionar todos

Function Main()
 aCadas := {}

 aAdD( aCadas, { "CLIENTES", "CLIENTES()" } )
 aAdD( aCadas, { "FORNECEDOR", "FORNECEDOR()" } )
 aAdD( aCadas, { "PEDIDOS", "PEDIDOS()" } )

 cProcurar := "FORNECEDOR"

 cQualFuncao := Hb_AScan( aCadas, { |x| cProcurar = x[1] } )

 If cQualFuncao > 0
  cNomeFunc := aCadas[ cQualFuncao, 2 ]
  &cNomeFunc.
 EndIf
 
Return Nil

Function Clientes()
 Hb_Alert( "Funcao Clientes" )
Return Nil

Function Fornecedor()
 Hb_Alert( "Funcao Fornecedor" )
Return Nil

Function Pedidos()
 Hb_Alert( "Funcao Pedidos" )
Return Nil

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 08:52
por rubens
Bom dia

Então Jairo...

Na realidade preciso mesmo do nome da função. É justamente essa a questão...

Olha esse trecho de código

Código: Selecionar todos

aRELVENDA :={;
				{ " Por Valor-----------------------",{||""       }} ,;
				{ " Vendas por &Dia                 ",{||RELVEN3()}} ,;
	 			{ " Vendas por &Vendedor            ",{||RELVEN4()}} ,;
	 			{ " Vendas por &Grupo               ",{||RELVEN7()}} ,;
	 			{ " Vendas por C&liente             ",{||RELVEN9()}} ,;
				{ " Diferenca Custo/Vend&a          ",{||RELVEN2()}} ,;
				{ " &Por Condicao de venda           ",{||RELVEN10()}},;
				{ "                                 ",{||""       }} ,;
				{ " Por Itens-----------------------",{||""       }} ,; 	
				{ " &Itens Resumido                 ",{||RELVEN1()}} ,;
				{ " I&tens vendidos por Vendedor    ",{||RELVENV()}} ,;
				{ " Itens vendidos por Cli&ente     ",{||RELVEN6()}}  ;
				}
Se eu preciso fazer alguma coisa no relatório "Por condição de venda', eu tenho que vir aqui pegar o nome da função e procurar no arquivo de relatório de vendas. Se eu conseguisse colocar o nome da função na tela já ia em cima...
Mas beleza... não é sangria desatada não.
Obrigado...

Rubens

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 08:56
por JoséQuintas
Vamos recomeçar:

Código: Selecionar todos

aCadas := { " &Clientes " ,{||CLIENTES() }}
Isso é um array de dois elementos.

aCadas[ 1 ] contém string "&Clientes"

aCadas[ 2 ] contém codeblock { || Clientes() }

O codeblock é o elemento 2, é o segundo item do array:

Código: Selecionar todos

Eval( aCadas[ 2 ] )
Ou no que postou depois:

Código: Selecionar todos

Eval( aRelvenda[ nCont, 2 ] )
É isso?

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 09:13
por JoséQuintas
Se eu preciso fazer alguma coisa no relatório "Por condição de venda', eu tenho que vir aqui pegar o nome da função e procurar no arquivo de relatório de vendas. Se eu conseguisse colocar o nome da função na tela já ia em cima...
Se o menu for sempre assim, tem outra opção:

Código: Selecionar todos

aMenu := { ;
   { "nome do relatorio", "rotina" } ;
   }

CLS
@ 1, 0 SAY aMenu[ nCont, 2 ] + " - " + aMenu[ nCont, 1 ]
Do( aMenu[ nCont, 2 ] )

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 09:29
por JoséQuintas
Outra coisa que uso, pra evitar duplicar fontes:

Código: Selecionar todos

PUBLIC mProg
aMenu := { ;
   { "Opcao liberada total", "CADASTRO10" }, ;
   { "Opcao mais limitada", "CADASTRO11" } }
...
mProg := aMenu[ nCont, 2 ]
Do( mProg )


PROCEDURE Cadastro11
   DO Cadastro10
   RETURN

PROCEDURE Cadastro10

   IF mProg == "CADASTRO10"
     ... opções só no cadastro10
   ENDIF
O próprio menu, ao setar o nome do módulo, já serve de configuração para o módulo.

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 10:42
por rubens
Quintas,

Essa é a função onde é executada a função escolhida no menu.

Código: Selecionar todos

***************************************************************************
FUNCTION PullDown( aMenu1, nLi, nCi, nChr1, nChr2, lNivel)
LOCAL cArea, nLargura, nNumPro, nLf, nCf, nI,nOpcao
LOCAL aMenu_Tmp, nQtde_Lin, nCf_Est := 0
LOCAL cSTRING
IF(lNivel==NIL,lNivel:=.T.,)
   FOR nI := 1 TO LEN(aMenu1)
      ASIZE(aMenu1[nI],7)
   NEXT
   aMenu_Tmp := aMenu1
   aMenu1:= {}
   FOR nI := 1 TO LEN(aMenu_Tmp)
      IF lNivel .OR. IF(aMenu_Tmp[nI,3] == NIL, .T., aMenu_Tmp[nI,3] <= VAL(NIVEL))
         AADD(aMenu1, aMenu_Tmp[nI]  )
      ENDIF
   NEXT
   nLargura := LenLargura( aMenu1 )
   nNumPro  := LEN( aMenu1 )
   IF nLi+nNumPro > 22; nQtde_Lin := 22 - nLi; nCf_Est += 3 ; ELSE; nQtde_Lin := nNumPro; ENDIF
       nLf := nLi + nQtde_Lin + 1
      nCf := nCi + nLargura + 1 + nCf_Est
      IF nCf > 78
         nCi -= nLargura + 1 + nCf_Est
         nCf := nCi + nLargura + 1 + nCf_Est
      ENDIF
      IF nCi < 2
         nCi := 2
         nCf := nCi + nLargura + 1 + nCf_Est
      ENDIF
      cArea := SAVESCREEN( nLi, nCi-2, nLf + 1, nCf+nChr1+nChr2)
      COR("BOX DA JANELA DO MENU")
      JANELA2(nLi, nCi, nLf, nCf+nChr1+nChr2, .T.)
      COR("MENU")
      nOpcao := 1
      WHILE nOpcao != 0
         SET KEY K_LEFT  TO Tecla()
         SET KEY K_RIGHT TO Tecla()
         FOR nI := 1 TO nNumPro
            @ nLi + nI, nCi + 1 + nChr1 PROMPT PAD( aMenu1[ nI, 1 ], nLargura)	NIVEL aMenu1[nI,3] ;
             MESSAGE aMenu1[nI,4] WHEN aMenu1[nI,5]
         NEXT
         MENU TO nOpcao	  CHR  LINHA nQtde_Lin COLOR VERTICAL
         SET KEY K_LEFT TO
         SET KEY K_RIGHT TO
         IF nOpcao > 0
            IF VALTYPE( aMenu1[ nOpcao, 2 ] ) == "B"
		 
               *cSTRING := BLOCKTOSTRING( aMENU1[nOPCAO,2] )
               *cSTR1 := CBNEW( aMENU1[nOPCAO,2] )
               *cSTR2 := CBSTRING( aMENU1[nOPCAO,2] )
               *@ 23,10 SAY SUBSTR( cSTRING, AT( '||',cSTRING )+2, LEN(LEFT( cSTRING, RAT( ')',cSTRING ) ) )-AT( '||',cSTRING )  )
               *INKEY(0)
	 	 
               EVAL( aMenu1[ nOpcao, 2] )
	    
            ELSE
               IF SET(36) > 0
                  @ SET(36),00 SAY SPACE(80) COLOR COR(39)
               ENDIF
               PullDown( aMenu1[ nOpcao, 2 ], nOpcao + nLi + 1, 1 + nCi + (nLargura / 2),nChr1,nChr2, lNivel)
            ENDIF
         ENDIF
      ENDDO
      RESTSCREEN( nLi, nCi-2, nLf + 1, nCf+nChr1+nChr2, cArea )
RETURN NIL
Nessa parte do código é que executa o bloco de código:

Código: Selecionar todos

 IF VALTYPE( aMenu1[ nOpcao, 2 ] ) == "B"
    
    *cSTR1 := CBNEW( aMENU1[nOPCAO,2] )
    *cSTRING := CBSTRING( cSTR1 )
    *@ 23,10 SAY SUBSTR( cSTRING, AT( '||',cSTRING )+2, LEN(LEFT( cSTRING, RAT( ')',cSTRING ) ) )-AT( '||',cSTRING )  )
    *INKEY(0)
    EVAL( aMenu1[ nOpcao, 2] )    // Aqui executa o bloco de código 
 ELSE
O aMEnu1[nOpcao,2] é o codeblock que tem a string da funcao { " &Por Condicao de venda ",{||RELVEN10()}},;
Eu quero pegar essa string. Porque daí antes da linha do Eval() eu imprimo na tela o nome da função @ 23,10 SAY SUBSTR( cSTRING, AT( '||',cSTRING )+2, LEN(LEFT( cSTRING, RAT( ')',cSTRING ) ) )-AT( '||',cSTRING ) )

Mas pelos testes quando usa a função CBNew direto no vetor funciona tipo: cSTR1 = CBNew( {||RELVEN10()} )
Agora quando vem por referencia que é o caso em questão: cSTR1 = CBNew( aMENU1[nOPCAO,2] ) não funciona... Para mim o problema tá aqui. O que é enviado para a função CBNew() ou do jeito que é enviado.
Daí já não consigo pegar a string....

Rubens

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 10:59
por JoséQuintas
Isso tá parecendo o meu menu.... rs

Vamos ver se entendi: quer passar a string pro módulo colocar o nome na tela.
Faça tudo no menu.
Até postei um pouco acima.

Quanto ao nome do PRG, pode fazer como postei acima, ou outra opção que uso num determinado aplicativo:

Código: Selecionar todos

aOpcoes := { "Nome da opcao", "PROG0010", { || Prog0010() } }
Se o próprio menu criar a tela:

Código: Selecionar todos

CLS
@ 0, 0 SAY Padc( oElemento[ 2 ] + " - " + oElemento[ 1 ], MaxCol() )
@ 1, 0 TO 1, MaxCol()
@ 22, 0 TO 22, MaxCol()
Eval( oElemento[ 3 ] )
O módulo só precisa se preocupar com o que se refere a ele, vai receber a tela pronta pra uso.

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 11:06
por JoséQuintas
Ou passar como parâmetro.
Usando o último exemplo:

Código: Selecionar todos

Eval( oElemento[ 3 ], oElemento[ 1 ], oElemento[ 2 ] )
...

FUNCTION Rotina( cNomeOpcao, cNomeRotina )
...

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 11:32
por rubens
Quintas,

Esse menu uso da época do Clipper´s Club. Vinha num programa exemplo de locadora.

Veja bem:

Opção 1
Quanto ao nome do PRG, pode fazer como postei acima, ou outra opção que uso num determinado aplicativo:
Daí tenho que refazer toda a matriz, e mudar a rotina do menu.
Vai levar um tempão, não consigo fazer isso agora.

Opção 2
Se o próprio menu criar a tela:
Vai ter que pegar a informação no codeblock para mostrar o nome da função na tela. É o problema atual.

Opção 3
Ou passar como parâmetro.
Essa é a opção que tô fugindo também... daí vai ter que entrar em cada rotina e colocar manualmente. Fica do mesmo tamanho de entrar na rotina e usar um procname()

Para mim a melhor opção ainda é achar uma forma de recuperar a string da codeblock()... Se não achar deixar quieto...

Obrigado
Rubens

Como pegar o Literal de um codblock

Enviado: 16 Jun 2016 11:39
por JoséQuintas
Deixe o array como está, na ordem que está, apenas acrescente um elemento a mais.

Seu menu funciona do jeito que está agora, ok.
Usa os elementos do array que existem hoje, ok.
Se adicionar um elemento novo, para as rotinas existentes de menu não vai fazer diferença.

Então é fazer isso, e usá-lo aonde necessário.

Código: Selecionar todos

Opcoes := { ;
   { "seu nome que já existe", { || SeuBlockQueJaExiste() }, "nome" } }