diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..1e99662f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,81 @@ +cmake_minimum_required(VERSION 3.20) +project(fortplot VERSION 2025.08.17 LANGUAGES Fortran C) + +# Set build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +# Compiler options +set(CMAKE_Fortran_FLAGS "-Wall -Wextra -fimplicit-none") +set(CMAKE_Fortran_FLAGS_DEBUG "-g -O0 -fcheck=all") +set(CMAKE_Fortran_FLAGS_RELEASE "-O3") + +# Set position independent code for shared library support +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Find all source files automatically +file(GLOB_RECURSE FORTRAN_SOURCES "src/*.f90") +file(GLOB_RECURSE C_SOURCES "src/*.c") + +# Debug output +list(LENGTH FORTRAN_SOURCES fortran_count) +list(LENGTH C_SOURCES c_count) +message(STATUS "Found ${fortran_count} Fortran source files") +message(STATUS "Found ${c_count} C source files") + +# Create the fortplot library +add_library(fortplot ${FORTRAN_SOURCES} ${C_SOURCES}) + +# Set Fortran module directory +set_target_properties(fortplot PROPERTIES + Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules +) + +# Include module directory for dependent projects +target_include_directories(fortplot + PUBLIC + $ + $ +) + +# Create namespaced alias for use in parent projects +add_library(fortplot::fortplot ALIAS fortplot) + +# Export configuration for find_package() support +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + # This is a subproject - don't install + message(STATUS "fortplot configured as subproject") +else() + # This is the main project - configure install + include(GNUInstallDirs) + + install(TARGETS fortplot + EXPORT fortplotTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) + + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.mod" + ) + + install(EXPORT fortplotTargets + FILE fortplotTargets.cmake + NAMESPACE fortplot:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fortplot + ) + + include(CMakePackageConfigHelpers) + configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/fortplotConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/fortplotConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fortplot + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fortplotConfig.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fortplot + ) +endif() \ No newline at end of file diff --git a/src/fortplot.f90 b/src/fortplot.f90 index 8ac35774..522551c3 100644 --- a/src/fortplot.f90 +++ b/src/fortplot.f90 @@ -18,6 +18,9 @@ module fortplot use fortplot_figure, only: figure_t use fortplot_format_parser, only: parse_format_string, contains_format_chars use fortplot_animation, only: animation_t, FuncAnimation + use fortplot_logging, only: set_log_level, log_error, log_warning, log_info, & + LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, & + LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG implicit none @@ -37,6 +40,10 @@ module fortplot ! Animation interface public :: animation_t, FuncAnimation + + ! Logging interface + public :: set_log_level, LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, & + LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG ! Line style constants (pyplot-style) character(len=*), parameter, public :: LINESTYLE_SOLID = '-' @@ -225,7 +232,7 @@ subroutine hist(data, bins, density, label, color) call ensure_global_figure_initialized() ! TODO: Implement hist method in figure_core ! call fig%hist(data, bins=bins, density=density, label=label, color=color) - print *, "ERROR: hist() not yet implemented - please use main branch for histogram support" + call log_error("hist() not yet implemented - please use main branch for histogram support") end subroutine hist subroutine histogram(data, bins, density, label, color) @@ -253,7 +260,7 @@ subroutine histogram(data, bins, density, label, color) call ensure_global_figure_initialized() ! TODO: Implement hist method in figure_core ! call fig%hist(data, bins=bins, density=density, label=label, color=color) - print *, "ERROR: hist() not yet implemented - please use main branch for histogram support" + call log_error("hist() not yet implemented - please use main branch for histogram support") end subroutine histogram subroutine boxplot(data, position, width, label, show_outliers, horizontal, color) @@ -285,7 +292,7 @@ subroutine boxplot(data, position, width, label, show_outliers, horizontal, colo ! TODO: Implement boxplot method in figure_core ! call fig%boxplot(data, position=position, width=width, label=label, & ! show_outliers=show_outliers, horizontal=horizontal, color=color) - print *, "ERROR: boxplot() not yet implemented - please use main branch for boxplot support" + call log_error("boxplot() not yet implemented - please use main branch for boxplot support") end subroutine boxplot subroutine show_data(x, y, label, title_text, xlabel_text, ylabel_text, blocking) @@ -666,13 +673,13 @@ subroutine show_viewer_implementation(blocking) call execute_command_line(command, wait=.false., exitstat=stat) if (stat /= 0) then - print *, 'Warning: Failed to open plot viewer. Plot saved to: ', trim(temp_filename) - print *, 'Please open the file manually with your preferred PDF viewer.' + call log_warning('Failed to open plot viewer. Plot saved to: ' // trim(temp_filename)) + call log_info('Please open the file manually with your preferred PDF viewer.') else - print *, 'Plot opened in default viewer. File: ', trim(temp_filename) + call log_info('Plot opened in default viewer. File: ' // trim(temp_filename)) if (do_block) then - print *, 'Press Enter to continue and clean up temporary file...' + call log_info('Press Enter to continue and clean up temporary file...') read(*,*) ! Clean up temporary file @@ -688,7 +695,7 @@ subroutine show_viewer_implementation(blocking) call execute_command_line(command) else ! In non-blocking mode, just inform that file stays - print *, 'Note: Temporary file will remain at: ', trim(temp_filename) + call log_info('Note: Temporary file will remain at: ' // trim(temp_filename)) end if end if end subroutine show_viewer_implementation diff --git a/src/fortplot_animation.f90 b/src/fortplot_animation.f90 index e1402d80..348997fc 100644 --- a/src/fortplot_animation.f90 +++ b/src/fortplot_animation.f90 @@ -4,6 +4,7 @@ module fortplot_animation use fortplot_pipe, only: open_ffmpeg_pipe, write_png_to_pipe, close_ffmpeg_pipe use fortplot_png, only: png_context, create_png_canvas, get_png_data use fortplot_mpeg1_format, only: encode_animation_to_mpeg1 + use fortplot_logging, only: log_error, log_info, log_warning implicit none private @@ -63,11 +64,11 @@ subroutine run(self) integer :: i if (.not. associated(self%animate_func)) then - print *, "Error: Animation callback function not associated" + call log_error("Animation callback function not associated") return end if - print *, "Running animation with", self%frames, "frames..." + call log_info("Running animation with frames...") do i = 1, self%frames call self%animate_func(i) @@ -78,7 +79,7 @@ subroutine run(self) end if end do - print *, "Animation completed." + call log_info("Animation completed.") end subroutine run subroutine set_save_frames(self, pattern) @@ -119,13 +120,13 @@ subroutine save(self, filename, fps, status) if (.not. is_video_format(extension)) then if (present(status)) status = -3 - print *, "Error: Unsupported file format. Use .mp4, .avi, or .mkv" + call log_error("Unsupported file format. Use .mp4, .avi, or .mkv") return end if if (.not. check_ffmpeg_available()) then if (present(status)) status = -1 - print *, "Error: ffmpeg not found. Please install ffmpeg to save animations." + call log_error("ffmpeg not found. Please install ffmpeg to save animations.") return end if @@ -230,7 +231,7 @@ subroutine save_animation_with_ffmpeg_pipe(anim, filename, fps, status) if (should_use_native_encoder(anim, filename)) then call save_animation_with_native_mpeg1(anim, filename, fps, status) if (status == 0) return ! Native encoder succeeded - print *, "Native MPEG-1 encoder failed, falling back to FFmpeg" + call log_warning("Native MPEG-1 encoder failed, falling back to FFmpeg") end if ! Fall back to FFmpeg pipeline @@ -327,7 +328,7 @@ subroutine save_animation_with_ffmpeg_pipeline(anim, filename, fps, status) stat = open_ffmpeg_pipe(filename, fps) if (stat /= 0) then status = -4 - print *, "Error: Could not open pipe to ffmpeg" + call log_error("Could not open pipe to ffmpeg") return end if @@ -335,7 +336,7 @@ subroutine save_animation_with_ffmpeg_pipeline(anim, filename, fps, status) call generate_png_frame_data(anim, frame_idx, png_data, stat) if (stat /= 0) then status = -5 - print *, "Error: Failed to generate frame", frame_idx + call log_error("Failed to generate frame") stat = close_ffmpeg_pipe() return end if @@ -343,7 +344,7 @@ subroutine save_animation_with_ffmpeg_pipeline(anim, filename, fps, status) stat = write_png_to_pipe(png_data) if (stat /= 0) then status = -6 - print *, "Error: Failed to write frame to pipe", frame_idx + call log_error("Failed to write frame to pipe") stat = close_ffmpeg_pipe() return end if @@ -358,7 +359,7 @@ subroutine save_animation_with_ffmpeg_pipeline(anim, filename, fps, status) status = 0 else status = -7 - print *, "Error: Generated video failed validation" + call log_error("Generated video failed validation") end if end subroutine save_animation_with_ffmpeg_pipeline diff --git a/src/fortplot_ascii.f90 b/src/fortplot_ascii.f90 index b722a23f..d9dc0d8b 100644 --- a/src/fortplot_ascii.f90 +++ b/src/fortplot_ascii.f90 @@ -8,6 +8,7 @@ module fortplot_ascii !! Author: fortplot contributors use fortplot_context + use fortplot_logging, only: log_info use fortplot_latex_parser use fortplot_unicode use, intrinsic :: iso_fortran_env, only: wp => real64 @@ -251,7 +252,7 @@ subroutine ascii_finalize(this, filename) open(newunit=unit, file=filename, status='replace') call output_to_file(this, unit) close(unit) - print *, "Unicode plot saved to '", trim(filename), "'" + call log_info("Unicode plot saved to '" // trim(filename) // "'") end if end subroutine ascii_finalize diff --git a/src/fortplot_figure_core.f90 b/src/fortplot_figure_core.f90 index cd75c3a7..2e780de7 100644 --- a/src/fortplot_figure_core.f90 +++ b/src/fortplot_figure_core.f90 @@ -13,6 +13,7 @@ module fortplot_figure_core use fortplot_scales use fortplot_utils use fortplot_axes + use fortplot_logging, only: log_warning, log_info use fortplot_gltf, only: gltf_context use fortplot_colormap use fortplot_pcolormesh @@ -27,7 +28,8 @@ module fortplot_figure_core private public :: figure_t, plot_data_t, subplot_t - public :: PLOT_TYPE_LINE, PLOT_TYPE_CONTOUR, PLOT_TYPE_PCOLORMESH, PLOT_TYPE_ERRORBAR, PLOT_TYPE_BAR, PLOT_TYPE_HISTOGRAM, PLOT_TYPE_BOXPLOT + public :: PLOT_TYPE_LINE, PLOT_TYPE_CONTOUR, PLOT_TYPE_PCOLORMESH, & + PLOT_TYPE_ERRORBAR, PLOT_TYPE_BAR, PLOT_TYPE_HISTOGRAM, PLOT_TYPE_BOXPLOT integer, parameter :: PLOT_TYPE_LINE = 1 integer, parameter :: PLOT_TYPE_CONTOUR = 2 @@ -630,11 +632,11 @@ subroutine savefig(self, filename, blocking) call self%backend%save(filename) end select - write(*, '(A, A, A)') 'Saved figure: ', trim(filename) + call log_info('Saved figure: ' // trim(filename)) ! If blocking requested, wait for user input if (do_block) then - print *, "Press Enter to continue..." + call log_info("Press Enter to continue...") read(*,*) end if end subroutine savefig @@ -663,7 +665,7 @@ subroutine show(self, blocking) ! If blocking requested, wait for user input if (do_block) then - print *, "Press Enter to continue..." + call log_info("Press Enter to continue...") read(*,*) end if end subroutine show @@ -2536,23 +2538,22 @@ subroutine set_ydata(self, plot_index, y_new) real(wp), intent(in) :: y_new(:) if (plot_index < 1 .or. plot_index > self%plot_count) then - print *, "Warning: Invalid plot index", plot_index, "for set_ydata" + call log_warning("Invalid plot index for set_ydata") return end if if (self%plots(plot_index)%plot_type /= PLOT_TYPE_LINE) then - print *, "Warning: set_ydata only supported for line plots" + call log_warning("set_ydata only supported for line plots") return end if if (.not. allocated(self%plots(plot_index)%y)) then - print *, "Warning: Plot", plot_index, "has no y data to update" + call log_warning("Plot has no y data to update") return end if if (size(y_new) /= size(self%plots(plot_index)%y)) then - print *, "Warning: New y data size", size(y_new), & - "does not match existing size", size(self%plots(plot_index)%y) + call log_warning("New y data size does not match existing size") return end if @@ -2634,7 +2635,7 @@ subroutine ensure_directory_exists(filename) write(command, '(A,A,A)') 'mkdir -p "', trim(dir_path), '"' call execute_command_line(command, exitstat=status) if (status /= 0) then - print *, "Warning: Could not create directory: ", trim(dir_path) + call log_warning("Could not create directory: " // trim(dir_path)) end if end if end subroutine ensure_directory_exists diff --git a/src/fortplot_gltf.f90 b/src/fortplot_gltf.f90 index 3a0d67a1..81058be7 100644 --- a/src/fortplot_gltf.f90 +++ b/src/fortplot_gltf.f90 @@ -6,6 +6,7 @@ module fortplot_gltf use fortplot_context, only: plot_context, setup_canvas use fortplot_gltf_base use fortplot_gltf_writer + use fortplot_logging, only: log_info, log_error use fortplot_gltf_geometry use fortplot_gltf_buffer use fortplot_glb_writer @@ -76,9 +77,9 @@ subroutine save_gltf(this, filename) ! Write GLB binary format if (allocated(this%buffer_data)) then call write_glb_file(filename, json, this%buffer_data) - print *, "GLB file '" // trim(filename) // "' created successfully!" + call log_info("GLB file '" // trim(filename) // "' created successfully!") else - print *, "Error: No binary data for GLB file" + call log_error("No binary data for GLB file") end if else ! Write GLTF text format @@ -87,9 +88,9 @@ subroutine save_gltf(this, filename) if (iostat == 0) then write(unit, '(A)') json close(unit) - print *, "GLTF file '" // trim(filename) // "' created successfully!" + call log_info("GLTF file '" // trim(filename) // "' created successfully!") else - print *, "Error: Failed to create GLTF file" + call log_error("Failed to create GLTF file") end if end if diff --git a/src/fortplot_logging.f90 b/src/fortplot_logging.f90 new file mode 100644 index 00000000..7ae83de3 --- /dev/null +++ b/src/fortplot_logging.f90 @@ -0,0 +1,65 @@ +module fortplot_logging + !! Simple logging facility for fortplot library + !! Allows control over console output verbosity + + implicit none + private + + public :: set_log_level, log_info, log_warning, log_error, log_debug + public :: LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG + + ! Log levels (in increasing verbosity) + integer, parameter :: LOG_LEVEL_SILENT = 0 + integer, parameter :: LOG_LEVEL_ERROR = 1 + integer, parameter :: LOG_LEVEL_WARNING = 2 + integer, parameter :: LOG_LEVEL_INFO = 3 + integer, parameter :: LOG_LEVEL_DEBUG = 4 + + ! Default log level (warnings and errors only) + integer :: current_log_level = LOG_LEVEL_WARNING + +contains + + subroutine set_log_level(level) + !! Set the global logging level + !! + !! Arguments: + !! level: LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, + !! LOG_LEVEL_INFO, or LOG_LEVEL_DEBUG + integer, intent(in) :: level + current_log_level = level + end subroutine set_log_level + + subroutine log_info(message) + !! Log an informational message + character(len=*), intent(in) :: message + if (current_log_level >= LOG_LEVEL_INFO) then + print *, "[INFO] ", trim(message) + end if + end subroutine log_info + + subroutine log_warning(message) + !! Log a warning message + character(len=*), intent(in) :: message + if (current_log_level >= LOG_LEVEL_WARNING) then + print *, "[WARNING] ", trim(message) + end if + end subroutine log_warning + + subroutine log_error(message) + !! Log an error message + character(len=*), intent(in) :: message + if (current_log_level >= LOG_LEVEL_ERROR) then + print *, "[ERROR] ", trim(message) + end if + end subroutine log_error + + subroutine log_debug(message) + !! Log a debug message + character(len=*), intent(in) :: message + if (current_log_level >= LOG_LEVEL_DEBUG) then + print *, "[DEBUG] ", trim(message) + end if + end subroutine log_debug + +end module fortplot_logging \ No newline at end of file diff --git a/src/fortplot_pdf.f90 b/src/fortplot_pdf.f90 index 36038dce..7edab64e 100644 --- a/src/fortplot_pdf.f90 +++ b/src/fortplot_pdf.f90 @@ -3,6 +3,7 @@ module fortplot_pdf use fortplot_vector, only: vector_stream_writer, vector_graphics_state use fortplot_latex_parser use fortplot_unicode + use fortplot_logging, only: log_info use fortplot_margins, only: plot_margins_t, plot_area_t, calculate_plot_area, get_axis_tick_positions use fortplot_ticks, only: generate_scale_aware_tick_labels, find_nice_tick_locations, format_tick_value_smart use fortplot_label_positioning, only: calculate_x_label_position, calculate_y_label_position, & @@ -427,7 +428,7 @@ subroutine write_pdf_file(this, filename) call finalize_pdf_stream(this) call create_pdf_document(unit, filename, this) - print *, "PDF file '", trim(filename), "' created successfully!" + call log_info("PDF file '" // trim(filename) // "' created successfully!") end subroutine write_pdf_file subroutine normalize_to_pdf_coords(ctx, x, y, pdf_x, pdf_y) diff --git a/src/fortplot_png.f90 b/src/fortplot_png.f90 index d022f113..6837d401 100644 --- a/src/fortplot_png.f90 +++ b/src/fortplot_png.f90 @@ -3,6 +3,7 @@ module fortplot_png use fortplot_context, only: setup_canvas use fortplot_raster, only: raster_context, create_raster_canvas, draw_axes_and_labels, draw_rotated_ylabel_raster use fortplot_zlib, only: zlib_compress, crc32_calculate + use fortplot_logging, only: log_error, log_info use, intrinsic :: iso_fortran_env, only: wp => real64, int8, int32 implicit none @@ -57,7 +58,7 @@ subroutine generate_png_data(width, height, image_data, png_buffer) compressed_data = zlib_compress(image_data, data_size, compressed_size) if (.not. allocated(compressed_data) .or. compressed_size <= 0) then - print *, "Compression failed" + call log_error("PNG compression failed") return end if @@ -124,7 +125,7 @@ subroutine write_png_file(filename, width, height, image_data) close(png_unit) deallocate(png_buffer) - print *, "PNG file '", trim(filename), "' created successfully!" + call log_info("PNG file '" // trim(filename) // "' created successfully!") end subroutine write_png_file ! Public wrapper for getting PNG data diff --git a/src/fortplot_raster.f90 b/src/fortplot_raster.f90 index 89a9fa17..69e13fa3 100644 --- a/src/fortplot_raster.f90 +++ b/src/fortplot_raster.f90 @@ -4,6 +4,7 @@ module fortplot_raster use fortplot_text, only: render_text_to_image, calculate_text_width, calculate_text_height use fortplot_latex_parser use fortplot_unicode + use fortplot_logging, only: log_error use fortplot_margins, only: plot_margins_t, plot_area_t, calculate_plot_area, get_axis_tick_positions use fortplot_ticks, only: generate_scale_aware_tick_labels, format_tick_value_smart, find_nice_tick_locations use fortplot_label_positioning, only: calculate_x_label_position, calculate_y_label_position, & @@ -600,7 +601,7 @@ subroutine raster_save_dummy(this, filename) character(len=*), intent(in) :: filename ! This is a dummy implementation - concrete backends like PNG will override this - print *, "Error: raster_context cannot save files directly. Use a concrete backend like PNG." + call log_error("raster_context cannot save files directly. Use a concrete backend like PNG.") stop end subroutine raster_save_dummy diff --git a/src/fortplot_text.f90 b/src/fortplot_text.f90 index e4f74ab6..9833c5c6 100644 --- a/src/fortplot_text.f90 +++ b/src/fortplot_text.f90 @@ -2,6 +2,7 @@ module fortplot_text use iso_c_binding use fortplot_stb_truetype use fortplot_unicode, only: utf8_to_codepoint, utf8_char_length + use fortplot_logging, only: log_error use, intrinsic :: iso_fortran_env, only: wp => real64 implicit none @@ -36,7 +37,7 @@ function init_text_system() result(success) success = discover_and_init_font() if (.not. success) then - print *, "Error: Could not initialize STB TrueType - no fonts found" + call log_error("Could not initialize STB TrueType - no fonts found") end if end function init_text_system @@ -253,7 +254,7 @@ function calculate_text_width(text) result(width) ! Initialize text system if not already done if (.not. font_initialized) then if (.not. init_text_system()) then - print *, "ERROR: STB TrueType initialization failed in calculate_text_width" + call log_error("STB TrueType initialization failed in calculate_text_width") width = len_trim(text) * 8 ! Fallback estimate return end if diff --git a/test/test_logging_system.f90 b/test/test_logging_system.f90 new file mode 100644 index 00000000..413780d1 --- /dev/null +++ b/test/test_logging_system.f90 @@ -0,0 +1,56 @@ +program test_logging_system + !! Test program to validate the new logging system + !! Demonstrates control over console output verbosity + + use fortplot, only: set_log_level, LOG_LEVEL_SILENT, LOG_LEVEL_ERROR, & + LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG + use fortplot_logging, only: log_info, log_warning, log_error, log_debug + + implicit none + + print *, "=== Testing fortplot logging system ===" + + ! Test default level (warnings and errors) + print *, "Default level (warnings and errors):" + call log_error("This error should appear") + call log_warning("This warning should appear") + call log_info("This info should NOT appear") + call log_debug("This debug should NOT appear") + + print *, "" + + ! Test silent level + print *, "Silent level (no output):" + call set_log_level(LOG_LEVEL_SILENT) + call log_error("This error should NOT appear") + call log_warning("This warning should NOT appear") + call log_info("This info should NOT appear") + call log_debug("This debug should NOT appear") + + print *, "" + + ! Test info level + print *, "Info level (all except debug):" + call set_log_level(LOG_LEVEL_INFO) + call log_error("This error should appear") + call log_warning("This warning should appear") + call log_info("This info should appear") + call log_debug("This debug should NOT appear") + + print *, "" + + ! Test debug level (all messages) + print *, "Debug level (all messages):" + call set_log_level(LOG_LEVEL_DEBUG) + call log_error("This error should appear") + call log_warning("This warning should appear") + call log_info("This info should appear") + call log_debug("This debug should appear") + + print *, "" + print *, "=== Logging system test completed ===" + + ! Reset to default for other tests + call set_log_level(LOG_LEVEL_WARNING) + +end program test_logging_system \ No newline at end of file diff --git a/test/test_silent_output.f90 b/test/test_silent_output.f90 new file mode 100644 index 00000000..a7e92b0f --- /dev/null +++ b/test/test_silent_output.f90 @@ -0,0 +1,28 @@ +program test_silent_output + !! Test program to verify silent output works in production + !! Should demonstrate zero output when set to silent level + + use fortplot, only: figure, plot, savefig, set_log_level, LOG_LEVEL_SILENT + + implicit none + real(8) :: x(10), y(10) + integer :: i + + ! Set to silent mode - no console output should occur + call set_log_level(LOG_LEVEL_SILENT) + + ! Generate test data + do i = 1, 10 + x(i) = real(i-1, 8) + y(i) = sin(x(i)) + end do + + ! Create plot - should produce no console output + call figure(400, 300) + call plot(x, y) + call savefig('/tmp/silent_test.png') + + ! This print should still work (it's not going through logging) + print *, "Silent test completed - check /tmp/silent_test.png" + +end program test_silent_output \ No newline at end of file