From c96e30089f58c0fb5020dc7c9ace95745eb447c0 Mon Sep 17 00:00:00 2001 From: Mike Karlesky Date: Wed, 3 Jan 2024 10:27:22 -0500 Subject: [PATCH] beep plugin updates - Removed unneeded tool element definitions - Revised and exapanded documentation - Added three sound options (tools) for more platform options - Added more appropriate logging and shell execution tooling --- plugins/beep/README.md | 81 +++++++++++++++++++++++++++++----- plugins/beep/lib/beep.rb | 39 ++++++++++++---- plugins/beep/lib/beep_tools.rb | 50 ++++++++++++++++----- 3 files changed, 140 insertions(+), 30 deletions(-) diff --git a/plugins/beep/README.md b/plugins/beep/README.md index 09047709..3c969ae3 100644 --- a/plugins/beep/README.md +++ b/plugins/beep/README.md @@ -1,12 +1,75 @@ -ceedling-beep -============= +# Ceedling Plugin: Beep -This is a simple plugin that just beeps at the end of a build and/or test sequence. Are you getting too distracted surfing -the internet, chatting with coworkers, or swordfighting while it's building or testing? The friendly beep will let you know +# Overview + +This plugin simply beeps at the end of a build. + +Are you getting too distracted surfing the internet, chatting with coworkers, or swordfighting while a long build runs? A friendly beep will let you know it's time to pay attention again. -This plugin has very few configuration options. At this time it can beep on completion of a task and/or on an error condition. -For each of these, you can configure the method that it should beep. +# Configuration + +Beep includes a default configuration. By just enabling the plugin, the simplest cross-platform sound mechanism (`:bell` below) is automatically enabled for both +build completion and build error events. + +If you would like to customize your beeps, the following explains your options. + +## Events + +When this plugin is enabled, a beep is sounded when: + +* A test build or release build finish successfully. +* An error condition breaks a build. + +To change the default sound for each event, define `:on_done` and `:on_error` beneath a top-level `:beep` entry in your configuration file. See example below. + +## Sound options + +The following options are fixed. At present, this plugin does not expose customization settings. + +* `:bell` + + `:bell` is the simplest and most widely available option for beeping. This option simply `echo`s the unprintable [ASCII bell character][ascii-bel-character] to a command terminal. This option is generally available on all platforms, including Windows. + + [ascii-bel-character]: https://en.wikipedia.org/wiki/Bell_character + +* `:tput` + + [`tput`][tput] is a command line utility widely availble among Unix derivatives, including Linux and macOS. The `tput` utility uses the terminfo database to make the values of terminal-dependent capabilities (including the [ASCII bell character][ascii-bel-character]) and terminal information available to the shell. + + If the `echo`-based method used by the `:bell` option is not successful, `:tput` is a good backup option (except on Windows). + + [tput]: https://linux.die.net/man/1/tput + +* `:beep` + + [`beep`][beep] is an old but widely available Linux package for tone generation using the PC speaker. + + `beep` requires isntallation and the possibility of a complementary kernel module. + + The original audio device in a PC before sound cards was a simple and limited speaker directly wired to a motherboard. Rarely, modern systems still have this device. More commonly, its functions are routed to a default mode of modern audio hardware. `beep` may not work on modern Linux systems. If it is a viable option, this utility is typically dependent on a PC speaker kernel module and related configuration. + + [beep]: https://linux.die.net/man/1/beep + +* `:speaker_test` + + [`speaker-test`][speaker-test] is a Linux package commonly available for tone generation using a system's audio features. + + `speaker-test` requires installation as well as audio subsystem configuration. + + _Note:_ `speaker-test` typically mandates a 4 second minimum run, even if the configured sound plays for less than this minimum. Options to limit `speaker-test`'s minimum time are likely possible but would require combining advanced Ceedling features. + + [speaker-test]: https://linux.die.net/man/1/speaker-test + +* `:say` + + macOS includes a built-in text-to-speech command line application, [`say`][say]. When Ceedling is running on macOS and this beep option is selected, Ceedling events will be verbally announced. + + [say]: https://ss64.com/mac/say.html + +## Example beep configurations in YAML + +In fact, this is the default configuration (and need not be duplicated in your project file). ```yaml :beep: @@ -14,9 +77,7 @@ For each of these, you can configure the method that it should beep. :on_error: :bell ``` -Each of these have the following options: +# Notes - - :bell - this option uses the ASCII bell character out stdout - - :speaker_test - this uses the linux speaker-test command if installed +* Some terminal emulators intercept and/or silence beeps. Remote terminal sessions can add further complication. Be sure to check relevant configuration options to accomplish what you want. -Very likely, we'll be adding to this list if people find this to be useful. diff --git a/plugins/beep/lib/beep.rb b/plugins/beep/lib/beep.rb index 2a9217b7..f91cc92a 100755 --- a/plugins/beep/lib/beep.rb +++ b/plugins/beep/lib/beep.rb @@ -1,4 +1,5 @@ require 'ceedling/plugin' +require 'ceedling/exceptions' require 'beep_tools' BEEP_ROOT_NAME = 'beep'.freeze @@ -15,24 +16,46 @@ def setup } if @tools[:beep_on_done].nil? - @ceedling[:streaminator].stderr_puts("Tool :beep_on_done is not defined.", verbosity=Verbosity::COMPLAIN) + raise CeedlingException.new("Option '#{@config[:on_done]}' for plugin :beep ↳ :on_done configuration did not map to a tool.") end if @tools[:beep_on_error].nil? - @ceedling[:streaminator].stderr_puts("Tool :beep_on_error is not defined.", verbosity=Verbosity::COMPLAIN) + raise CeedlingException.new("Option '#{@config[:on_done]}' for plugin :beep ↳ :on_error configuration did not map to a tool.") end end def post_build - return if @tools[:beep_on_done].nil? - command = @ceedling[:tool_executor].build_command_line(@tools[:beep_on_done], []) - system(command[:line]) + if @tools[:beep_on_done].nil? + @ceedling[:streaminator].stderr_puts("Tool for :beep ↳ :on_done event handling is not available", Verbosity::COMPLAIN) + return + end + + command = @ceedling[:tool_executor].build_command_line( + @tools[:beep_on_done], + [], + ["ceedling build done"]) # Only used by tools with `${1}` replacement arguments + + @ceedling[:streaminator].stdout_puts("Command: #{command}", Verbosity::DEBUG) + + # Verbosity is enabled to allow shell output (primarily for sake of the bell character) + @ceedling[:system_wrapper].shell_system( command: command[:line], verbose: true ) end def post_error - return if @tools[:beep_on_error].nil? - command = @ceedling[:tool_executor].build_command_line(@tools[:beep_on_error], []) - system(command[:line]) + if @tools[:beep_on_error].nil? + @ceedling[:streaminator].stderr_puts("Tool for :beep ↳ :on_error event handling is not available", Verbosity::COMPLAIN) + return + end + + command = @ceedling[:tool_executor].build_command_line( + @tools[:beep_on_error], + [], + ["ceedling build error"]) # Only used by tools with `${1}` replacement arguments + + @ceedling[:streaminator].stdout_puts("Command: #{command}", Verbosity::DEBUG) + + # Verbosity is enabled to allow shell output (primarily for sake of the bell character) + @ceedling[:system_wrapper].shell_system( command: command[:line], verbose: true ) end end diff --git a/plugins/beep/lib/beep_tools.rb b/plugins/beep/lib/beep_tools.rb index 51f54d7a..a3df00f4 100644 --- a/plugins/beep/lib/beep_tools.rb +++ b/plugins/beep/lib/beep_tools.rb @@ -1,23 +1,49 @@ BEEP_TOOLS = { + + # Most generic beep option across all platforms -- echo the ASCII bell character :bell => { - :executable => 'echo'.freeze, + :executable => 'echo'.freeze, # Using `echo` shell command / command line application :name => 'default_beep_bell'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :optional => false.freeze, :arguments => [ - *('-ne'.freeze unless SystemWrapper.windows?), - "\x07".freeze + *('-n'.freeze unless SystemWrapper.windows?), # No trailing newline for Unix-style echo (argument omitted on Windows) + "\x07".freeze # Unprintable ASCII bell character, escaped in Ruby string ].freeze }.freeze, + + # Terminal put the bell character on Unix-derived platforms + :tput => { + :executable => 'tput'.freeze, # `tput` command line application + :name => 'default_beep_tput'.freeze, + :arguments => [ + "bel".freeze # `tput` argument for bell character (named 'bel' in ASCII standard) + ].freeze + }.freeze, + + # Old but widely available `beep` tone generator package for Unix-derived platforms (not macOS) + :beep => { + :executable => 'beep'.freeze, # `beep` command line application + :name => 'default_beep_beep'.freeze, + :arguments => [].freeze # Default beep (no arguments) + }.freeze, + + # Widely available tone generator package for Unix-derived platforms (not macOS) :speaker_test => { - :executable => 'speaker-test'.freeze, + :executable => 'speaker-test'.freeze, # `speaker-test` command line application :name => 'default_beep_speaker_test'.freeze, - :stderr_redirect => StdErrRedirect::NONE.freeze, - :optional => false.freeze, + :arguments => [ # 1000 hz sine wave frequency + '-t sine'.freeze, + '-f 1000'.freeze, + '-l 1'.freeze + ].freeze + }.freeze, + + # macOS text to speech + :say => { + :executable => 'say'.freeze, # macOS `say` command line application + :name => 'default_beep_say'.freeze, :arguments => [ - - '-t sine'.freeze, - - '-f 1000'.freeze, - - '-l 1'.freeze + "\"${1}\"" # Replacement argument for text ].freeze - }.freeze + }.freeze, + }.freeze