2011-04-04 66 views
3

在Ubuntu Lucid上使用Emacs 23.2.1,基於Comint的任何模式都會爲較大的輸出插入偶爾的換行符(請參閱下面的示例Shell和SQL模式輸出)。我已經在SQL模式和Shell模式下嘗試了這一點,在這兩種情況下都有相同的結果。在普通終端模擬器中運行類似的命令不會導致這些問題(對於shell模式和mysql模式命令)。Comint模式插入換行符每4096個字符

事情我已經嘗試:

  • 在SQL模式下使用MySQL,加入以下標誌:-A,-C,-t,-f,-n和的max_allowed_pa​​cket設置爲16MB。

  • 設置COMINT緩衝,最大尺寸至10240

這些都不會對這種行爲產生任何影響。

如果我向上滾動到問題的行並刪除換行符,輸出就會正確顯示,因此對於此問題的可能解決方案可能涉及一個鉤子,每刪除一個第4096個字符(如果可能的話)。

注意:在終端示例中,輸出似乎在除4096個字符以外的點處被切斷。在SQL模式下,它正好每4096(確實是一個可疑數字)。

下面是一些示例輸出:

[email protected]:/$ for i in {1..4096}; do echo -n 0; done; echo; 

0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 

在這種情況下,它應該打印出0的單行線,但實際上已經經過904個字符插入新行字符。

另外使用MySQL在SQL模式的示例:

mysql> show variables like '%n%'; 

+-----------------------------------------+----------------------------------+ 
| Variable_name       | Value       | 
+-----------------------------------------+----------------------------------+ 
| auto_increment_increment    | 1        | 
| auto_increment_offset     | 1        | 
| binlog_cache_size      | 32768       | 
| binlog_format       | STATEMENT      | 
| bulk_insert_buffer_size     | 8388608       | 
| character_set_client     | utf8        | 
| character_set_connection    | utf8        | 
| collation_connection     | utf8_general_ci     | 
| collation_database      | latin1_swedish_ci    | 
| collation_server      | latin1_swedish_ci    | 
| completion_type       | 0        | 
| concurrent_insert      | 1        | 
| connect_timeout       | 10        | 
| delayed_insert_limit     | 100        | 
| delayed_insert_timeout     | 300        | 
| div_precision_increment     | 4        | 
| engine_condition_pushdown    | ON        | 
| error_count        | 0        | 
| event_scheduler       | OFF        | 
| foreign_key_checks      | ON        | 
| ft_boolean_syntax      | + -><()~*:""&|     | 
| ft_max_word_len       | 84        | 
| ft_min_word_len       | 4        | 
| ft_query_expansion_limit    | 20        | 
| general_log        | OFF        | 
| general_log_file      | /var/lib/mysql/battlecruiser.log | 
| group_concat_max_len     | 1024        | 
| have_community_features     | YES        | 
| have_dynamic_loading     | YES        | 
| have_innodb        | YES        | 
| have_ndbcluster       | NO        | 
| have_openssl       | DISABLED       | 
| have_partitioning      | YES        | 
| have_symlink       | YES        | 
| hostname        | battlecruiser     | 
| identity        | 0        | 
| ignore_builtin_innodb     | OFF        | 
| init_connect       |         | 
| init_file        |         | 
| init_slave        |         | 
| innodb_adaptive_hash_index    | ON        | 
| innodb_additional_mem_pool_size   | 1048576       | 
| innodb_autoextend_increment    | 8        | 
| innodb_autoinc_lock_mode    | 1        | 
| innodb_buffer_pool_size     | 8388608       | 
| innodb_checksums      | ON        | 
| innodb_commit_concurrency    | 0        | 
| innodb_concurrency_tickets    | 500        | 
| innodb_data_file_path     | ibdata1:10M:autoextend 
      | 
