سؤال

لقد اكتشفت هذا في حين باستخدام روبي printf ، ولكنه ينطبق أيضا على ج printf.

إذا قمت بتضمين ANSI اللون هروب رموز في سلسلة الإنتاج ، فإنه عبث المحاذاة.

روبي:

ruby-1.9.2-head > printf "%20s\n%20s\n", "\033[32mGreen\033[0m", "Green"
      Green          # 6 spaces to the left of this one
               Green # correctly padded to 20 chars
 => nil

نفس الخط في برنامج C تنتج نفس الناتج.

هناك على أية حال الحصول على printf (أو شيء آخر) مواءمة المخرجات وليس إضافة مساحات غير المطبوعة الشخصيات ؟

هل هذا خطأ أم أن هناك سبب وجيه لذلك ؟

تحديث: منذ printf لا يمكن الاعتماد على محاذاة البيانات عندما يكون هناك رموز ANSI واسعة حرف ، هل هناك أفضل الممارسات طريقة اصطفاف الملونة جداول البيانات في وحدة التحكم في روبي ؟

هل كانت مفيدة؟

المحلول

أنا لا أتفق مع توصيف '9 المساحات بعد الأخضر الأخضر'.يمكنني استخدام بيرل بدلا من روبي, ولكن إذا كنت تستخدم تعديل البيان ، الطباعة رمزا الأنابيب بعد سلسلة أحصل على:

perl -e 'printf "%20s|\n%20s|\n", "\033[32mGreen\033[0m", "Green";'
      Green|
               Green|

هذا يظهر لي أن printf() بيان عد 14 الشخصيات في السلسلة ، لذلك إرفاق مسبقا 6 مساحات لإنتاج 20 حرفا محاذاة إلى اليمين.ومع ذلك ، فإن محطة ابتلع 9 من تلك الشخصيات تفسيرها كما يتغير اللون.حتى الإخراج ظهر 9 شخصيات أقصر مما كنت أرغب في ذلك.ومع ذلك ، printf() لم تتم طباعة 9 الفراغات بعد أول 'الأخضر'.


بشأن أفضل الممارسات الانحياز الناتج (مع colourization), أعتقد أنك سوف تحتاج إلى أن يكون كل الحجم و الانحياز حقل محاط بسيطة '%s' الحقول التي تتعامل مع colourization:

printf "%s%20.20s%s|%s%-10d%s|%s%12.12s%s|\n",
       co_green, column_1_data, co_plain,
       co_blue,  column_2_data, co_plain,
       co_red,   column_3_data, co_plain;

حيث من الواضح ، co_XXXX المتغيرات (الثوابت?) تحتوي على تسلسلات الهروب إلى التبديل إلى اسمه اللون (و co_plain قد يكون أفضل co_black).إذا اتضح أنك لا تحتاج colourization على بعض الحقول ، يمكنك استخدام سلسلة فارغة في مكان co_XXXX المتغيرات (أو يطلق عليه co_empty).

نصائح أخرى

إنها ليست خطأ: لا توجد طريقة يجب أن يعرفها روبي (على الأقل داخل printf ، ستكون قصة مختلفة عن شيء مثل اللعنات) أن stdout ستذهب إلى محطة تتفهم تسلسل الهروب VT100.

إذا كنت لا تقوم بضبط ألوان الخلفية ، فقد يكون شيء من هذا القبيل فكرة أفضل:

GREEN = "\033[32m"
NORMAL = "\033[0m"
printf "%s%20s%s\n", GREEN, "Green", NORMAL

printf لا تعد محددات عرض الحقل مفيدة لمحاذاة البيانات الجدولية وعناصر الواجهة ، وما إلى ذلك. بصرف النظر عن مسألة أحرف التحكم التي اكتشفتها بالفعل ، هناك أيضًا أحرف غير متوقعة وعرض مزدوج سيتعين على برنامجك التعامل معها إذا كنت لا ترتدي " تريد الحد من الأشياء على تشفير الأحرف القديمة (التي يعتبرها العديد من المستخدمين إهمالًا).

إذا أصرت على استخدام printf بهذه الطريقة ، ربما تحتاج إلى القيام بشيء مثل:

printf("%*s\n%*s\n", bytestopad("\033[32mGreen\033[0m", 20), "\033[32mGreen\033[0m", bytestopad("Green", 20), "Green");

أين bytestopad(s,n) هي وظيفة تكتبها تحسب عدد البايتات الإجمالية اللازمة (مساحات الحشو سلسلة) لتؤدي إلى السلسلة s احترف n الأعمدة الطرفية. هذا من شأنه أن يتضمن تحليل الهروب ومعالجة الأحرف متعددة الفئران واستخدام منشأة (مثل Posix wcwidth وظيفة) للبحث عن عدد الأعمدة الطرفية التي يأخذها كل منها. لاحظ استخدام * بدلاً من عرض مجال ثابت في printf سلسلة تنسيق. هذا يسمح لك بتمرير int حجة ل printf لعرض الحقل المتغير وقت التشغيل.

أود أن أفصل أي تسلسل هروب من النص الفعلي لتجنب المسألة برمتها.

# in Ruby
printf "%s%20s\n%s%20s\n", "\033[32m", "Green", "\033[0m", "Green"

أو

/* In C */
printf("%s%20s\n%s%20s\n", "\033[32m", "Green", "\033[0m", "Green");

نظرًا لأن تسلسل ANSI Escape ليس جزءًا من Ruby أو C لا يعتقد أنه يحتاج إلى معاملة هذه الشخصيات خاصة ، وهي محقة في ذلك.

إذا كنت ستقوم بالكثير من الأشياء الملونة الطرفية ، فيجب عليك النظر في اللعنات والرسومات التي توفر وظائف لإجراء تغييرات في الألوان التي تعمل مع العديد من أنواع المحطات المختلفة. كما أنها توفر المزيد من الوظائف ، مثل النوافذ المستندة إلى النص ، ومفاتيح الوظائف ، وأحيانًا تفاعل الماوس.

إليك الحل الذي توصلت إليه مؤخرًا. هذا يتيح لك الاستخدام color("my string", :red) في printf بيان. أحب استخدام نفس سلسلة التنسيق للرؤوس والبيانات - الجافة. هذا يجعل ذلك ممكنا. أيضا ، أنا استخدم قوس المطر جوهرة لتوليد رموز الألوان. إنه ليس مثاليًا ولكنه ينجز المهمة. ال CPAD يحتوي التجزئة على قيمتين لكل لون ، المقابل للحشو الأيسر واليمين ، على التوالي. وبطبيعة الحال ، يجب أن يمتد هذا الحل لتسهيل الألوان والمعدلات الأخرى مثل الجريئة والتسديد.

CPAD = {
  :default => [0, 2],
  :green   => [0, 3],
  :yellow  => [0, 2],
  :red     => [0, 1],
}

def color(text, color)
  "%*s%s%*s" % [CPAD[color][0], '', text.color(color), CPAD[color][1], '']
end

مثال:

puts "%-10s   %-10s   %-10s   %-10s" % [
  color('apple',  :red),
  color('pear',   :green),
  color('banana', :yellow)
  color('kiwi',   :default)
]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top