Calculadora de AppleScript: tome la ecuación del texto seleccionado y calcule el resultado

2

Quiero crear un servicio que pueda tomar el texto seleccionado, realizar automáticamente la operación matemática deseada y luego pegar el resultado directamente después del texto seleccionado. Este servicio es similar a la función de calculadora integrada en la Búsqueda de Google, pero es más práctico.

Aquí hay algunos ejemplos:

  

si este es el texto seleccionado : entonces este es el nuevo texto

     

43 + 957: = 1000

     

763-9482: = -8719

     

8 * 26: = 208

     

83/23: = 3.60869565217

Las operaciones anteriores incluyen la suma, resta, multiplicación y división. Hasta ahora, este script no es difícil de escribir.

Pero, también me gustaría la posibilidad de hacer uso de paréntesis en los cálculos. Aquí es donde el camino se vuelve rocoso.

Aquí hay algunos ejemplos de ecuaciones que involucran paréntesis:

  

(4 + 55) / 2: = 29.5

     

352 + ((76.031 * 57/100) + (93.6 * 87/100)): = 476.76967

     

(45 + 36 + (64 * 0.04) + 152 + 33 + 90) * (1 / (1.98-425- (0.25 * 629) +431)): = -2.40209017217

Yikes.

Está bien. Pasos de bebé ...

Aquí está el código que he escrito. Solo puede manejar el primer conjunto de ejemplos:

set inputString to "43 + 555 /4 *122"

-- Remove any and all spaces from this string
set inputString to replace_chars(inputString, " ", "")

-- Convert every instance of "x" to "*"
if (inputString contains "x") then
    set inputString to replace_chars(inputString, "x", "*")
end if

-- Ensure that the string contains no foreign characters:
set supportedCharacters to {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "+", "-", "*", "/"}

set x to 1
set everyCharacterInInputStringIsValid to true

repeat until (x > (length of inputString))
    if supportedCharacters contains (character x of inputString) then
        set x to (x + 1)
    else
        set everyCharacterInInputStringIsValid to false
        display dialog "Input string contains invalid character: " & (character x of inputString)
        error number -128 (* user cancelled *)
    end if
end repeat

-- String is all good. Now for the "fun" part.

set AppleScript's text item delimiters to {"+", "-", "*", "/"}
set onlyTheNumbers to text items of inputString
set AppleScript's text item delimiters to {""}
-- return onlyTheNumbers -- {"43", "555", "4", "122"}

set AppleScript's text item delimiters to onlyTheNumbers
set onlyTheSymbols to text items of inputString
set AppleScript's text item delimiters to {""}
-- return onlyTheSymbols -- {"", "+", "/", "*", ""}

-- Remove the first and last items in the onlyTheSymbols list
-- post #3 from http://macscripter.net/viewtopic.php?id=43371/
set removeSpecificItemsFromList to {1, (count of onlyTheSymbols)}
repeat with i in removeSpecificItemsFromList
    set item i of onlyTheSymbols to null
end repeat
set onlyTheSymbols to every text of onlyTheSymbols

set calculatorBalance to ((0) as number)
set x to 1 as integer
set y to 2 as integer
set z to 1 as integer
set num1 to (((item x) of onlyTheNumbers) as number)
repeat until ((z) is greater than (count of onlyTheSymbols))

    set num2 to (((item (y)) of onlyTheNumbers) as number)
    set symbol to ((item z) of onlyTheSymbols)
    if (symbol is "+") then
        set calculatorBalance to (num1 + num2)
    else if (symbol is "-") then
        set calculatorBalance to (num1 - num2)
    else if (symbol is "*") then
        set calculatorBalance to (num1 * num2)
    else if (symbol is "/") then
        set calculatorBalance to (num1 / num2)
    end if

    set num1 to (calculatorBalance as number)

    set y to (y + 1)
    set z to (z + 1)
end repeat

display dialog " = " & calculatorBalance


on replace_chars(this_text, search_string, replacement_string)
    set AppleScript's text item delimiters to the search_string
    set the item_list to every text item of this_text
    set AppleScript's text item delimiters to the replacement_string
    set this_text to the item_list as string
    set AppleScript's text item delimiters to ""
    return this_text
end replace_chars

Estoy confundido en cuanto a cómo abordar todo el concepto de paréntesis en este script. ¿Alguien puede echar una mano?

Aquí está mi idea aproximada:

  1. Determine cuántos paréntesis hay en la cadena.

  2. Divide la cadena de entrada en segmentos. El número de segmentos se basa en el número total de paréntesis en la cadena, menos uno. El número de segmentos debe ser un número impar.

  3. Compruebe si alguno de los segmentos contiene paréntesis incrustados.

  4. Repita los pasos del 1 al 4 hasta que no haya paréntesis en ningún segmento.

  5. Ahora que tiene sus segmentos, actúe como si cada segmento fuera su propia cadena. Es decir, calcule el resultado de cada segmento de forma independiente, en lugar de simplemente utilizar el número anterior en la lista para interactuar con el siguiente número en la lista.

  6. Agrega todos los resultados del segmento juntos.

No estoy seguro de tener la idea correcta.

Soy consciente de que he ignorado por completo el concepto de orden de operaciones . Tampoco sé cómo implementar esto exactamente. Mi defensa es que esto es básicamente una parte del código de paréntesis. Por ejemplo, 1 + 4 * 2 primero tendría que convertirse a 1+ (4 * 2) antes de poder calcular el resultado.

Nota:

Declaré que quiero que la entrada para AppleScript sea el texto seleccionado actualmente. Pero, verá claramente que no he escrito el código de esta manera.

A los efectos de escribir, depurar y solucionar problemas de esta secuencia de comandos, estoy ignorando ese elemento de la secuencia de comandos, porque es una parte muy fácil de escribir y hace que la prueba del código sea más complicada.

Una vez que se haya perfeccionado el script, simplemente configuraré el Servicio para recibir selected text in any application . Para la salida, le diré al script el código de clave y luego pegaré el resultado final.

Por cierto, si estas preguntas elaboradas de AppleScript se vuelven un poco exageradas para Ask Different , hágamelo saber y las llevaré a un sitio más centrado en AppleScript (por ejemplo, MacScripter.net). No sé si estoy superando mi límite aquí.

    
pregunta rubik's sphere 13.03.2017 - 04:55

1 respuesta

3

Sobre StackOverflow encontrará estas preguntas relacionadas:

Para una discusión sobre el análisis de expresiones, consulte:

La carga de AppleScript

AppleScript no es un lenguaje para disfrutar escribiendo un analizador. El lenguaje es ideal para muchas cosas pero no para la manipulación de texto. El idioma es Turing Complete , por lo que su proyecto es posible, pero difícil.

AppleScript es un dialecto de Arquitectura de secuencias de comandos abierta (OSA) y quizás esté dispuesto a considerar otro dialecto de OSA para este proyecto, como JavaScript. Si bien JavaScript no es lo ideal, encontrará más recursos y guías para ayudarlo. También puede mezclar y combinar scripts compilados de AppleScript y JavaScript.

Usa bc

Considere canalizar el texto seleccionado a bc y devolver el resultado:

set theInput to "(4.0+55.0)/2.0"
set myCalculation to "echo 'scale=1;" & (theInput) & "' | bc"
set myResult to do shell script myCalculation

Este enfoque evita reinventar la rueda y utiliza la calculadora de línea de comandos incluida con macOS, bc .

    
respondido por el Graham Miln 13.03.2017 - 07:27

Lea otras preguntas en las etiquetas