| innodb_data_home_dir     |         | 
| innodb_doublewrite      | ON        | 
| innodb_fast_shutdown     | 1        | 
| innodb_file_io_threads     | 4        | 
| innodb_file_per_table     | OFF        | 
| innodb_flush_log_at_trx_commit   | 1        | 
| innodb_flush_method      |         | 
| innodb_force_recovery     | 0        | 
| innodb_lock_wait_timeout    | 50        | 
| innodb_locks_unsafe_for_binlog   | OFF        | 
| innodb_log_buffer_size     | 1048576       | 
| innodb_log_file_size     | 5242880       | 
| innodb_log_files_in_group    | 2        | 
| innodb_log_group_home_dir    | ./        | 
| innodb_max_dirty_pages_pct    | 90        | 
| innodb_max_purge_lag     | 0        | 
| innodb_mirrored_log_groups    | 1        | 
| innodb_open_files      | 300        | 
| innodb_rollback_on_timeout    | OFF        | 
| innodb_stats_on_metadata    | ON        | 
| innodb_support_xa      | ON        | 
| innodb_sync_spin_loops     | 20        | 
| innodb_table_locks      | ON        | 
| innodb_thread_concurrency    | 8        | 
| innodb_thread_sleep_delay    | 10000       | 
| innodb_use_legacy_cardinality_algorithm | ON        | 
| insert_id        | 0        | 
| interactive_timeout      | 28800       | 
| join_buffer_size      | 131072       | 
| keep_files_on_create     | OFF        | 
| key_cache_division_limit    | 100        | 
| language        | /usr/share/mysql/english/  | 
| last_insert_id       | 0        | 
| lc_time_names       | en_US       | 
| license         | GPL        | 
| local_infile       | ON        | 
| locked_in_memory      | OFF        | 
| log_bin         | OFF        | 
| log_bin_trust_function_creators   | OFF        | 
| log_bin_trust_routine_creators   | OFF        | 
| log_queries_not_using_indexes   | OFF        | 
| log_warnings       | 1        | 
| long_query_time       | 10.000000      | 
| lower_case_table_names     | 0        | 
| max_binlog_cache_size     | 4294963200      | 
| max_binlog_size       | 104857600      | 
| max_connect_errors      | 10        | 
| max_connections       | 151        | 
| max_error_count       | 64        | 
| max_insert_delayed_threads    | 20        | 
| max_join_size       | 18446744073709551615    | 
| max_length_for_sort_data    | 1024  
         | 
| max_prepared_stmt_count     | 16382       | 
| max_sort_length       | 1024        | 
| max_sp_recursion_depth     | 0        | 
| max_user_connections     | 0        | 
| max_write_lock_count     | 4294967295      | 
| min_examined_row_limit     | 0        | 
| multi_range_count      | 256        | 
| myisam_data_pointer_size    | 6        | 
| myisam_recover_options     | BACKUP       | 
| net_buffer_length      | 16384       | 
| net_read_timeout      | 30        | 
| net_retry_count       | 10        | 
| net_write_timeout      | 60        | 
| new          | OFF        | 
| open_files_limit      | 1024        | 
| optimizer_prune_level     | 1        | 
| plugin_dir        | /usr/lib/mysql/plugin   | 
| profiling        | OFF        | 
| profiling_history_size     | 15        | 
| protocol_version      | 10        | 
| query_cache_min_res_unit    | 4096        | 
| query_cache_wlock_invalidate   | OFF        | 
| rand_seed1        |         | 
| rand_seed2        |         | 
| range_alloc_block_size     | 4096        | 
| read_only        | OFF        | 
| read_rnd_buffer_size     | 262144       | 
| relay_log_index       |         | 
| relay_log_info_file      | relay-log.info     | 
| rpl_recovery_rank      | 0        | 
| skip_external_locking     | ON        | 
| skip_networking       | OFF        | 
| slave_net_timeout      | 3600        | 
| slave_transaction_retries    | 10        | 
| slow_launch_time      | 2        | 
| sql_auto_is_null      | ON        | 
| sql_log_bin        | ON        | 
| sql_max_join_size      | 18446744073709551615    | 
| sql_notes        | ON        | 
| sql_slave_skip_counter     |         | 
| sql_warnings       | OFF        | 
| storage_engine       | MyISAM       | 
| sync_binlog        | 0        | 
| sync_frm        | ON        | 
| system_time_zone      | EDT        | 
| table_definition_cache     | 256        | 
| table_open_cache      | 64        | 
| thread_handling       | one-thread-per-connection  | 
| time_zone        | SYSTEM       | 
| transaction_alloc_block_size   | 8192        | 
| transaction_prealloc_size    | 4096        | 
| tx_isolation       
    | REPEATABLE-READ     | 
