Textmate "comment" command not working properly for css code - css

I'm having some problems when I toggle the comments in TextMate for CSS source code.
Using the shortcut CMD + / I activate the "Comment Line/Selection" command from the "source" bundle. The problem is that it inserts a series of // for all kinds of languages. For example, in CSS files it is supposed to insert a /**/ block, but it doesn't. In CSS files I also tried the "Insert Block Comment" command from the source bundle with the weird result that I get the following //.
// ----------------------------------------
instead of my code, deleting the code and inserting that.
I know I am supposed to modify the command from the bundle, but I can't figure out how and what.
This is the code of the "Comment Line/Selection" command from the "Source" Bundle:
#!/usr/bin/env ruby
# by James Edward Gray II <james (at) grayproductions.net>
#
# To override the operation of this commond for your language add a Preferences
# bundle item that defines the following valiables as appropriate for your
# language:
#
# TM_COMMENT_START - the character string that starts comments, e.g. /*
# TM_COMMENT_END - the character string that ends comments (if appropriate),
# e.g. */
# TM_COMMENT_MODE - the type of comment to use - either 'line' or 'block'
#
require "#{ENV["TM_SUPPORT_PATH"]}/lib/escape"
def out(*args)
print( *args.map do |arg|
escaped = e_sn(arg)
$selected ? escaped.gsub("}", "\\}") : escaped.sub("\0", "${0}")
end )
end
# find all available comment variables
var_suffixes = [""]
2.upto(1.0/0.0) do |n|
if ENV.include? "TM_COMMENT_START_#{n}"
var_suffixes << "_#{n}"
else
break
end
end
text = STDIN.read
default = nil # the comment we will insert, if none are removed
# maintain selection
if text == ENV["TM_SELECTED_TEXT"]
$selected = true
print "${0:"
at_exit { print "}" }
else
$selected = false
end
# try a removal for each comment...
var_suffixes.each do |suffix|
# build comment
com = { :start => ENV["TM_COMMENT_START#{suffix}"] || "# ",
:end => ENV["TM_COMMENT_END#{suffix}"] || "",
:mode => ENV["TM_COMMENT_MODE#{suffix}"] ||
(ENV["TM_COMMENT_END#{suffix}"] ? "block" : "line"),
:no_indent => ENV["TM_COMMENT_DISABLE_INDENT#{suffix}"] }
com[:esc_start], com[:esc_end] = [com[:start], com[:end]].map do |str|
str.gsub(/[\\|()\[\].?*+{}^$]/, '\\\\\&').
gsub(/\A\s+|\s+\z/, '(?:\&)?')
end
# save the first one as our insertion default
default = com if default.nil?
# try a removal
case com[:mode]
when "line" # line by line comment
if text !~ /\A[\t ]+\z/ &&
text.send(text.respond_to?(:lines) ? :lines : :to_s).
map { |l| !!(l =~ /\A\s*(#{com[:esc_start]}|$)/) }.uniq == [true]
if $selected
out text.gsub( /^(\s*)#{com[:esc_start]}(.*?)#{com[:esc_end]}(\s*)$/,
'\1\2\3' )
exit
else
r = text.sub( /^(\s*)#{com[:esc_start]}(.*?)#{com[:esc_end]}(\s*)$/,
'\1\2\3' )
i = ENV["TM_LINE_INDEX"].to_i
i = i > text.index(/#{com[:esc_start]}/) ?
[[0, i - com[:start].length].max, r.length].min :
[i, r.length].min
r[i, 0] = "\0"
out r
exit
end
end
when "block" # block comment
regex = /\A(\s*)#{com[:esc_start]}(.*?)#{com[:esc_end]}(\s*)\z/m
if text =~ regex
if $selected
out text.sub(regex, '\1\2\3')
exit
else
r = text.sub(regex, '\1\2\3')
i = ENV["TM_LINE_INDEX"].to_i
i = i > text.index(/#{com[:esc_start]}/) ?
[[0, i - com[:start].length].max, r.length].min :
[i, r.length].min
r[i, 0] = "\0"
out r
exit
end
end
end
end
# none of our removals worked, so preform an insert (minding indent setting)
text[ENV["TM_LINE_INDEX"].to_i, 0] = "\0" unless $selected or text.empty?
case default[:mode]
when "line" # apply comment line by line
if text.empty?
out "#{default[:start]}\0#{default[:end]}"
elsif default[:no_indent]
out text.gsub(/^.*$/, "#{default[:start]}\\&#{default[:end]}")
elsif text =~ /\A([\t ]*)\0([\t ]*)\z/
out text.gsub(/^.*$/, "#{$1}#{default[:start]}#{$2}#{default[:end]}")
else
indent = text.scan(/^[\t \0]*(?=\S)/).
min { |a, b| a.length <=> b.length } || ""
text.send(text.respond_to?(:lines) ? :lines : :to_s).map do |line|
if line =~ /^(#{indent})(.*)$(\n?)/ then
out $1 + default[:start] + $2 + default[:end] + $3
elsif line =~ /^(.*)$(\n?)/ then
out indent + default[:start] + $1 + default[:end] + $2
end
end
end
when "block" # apply comment around selection
if text.empty?
out default[:start]
print "${0}"
out default[:end]
elsif text =~ /\A([\t ]*)\0([\t ]*)\z/
out $1, default[:start]
print "${0}"
out $2, default[:end]
elsif default[:no_indent]
out default[:start], text, default[:end]
else
lines = text.to_a
if lines.empty?
out default[:start], default[:end]
else
lines[-1].sub!(/^(.*)$/, "\\1#{default[:end]}")
out lines.shift.sub(/^([\s\0]*)(.*)$/, "\\1#{default[:start]}\\2")
out(*lines) unless lines.empty?
end
end
end

Ensure you have the "Source" bundle installed. In the latest Textmate 2 Alpha at the time of writing, go to TextMate -> Preferences -> Bundles -> Check "Source" bundle to install. The CMD + / shortcut should now work.

It is small syntax problem if you're using a Ruby higher then 1.8.7. You will find that to_a method has been removed. If you want to fix the problem all you need to do is modify the code found in this file.
In order to fix the problem you need to search for any location that they call to_a and replace it with Array("string").
In my case I did this. This also should work for you:
lines = text.to_a
with
lines = text.lines.to_a
This should be a solution for every thing. Look to the image to see what file I ended up fixing.

I had the same problem and it turns out that I had an SCSS bundle installed that had a preference set to use "//" for comments with a scope selector for source.css as well as source.scss.
I would check to make sure that you don't have the same SCSS bundle and if you do, change the scope selector of the comments preference to be just source.scss.

Cmd/ has been working for years and still is. Well, my copy of TM2 alpha is broken (doesn't work with the / in the numeric pad but, well, it's alpha) but TM 1.5.x works as it should.
You are not supposed to modify anything anywhere. The Comment Line/Selection command is smart enough to put the right kind of comment in "any" kind of file.
Did you mess with language definitions? Is your file recognized as "CSS"? Does it work when removing all or certain plugins/bundles?
-- EDIT --

Related

Need of awk command explaination

I want to know how the below command is working.
awk '/Conditional jump or move depends on uninitialised value/ {block=1} block {str=str sep $0; sep=RS} /^==.*== $/ {block=0; if (str!~/oracle/ && str!~/OCI/ && str!~/tuxedo1222/ && str!~/vprintf/ && str!~/vfprintf/ && str!~/vtrace/) { if (str!~/^$/){print str}} str=sep=""}' file_name.txt >> CondJump_val.txt
I'd also like to know how to check the texts Oracle, OCI, and so on from the second line only. 
The first step is to write it so it's easier to read
awk '
/Conditional jump or move depends on uninitialised value/ {block=1}
block {
str=str sep $0
sep=RS
}
/^==.*== $/ {
block=0
if (str!~/oracle/ && str!~/OCI/ && str!~/tuxedo1222/ && str!~/vprintf/ && str!~/vfprintf/ && str!~/vtrace/) {
if (str!~/^$/) {
print str
}
}
str=sep=""
}
' file_name.txt >> CondJump_val.txt
It accumulates the lines starting with "Conditional jump ..." ending with "==...== " into a variable str.
If the accumulated string does not match several patterns, the string is printed.
I'd also like to know how to check the texts Oracle, OCI, and so on from the second line only.
What does that mean? I assume you don't want to see the "Conditional jump..." line in the output. If that's the case then use the next command to jump to the next line of input.
/Conditional jump or move depends on uninitialised value/ {
block=1
next
}
perhaps consolidate those regex into a single chain ?
if (str !~ "oracle|OCI|tuxedo1222|v[f]?printf|vtrace") {
print str
}
There are two idiomatic awkisms to understand.
The first can be simplified to this:
$ seq 100 | awk '/^22$/{flag=1}
/^31$/{flag=0}
flag'
22
23
...
30
Why does this work? In awk, flag can be tested even if not yet defined which is what the stand alone flag is doing - the input is only printed if flag is true and flag=1 is only executed when after the regex /^22$/. The condition of flag being true ends with the regex /^31$/ in this simple example.
This is an idiom in awk to executed code between two regex matches on different lines.
In your case, the two regex's are:
/Conditional jump or move depends on uninitialised value/ # start
# in-between, block is true and collect the input into str separated by RS
/^==.*== $/ # end
The other 'awkism' is this:
block {str=str sep $0; sep=RS}
When block is true, collect $0 into str and first time though, RS should not be added in-between the last time. The result is:
str="first lineRSsecond lineRSthird lineRS..."
both depend on awk being able to use a undefined variable without error

How to get the variable's name from a file using source command in UNIX?

I have a file named param1.txt which contains certain variables. I have another file as source1.txt which contains place holders. I want to replace the place holders with the values of the variables that I get from the parameter file.
I have basically hard coded the script where the variable names in the parameter.txt file is known before hand. I want to know a dynamic solution to the problem where the variable names will not be known beforehand. In other words, is there any way to find out the variable names in a file using the source command in UNIX?
Here is my script and the files.
Script:
#!/bin/bash
source /root/parameters/param1.txt
sed "s/{DB_NAME}/$DB_NAME/gI;
s/{PLANT_NAME}/$PLANT_NAME/gI" \
/root/sources/source1.txt >
/root/parameters/Output.txt`
param1.txt:
PLANT_NAME=abc
DB_NAME=gef
source1.txt:
kdashkdhkasdkj {PLANT_NAME}
jhdbjhasdjdhas kashdkahdk asdkhakdshk
hfkahfkajdfk ljsadjalsdj {PLANT_NAME}
{DB_NAME}
I cannot comment since I don't have enough points.
But is it correct that this is what you're looking for:
How to reference a file for variables using Bash?
Your problem statement isn't very clear to me. Perhaps you can simplify your problem and desired state.
Don't understand why you try to source param1.txt.
You can try with this awk :
awk '
NR == FNR {
a[$1] = $2
next
}
{
for ( i = 1 ; i <= NF ; i++ ) {
b = $i
gsub ( "^{|}$" , "" , b )
if ( b in a )
sub ( "{" b "}" , a[b] , $i )
}
} 1' FS='=' param1.txt FS=" " source1.txt

Assistance in understanding sqr logic

Hello, I am new to learning how to develop sqr programs within PeopleSoft. I've been going through some programs we are utilizing and wanted to see if someone could help provide clarification with what the below snippet of code is doing in this While loop.
if $path != ''
let $Archive_File = $path || 'ARCHIVE\' || $filename || $Curr_Date || '.dat'
open $Out_File as 1 for-reading record=450:vary status=#fileread
open $Archive_File as 2 for-writing record=450:vary status=#filewrite
While 1
if #END-FILE
break
else
read 1 into $Current_Line:999
write 2 from $Current_Line
end-if
End-While
close 1
close 2
end-if
I'm trying to understand if the WHILE statement is evaluating the "$Out_File as 1" as the logical expression, or is 1 being evaluated as the value of the variable #END-FILE (As I understand this variable is set to either 0 or 1).
Its a true loop, it will go there until reach a BREAK.
In this case if #END-FILE is true, the loop will break.
In addition to the file name, the open command takes a number as a parameter which it uses as a handler for the file. In your example, two files are being opened.
The WHILE 1 statement doesn't have anything to do with file 1. Here 1 means true, instead of 0 for false. So 1 is always true, creating an endless loop unless something within the loop breaks out if it, which in this case is the BREAK command.
The #END-FILE variable contains FALSE when the file cursor is not at EOF, and a TRUE when the the file cursor is at EOF.
An alternative, which uses less lines of code and is easier to understand might look like this:
if $path != ''
let $Archive_File = $path || 'ARCHIVE\' || $filename || $Curr_Date || '.dat'
open $Out_File as 1 for-reading record=450:vary status=#fileread
open $Archive_File as 2 for-writing record=450:vary status=#filewrite
While Not #END-FILE
read 1 into $Current_Line:999
write 2 from $Current_Line
End-While
close 1
close 2
end-if

Can LLDB data formatters call methods?

I'm debugging a Qt application using LLDB. At a breakpoint I can write
(lldb) p myQString.toUtf8().data()
and see the string contained within myQString, as data() returns char*. I would like to be able to write
(lldb) p myQString
and get the same output. This didn't work for me:
(lldb) type summary add --summary-string "${var.toUtf8().data()}" QString
Is it possible to write a simple formatter like this, or do I need to know the internals of QString and write a python script?
Alternatively, is there another way I should be using LLDB to view QStrings this way?
The following does work.
First, register your summary command:
debugger.HandleCommand('type summary add -F set_sblldbbp.qstring_summary "QString"')
Here is an implementation
def make_string_from_pointer_with_offset(F,OFFS,L):
strval = 'u"'
try:
data_array = F.GetPointeeData(0, L).uint16
for X in range(OFFS, L):
V = data_array[X]
if V == 0:
break
strval += unichr(V)
except:
pass
strval = strval + '"'
return strval.encode('utf-8')
#qt5
def qstring_summary(value, unused):
try:
d = value.GetChildMemberWithName('d')
#have to divide by 2 (size of unsigned short = 2)
offset = d.GetChildMemberWithName('offset').GetValueAsUnsigned() / 2
size = get_max_size(value)
return make_string_from_pointer_with_offset(d, offset, size)
except:
print '?????????????????????????'
return value
def get_max_size(value):
_max_size_ = None
try:
debugger = value.GetTarget().GetDebugger()
_max_size_ = int(lldb.SBDebugger.GetInternalVariableValue('target.max-string-summary-length', debugger.GetInstanceName()).GetStringAtIndex(0))
except:
_max_size_ = 512
return _max_size_
It is expected that what you tried to do won't work. The summary strings feature does not allow calling expressions.
Calling expressions in a debugger is always interesting, in a data formatter more so (if you're in an IDE - say Xcode - formatters run automatically). Every time you stop somewhere, even if you just stepped over one line, all these little expressions would all automatically run over and over again, at a large performance cost - and this is not even taking into account the fact that your data might be in a funny state already and running expressions has the potential to alter it even more, making your debugging sessions trickier than needed.
If the above wall of text still hasn't discouraged you ( :-) ), you want to write a Python formatter, and use the SB API to run your expression. Your value is an SBValue object, which has access to an SBFrame and an SBTarget. The combination of these two allows you to run EvaluateExpression("blah") and get back another SBValue, probably a char* to which you can then ask GetSummary() to get your c-string back.
If, on the other hand, you are now persuaded that running expressions in formatters is suboptimal, the good news is that QString most certainly has to store its data pointer somewhere.. if you find out where that is, you can just write a formatter as ${var.member1.member2.member3.theDataPointer} and obtain the same result!
this is my trial-and-error adaptation of a UTF16 string interpretation lldb script I found online (I apologise that I don't remember the source - and that I can't credit the author)
Note that this is for Qt 4.3.2 and versions close to it - as the handling of the 'data' pointer has since changed between then and Qt 5.x
def QString_SummaryProvider(valobj, internal_dict):
data = valobj.GetChildMemberWithName('d')#.GetPointeeData()
strSize = data.GetChildMemberWithName('size').GetValueAsUnsigned()
newchar = -1
i = 0
s = u'"'
while newchar != 0:
# read next wchar character out of memory
data_val = data.GetChildMemberWithName('data').GetPointeeData(i, 1)
size = data_val.GetByteSize()
e = lldb.SBError()
if size == 1:
newchar = data_val.GetUnsignedInt8(e, 0) # utf-8
elif size == 2:
newchar = data_val.GetUnsignedInt16(e, 0) # utf-16
elif size == 4:
newchar = data_val.GetUnsignedInt32(e, 0) # utf-32
else:
s = s + '<unexpected char size - error parsing QString>'
break
if e.fail:
s = s + '<parse error:' + e.why() + '>'
break
i = i + 1
if i > strSize:
break
# add the character to our string 's'
# print "char2 = %s" % newchar
if newchar != 0:
s = s + unichr(newchar)
s = s + u'"'
return s.encode('utf-8')

Using Vim, how can I make CSS rules into one liners?

I would like to come up with a Vim substitution command to turn multi-line CSS rules, like this one:
#main {
padding: 0;
margin: 10px auto;
}
into compacted single-line rules, like so:
#main {padding:0;margin:10px auto;}
I have a ton of CSS rules that are taking up too many lines, and I cannot figure out the :%s/ commands to use.
Here's a one-liner:
:%s/{\_.\{-}}/\=substitute(submatch(0), '\n', '', 'g')/
\_. matches any character, including a newline, and \{-} is the non-greedy version of *, so {\_.\{-}} matches everything between a matching pair of curly braces, inclusive.
The \= allows you to substitute the result of a vim expression, which we here use to strip out all the newlines '\n' from the matched text (in submatch(0)) using the substitute() function.
The inverse (converting the one-line version to multi-line) can also be done as a one liner:
:%s/{\_.\{-}}/\=substitute(submatch(0), '[{;]', '\0\r', 'g')/
If you are at the beginning or end of the rule, V%J will join it into a single line:
Go to the opening (or closing) brace
Hit V to enter visual mode
Hit % to match the other brace, selecting the whole rule
Hit J to join the lines
Try something like this:
:%s/{\n/{/g
:%s/;\n/;/g
:%s/{\s+/{/g
:%s/;\s+/;/g
This removes the newlines after opening braces and semicolons ('{' and ';') and then removes the extra whitespace between the concatenated lines.
If you want to change the file, go for rampion's solution.
If you don't want (or can't) change the file, you can play with a custom folding as it permits to choose what and how to display the folded text. For instance:
" {rtp}/fold/css-fold.vim
" [-- local settings --] {{{1
setlocal foldexpr=CssFold(v:lnum)
setlocal foldtext=CssFoldText()
let b:width1 = 20
let b:width2 = 15
nnoremap <buffer> + :let b:width2+=1<cr><c-l>
nnoremap <buffer> - :let b:width2-=1<cr><c-l>
" [-- global definitions --] {{{1
if exists('*CssFold')
setlocal foldmethod=expr
" finish
endif
function! CssFold(lnum)
let cline = getline(a:lnum)
if cline =~ '{\s*$'
return 'a1'
elseif cline =~ '}\s*$'
return 's1'
else
return '='
endif
endfunction
function! s:Complete(txt, width)
let length = strlen(a:txt)
if length > a:width
return a:txt
endif
return a:txt . repeat(' ', a:width - length)
endfunction
function! CssFoldText()
let lnum = v:foldstart
let txt = s:Complete(getline(lnum), b:width1)
let lnum += 1
while lnum < v:foldend
let add = s:Complete(substitute(getline(lnum), '^\s*\(\S\+\)\s*:\s*\(.\{-}\)\s*;\s*$', '\1: \2;', ''), b:width2)
if add !~ '^\s*$'
let txt .= ' ' . add
endif
let lnum += 1
endwhile
return txt. '}'
endfunction
I leave the sorting of the fields as exercise. Hint: get all the lines between v:foldstart+1 and v:voldend in a List, sort the list, build the string, and that's all.
I won’t answer the question directly, but instead I suggest you to reconsider your needs. I think that your “bad” example is in fact the better one. It is more readable, easier to modify and reason about. Good indentation is very important not only when it comes to programming languages, but also in CSS and HTML.
You mention that CSS rules are “taking up too many lines”. If you are worried about file size, you should consider using CSS and JS minifiers like YUI Compressor instead of making the code less readable.
A convenient way of doing this transformation is to run the following
short command:
:g/{/,/}/j
Go to the first line of the file, and use the command gqG to run the whole file through the formatter. Assuming runs of nonempty lines should be collapsed in the whole file.

Resources