| unique_checks       | ON        | 
| version         | 5.1.41-3ubuntu12.10    | 
| version_comment       | (Ubuntu)       | 
| version_compile_machine     | i486        | 
| version_compile_os      | debian-linux-gnu     | 
| warning_count       | 0        | 
+-----------------------------------------+----------------------------------+ 
159 rows in set (0.00 sec) 

在這裏,輸出總是由一個新行以4096個字符確切的時間間隔中斷。

除了可能的解決方案,任何新的方法來找到更多關於正在發生的事情的信息將不勝感激。

回答

3

我找到了解決這個問題的辦法。我已經把我的配置文件來源的下面的代碼從http://www.emacswiki.org/emacs/SqlMode

(defun sql-add-newline-first (output) 
    "Add newline to beginning of OUTPUT for `comint-preoutput-filter-functions'" 
    (concat "\n" output)) 

    (defun sqli-add-hooks() 
    "Add hooks to `sql-interactive-mode-hook'." 
    (add-hook 'comint-preoutput-filter-functions 
       'sql-add-newline-first)) 

    (add-hook 'sql-interactive-mode-hook 'sqli-add-hooks) 

移除代碼(因爲它設置comint-preoutput-filter-functions,影響shell-mode爲好),我不再遇到這些問題後。

我建議更換該代碼來獲得我想要的行爲(對我的作品至今):

(defun sql-add-newline-first (output) 
    "Add newline to beginning of OUTPUT for `comint-preoutput-filter-functions'" 
    (remove-hook 'comint-preoutput-filter-functions 
      'sql-add-newline-first) 
    (concat "\n" output)) 

(defun sql-send-region-better (start end) 
    "Send a region to the SQL process." 
    (interactive "r") 
    (if (buffer-live-p sql-buffer) 
     (save-excursion 
    (add-hook 'comint-preoutput-filter-functions 
      'sql-add-newline-first) 
    (comint-send-region sql-buffer start end) 
    (if (string-match "\n$" (buffer-substring start end)) 
     () 
     (comint-send-string sql-buffer "\n")) 
    (message "Sent string to buffer %s." (buffer-name sql-buffer)) 
    (if sql-pop-to-buffer-after-send-region 
     (pop-to-buffer sql-buffer) 
     (display-buffer sql-buffer))) 
    (message "No SQL process started."))) 

(defvar sql-mode-map 
    (let ((map (make-sparse-keymap))) 
    (define-key map (kbd "C-c C-c") 'sql-send-paragraph) 
    (define-key map (kbd "C-c C-r") 'sql-send-region-better) 
    (define-key map (kbd "C-c C-s") 'sql-send-string) 
    (define-key map (kbd "C-c C-b") 'sql-send-buffer) 
    map) 
    "Mode map used for `sql-mode'.") 

從本質上講,我是我的前右加鉤SQL-發區域,更好的代碼開始發送輸出,然後內掛鉤我再次刪除掛鉤,保證它只插入一個我想要的新行。

+0

嘎!你爲什麼不把它放在wiki頁面中?我用更糟的方式重新實現了它。 – 2013-03-27 15:00:05

+0

實際上,我的實現可以和所有'sql-send- *'命令一起使用,所以我會在這裏發佈它並更新wiki。 – 2013-03-29 23:47:01

4

我有類似的問題,雖然我的休息似乎在1024個字符(ah-ha!在版本21_1中是這種情況)。這對我來說並不是什麼大事,但我寫了一些能正確連接結果的東西,所以我可以對它們進行後處理。儘管如此,這並沒有影響產出,所以它不會有太大的幫助。

你的問題的根源在於read_process_outputprocess.c,其中硬編碼4096:

/* Read pending output from the process channel, 
    starting with our buffered-ahead character if we have one. 
    Yield number of decoded characters read. 

    This function reads at most 4096 characters. 
    If you want to read all available subprocess output, 
    you must call it repeatedly until it returns zero. 

    The characters read are decoded according to PROC's coding-system 
    for decoding. */ 

static int 
read_process_output (proc, channel) 
    Lisp_Object proc; 
    register int channel; 
{ 
    // ... snip 
    int readmax = 4096; 

就像你在你的問題中提到,一個非常可行的解決方案,這將是編寫一個函數(稱之爲,clean-up-comint-output-at-4096-chars),並將其添加到comint-output-filter-functions。像這樣的東西。 注:未經測試的代碼

(add-hook 'comint-output-filter-functions 'clean-up-comint-output-at-4096-chars) 
(defun clean-up-comint-output-at-4096-chars (&optional str) 
    "look for string of 4096 length and remove newline in the buffer" 
    (let ((magic-block-size 4096)) 
    (save-match-data 
     (when (= magic-block-size (length str)) 
     ;; at the magic block size, look for a newline 
     (goto-char (point-max)) 
     (when (and (search-backward str nil t) 
        (progn 
        (forward-char magic-block-size) 
        (looking-at "\n"))) 
      (delete-char 1)))))) 
+0

+1只要知道問題所在就是一個巨大的幫助,謝謝。 – 2011-04-04 17:05:18

+0

@BrentNewey我一直想要自己追蹤多年,希望我提出的解決方案是一個很好的開始幫助它。 – 2011-04-04 17:31:57

+0

我試着將readmax中的值更改爲65536並重新編譯Emacs,但我仍然觀察到相同的結果。不知道是否有其他地方的限制是硬編碼的,或者這種方法是否可行。 – 2011-04-04 17:40:40

1

這裏是我的執行僅在前面加上「\ n」每一次輸入:

(defvar sql-last-prompt-pos 1 
    "position of last prompt when added recording started") 
(make-variable-buffer-local 'sql-last-prompt-pos) 
(put 'sql-last-prompt-pos 'permanent-local t) 



(defun sql-add-newline-first (output) 
    "Add newline to beginning of OUTPUT for 
    `comint-preoutput-filter-functions' 

    This fixes up the display of queries sent to the inferior 
    buffer programatically. But also adds extra new-line for 
    interactive commands. 

    " 
    (let ((begin-of-prompt 
     (or (and comint-last-prompt-overlay 
        ;; sometimes this overlay is not on prompt 
        (save-excursion 
        (goto-char (overlay-start comint-last-prompt-overlay)) 
        (looking-at-p comint-prompt-regexp) 
        (point))) 
      1))) 
    (if (> begin-of-prompt sql-last-prompt-pos) 
     (progn 
      (setq sql-last-prompt-pos begin-of-prompt) 
      (concat "\n" output)) 
     output))) 

(defun le-sqli-setup() 
    "Add hooks to `sql-interactive-mode-hook'." 
    (add-hook 'comint-preoutput-filter-functions 
      'sql-add-newline-first t t)) 
(add-hook 'sql-interactive-mode-hook 'le-sqli-setup) 
+0

我喜歡這個答案。我同意維基需要更新。 – 2013-04-05 13:37:10

0

我的解決辦法 - 增加一個換行符(但隨後的勾去掉,以防止多者將文字)。然後在每個輸入提示處重新添加掛鉤。

(defun sql-add-newline-first (output) 
    "Add newline to beginning of sql OUTPUT, but remove the hook so 
    that it doesn't output a newline everytime the output cache is 
    filled." 
    (remove-hook 'comint-preoutput-filter-functions 'sql-add-newline-first) 
    (concat "\n" output)) 

(defun sql-readd-newline-first (ignore) 
    "Readd the newline putting hook" 
    (add-hook 'comint-preoutput-filter-functions 'sql-add-newline-first)) 

(defun sqli-add-hooks() 
    "Add the 'suicidal' newline printing hook, and another hook to 
    respawn it at every input prompt." 
    (add-hook 'comint-preoutput-filter-functions 'sql-add-newline-first) 
    (add-hook 'comint-input-filter-functions 'sql-readd-newline-first)) 

(add-hook 'sql-interactive-mode-hook 'sqli-add-hooks) 

另外,在我的情況下,我使用的是postgresql。在多行查詢(例如database-#database-#database-#| col | col |)後將額外的提示放在後面,這種討厭的習慣會將列名推開。爲了解決,我最終做到了這一點:

(defun sql-remove-continuing-prompts (output) 
    (concat "\n" (replace-regexp-in-string "warren_hero[^=()]# " "" output))) 

(defun sqli-add-hooks() 
    (add-hook 'comint-preoutput-filter-functions 'sql-remove-continuing-prompts)) 

(add-hook 'sql-interactive-mode-hook 'sqli-add-hooks) 
相關問題